Compare commits

..

No commits in common. "fc8d335ea29f11fd8984df9cd67cde304fb5739a" and "c502694e59ba064e62011aa83d64e94bae4983c8" have entirely different histories.

670 changed files with 16676 additions and 20792 deletions

View File

@ -13,7 +13,7 @@ insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
max_line_length = 120 max_line_length = 120
[{.babelrc,package.json,.eslintrc.json,.prettierrc.json}] [{.babelrc,package.json}]
indent_size = 2 indent_size = 2
[docker/**.conf] [docker/**.conf]

View File

@ -1,3 +0,0 @@
/public
/node_modules
/vendor

View File

@ -1,17 +0,0 @@
{
"parser": "@babel/eslint-parser",
"extends": [ "plugin:editorconfig/all" ],
"plugins": [ "editorconfig" ],
"rules": {
"prefer-arrow-callback": "error",
"prefer-template": "error",
"no-var": "error",
"quotes": [
"error",
"single",
{
"avoidEscape": true
}
]
}
}

5
.gitignore vendored
View File

@ -26,10 +26,8 @@ _vimrc_local.vim
# Project files # Project files
/config/config.php /config/config.php
/config/lang/
/public/*.xml
/public/coverage
/test/coverage /test/coverage
/public/coverage
/coverage /coverage
/unittests.xml /unittests.xml
/resources/lang/*/*.mo /resources/lang/*/*.mo
@ -42,4 +40,3 @@ _vimrc_local.vim
/public/assets /public/assets
/package-lock.json /package-lock.json
/yarn-error.log /yarn-error.log
/.yarn-cache

View File

@ -12,7 +12,6 @@ variables:
DOCROOT: /var/www/ DOCROOT: /var/www/
stages: stages:
- prepare
- validate - validate
- build - build
- test - test
@ -21,90 +20,44 @@ stages:
- deploy-production - deploy-production
- stop - stop
.use_cache: &use_cache
cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- .yarn-cache/
- vendor/
# for jobs that depend on composer
.use_composer: &use_composer
<<: *use_cache
needs:
- composer install
before_script:
- composer install --no-ansi --no-progress
# for jobs that depend on yarn
.use_yarn: &use_yarn
<<: *use_cache
needs:
- yarn install
before_script:
- yarn install --check-frontend --cache-folder .yarn-cache
# #
# Preparation # Validation
# #
composer validate: check-style:
image: composer:latest image: composer:latest
stage: prepare stage: validate
before_script:
- composer --no-ansi global config --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
- composer --no-ansi global require slevomat/coding-standard squizlabs/php_codesniffer
- export PATH=$PATH:$COMPOSER_HOME/vendor/bin
script:
- phpcs -p --no-colors --basepath="$PWD"
check-editorconfig:
image: mstruebing/editorconfig-checker
stage: validate
script:
- ec -v
validate-composer:
image: composer:latest
stage: validate
script: script:
- composer --no-ansi validate --strict - composer --no-ansi validate --strict
composer install: validate-yarn:
<<: *use_cache
image: composer:latest
stage: prepare
needs:
- composer audit
- composer validate
script:
- composer install --no-ansi --no-progress
composer audit:
image: php:latest
stage: prepare
needs:
- composer validate
before_script:
- curl -Ls https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64.gz | gzip -d > /bin/symfony
- chmod +x /bin/symfony
script:
- symfony check:security --no-ansi
yarn-validate:
image: node:alpine image: node:alpine
stage: prepare stage: validate
before_script: before_script:
- yarn global add package-json-validator - yarn global add package-json-validator
- export PATH=$PATH:~/.yarn/bin - export PATH=$PATH:~/.yarn/bin
script: script:
- pjv - pjv
yarn install:
<<: *use_cache
image: node:alpine
stage: prepare
needs:
- yarn-validate
- yarn audit
script:
- yarn install --check-frontend --cache-folder .yarn-cache
yarn audit:
image: node:alpine
stage: prepare
needs:
- yarn-validate
script:
- yarn audit
generate-version: generate-version:
image: alpine image: alpine
stage: prepare stage: validate
artifacts: artifacts:
name: "${CI_JOB_NAME}_${CI_JOB_ID}_version" name: "${CI_JOB_NAME}_${CI_JOB_ID}_version"
expire_in: 1 day expire_in: 1 day
@ -117,44 +70,6 @@ generate-version:
- echo "${VERSION}" - echo "${VERSION}"
- echo -n "${VERSION}" > storage/app/VERSION - echo -n "${VERSION}" > storage/app/VERSION
#
# Validation
#
phpcs:
<<: *use_composer
image: composer:latest
stage: validate
script:
# tell phpcs the PHP version to check against
# we are using the min suppported version here
- ./vendor/bin/phpcs --config-set php_version 80100
- ./vendor/bin/phpcs -p --no-colors --basepath="$PWD"
phpstan:
<<: *use_composer
image: composer:latest
stage: validate
script:
- ./vendor/bin/phpstan --no-progress
yarn check:
<<: *use_yarn
image: node:alpine
stage: validate
script:
- yarn check
yarn lint:
<<: *use_yarn
image: node:alpine
stage: validate
script:
# Install git, so that tools can use .gitignore.
# Not done in before_script because of <<: *use_yarn.
- apk add --no-cache git
- yarn lint
# #
# Build # Build
# #
@ -172,24 +87,39 @@ build-image:
<<: *container_definition <<: *container_definition
stage: build stage: build
needs: needs:
- phpcs - check-editorconfig
- phpstan - check-style
- composer validate
- yarn check
- yarn lint
- generate-version - generate-version
- validate-composer
- validate-yarn
dependencies: dependencies:
- generate-version - generate-version
script: script:
- /kaniko/executor --context ${CI_PROJECT_DIR} - /kaniko/executor --context ${CI_PROJECT_DIR}
--dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile --dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile
--destination "${TEST_IMAGE}" --destination "${TEST_IMAGE}"
--cache=true
# #
# Test # Test
# #
audit-composer:
image: php:latest
stage: test
needs: [ ]
before_script:
- curl -Ls https://github.com/symfony/cli/releases/latest/download/symfony_linux_amd64.gz | gzip -d > /bin/symfony
- chmod +x /bin/symfony
script:
- symfony check:security --no-ansi
audit-yarn:
image: node:alpine
stage: test
needs: [ ]
script:
- yarn audit
test: test:
image: image:
name: ${TEST_IMAGE} name: ${TEST_IMAGE}
@ -218,7 +148,7 @@ test:
- ./bin/migrate - ./bin/migrate
script: script:
- >- - >-
php -d memory_limit=1024M -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit -vvv --colors=never php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit -vvv --colors=never
--coverage-text --coverage-html "${HOMEDIR}/coverage/" --coverage-text --coverage-html "${HOMEDIR}/coverage/"
--log-junit "${HOMEDIR}/unittests.xml" --log-junit "${HOMEDIR}/unittests.xml"
after_script: after_script:
@ -271,11 +201,7 @@ release-image:
- test - test
dependencies: [ ] dependencies: [ ]
script: script:
- echo -e "FROM ${TEST_IMAGE}" - echo -e "FROM ${TEST_IMAGE}" | /kaniko/executor --dockerfile /dev/stdin --destination "${RELEASE_IMAGE}"
| /kaniko/executor
--dockerfile /dev/stdin
--destination "${RELEASE_IMAGE}"
--cache=true
only: only:
- main - main
@ -292,8 +218,8 @@ build-release-file:
stage: release stage: release
needs: needs:
- build-image - build-image
- yarn audit - audit-yarn
- composer audit - audit-composer
- test - test
- dump-database - dump-database
- generate-assets - generate-assets
@ -348,7 +274,6 @@ deploy:
dependencies: *deploy_needs dependencies: *deploy_needs
environment: environment:
name: rsync-staging name: rsync-staging
deployment_tier: development
only: only:
- main - main
script: script:
@ -371,10 +296,7 @@ deploy:
- test - test
- build-image - build-image
before_script: before_script:
- &kubectl_deployment_script |- - &kubectl_deployment_script if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi
if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi
if [[ -n "${KUBE_CONTEXT}" ]]; then kubectl config use-context "${KUBE_CONTEXT}"; fi
if [[ -z "${KUBE_NAMESPACE}" ]]; then export KUBE_NAMESPACE=${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}; fi
.deploy_k8s: &deploy_k8s .deploy_k8s: &deploy_k8s
<<: *kubectl_deployment <<: *kubectl_deployment
@ -389,12 +311,8 @@ deploy:
# CI_ENVIRONMENT_URL is the URL configured in the GitLab environment # CI_ENVIRONMENT_URL is the URL configured in the GitLab environment
- export CI_ENVIRONMENT_URL="${CI_ENVIRONMENT_URL:-https://${CI_PROJECT_PATH_SLUG}.${KUBE_INGRESS_BASE_DOMAIN}/}" - export CI_ENVIRONMENT_URL="${CI_ENVIRONMENT_URL:-https://${CI_PROJECT_PATH_SLUG}.${KUBE_INGRESS_BASE_DOMAIN}/}"
- export CI_IMAGE=$RELEASE_IMAGE - export CI_IMAGE=$RELEASE_IMAGE
- export CI_INGRESS_CLASS=${CI_INGRESS_CLASS:-traefik}
- export CI_INGRESS_MATCH=${CI_INGRESS_MATCH:-$( if [[ "$CI_INGRESS_CLASS" == "nginx" ]]; then echo '/?(.*)'; fi )}
- export CI_INGRESS_TRAEFIK_ENTRYPOINT=${CI_INGRESS_TRAEFIK_ENTRYPOINT:-websecure}
- export CI_INGRESS_DOMAIN=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?\K([^/]+)' | head -n1) - export CI_INGRESS_DOMAIN=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?\K([^/]+)' | head -n1)
- export CI_INGRESS_PATH=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?(?:[^/])+\K(.*)') - export CI_INGRESS_PATH=$(echo "$CI_ENVIRONMENT_URL" | grep -oP '(?:https?://)?(?:[^/])+\K(.*)')
- '[[ "${CI_INGRESS_PATH}" == /* ]] || export CI_INGRESS_PATH="/${CI_INGRESS_PATH}"'
- export CI_KUBE_NAMESPACE=$KUBE_NAMESPACE - export CI_KUBE_NAMESPACE=$KUBE_NAMESPACE
# Any available storage class like default, local-path (if you know what you are doing ;), longhorn etc. # Any available storage class like default, local-path (if you know what you are doing ;), longhorn etc.
- export CI_PVC_SC=${CI_PVC_SC:-"${CI_PVC_SC_LOCAL:-local-path}"} - export CI_PVC_SC=${CI_PVC_SC:-"${CI_PVC_SC_LOCAL:-local-path}"}
@ -403,24 +321,19 @@ deploy:
- export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt} - export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt}
- export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD} - export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD}
- echo "Generating config"
- cp deployment.tpl.yaml deployment.yaml - cp deployment.tpl.yaml deployment.yaml
- >- - >-
for env in ${!CI_*}; do for env in ${!CI_*}; do
sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml; sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml;
done done
- echo "Checking namespace ${CI_KUBE_NAMESPACE}"
- kubectl get namespace "${CI_KUBE_NAMESPACE}" > /dev/null 2>&1 || kubectl create namespace "${CI_KUBE_NAMESPACE}"
- echo "Deploying to ${CI_ENVIRONMENT_URL}" - echo "Deploying to ${CI_ENVIRONMENT_URL}"
- kubectl -n "${CI_KUBE_NAMESPACE}" diff -f deployment.yaml || true - kubectl apply -f deployment.yaml
- kubectl -n "${CI_KUBE_NAMESPACE}" apply -f deployment.yaml
- >- - >-
kubectl -n "${CI_KUBE_NAMESPACE}" wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=database -l app=$CI_PROJECT_PATH_SLUG -l tier=database
- >- - >-
kubectl -n "${CI_KUBE_NAMESPACE}" wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m kubectl -n $CI_KUBE_NAMESPACE wait --for=condition=Ready pods --timeout=${CI_WAIT_TIMEOUT:-5}m
-l app=$CI_PROJECT_PATH_SLUG -l tier=application -l commit=$CI_COMMIT_SHORT_SHA -l app=$CI_PROJECT_PATH_SLUG -l tier=application -l commit=$CI_COMMIT_SHORT_SHA
.deploy_k8s_stop: &deploy_k8s_stop .deploy_k8s_stop: &deploy_k8s_stop
@ -440,7 +353,6 @@ deploy-k8s-review:
on_stop: stop-k8s-review on_stop: stop-k8s-review
auto_stop_in: 1 week auto_stop_in: 1 week
url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG} url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG}
deployment_tier: development
variables: variables:
CI_REPLICAS_REVIEW: 1 CI_REPLICAS_REVIEW: 1
CI_APP_NAME: review/${CI_COMMIT_REF_NAME} CI_APP_NAME: review/${CI_COMMIT_REF_NAME}
@ -454,7 +366,6 @@ stop-k8s-review:
environment: environment:
name: review/${CI_COMMIT_REF_NAME} name: review/${CI_COMMIT_REF_NAME}
action: stop action: stop
deployment_tier: development
# #
# Deploy production # Deploy production
@ -465,8 +376,8 @@ deploy-production:
stage: deploy-production stage: deploy-production
needs: needs:
- test - test
- yarn audit - audit-yarn
- composer audit - audit-composer
- build-image - build-image
- generate-assets - generate-assets
dependencies: dependencies:
@ -474,7 +385,6 @@ deploy-production:
- generate-assets - generate-assets
environment: environment:
name: rsync-production name: rsync-production
deployment_tier: production
when: manual when: manual
only: only:
- main - main
@ -494,8 +404,8 @@ deploy-k8s-production:
stage: deploy-production stage: deploy-production
needs: needs:
- release-image - release-image
- yarn audit - audit-yarn
- composer audit - audit-composer
environment: environment:
name: production name: production
on_stop: stop-k8s-production on_stop: stop-k8s-production

View File

@ -4,11 +4,9 @@
<file>config</file> <file>config</file>
<file>db</file> <file>db</file>
<file>includes</file>
<file>public/index.php</file> <file>public/index.php</file>
<file>src</file> <file>src</file>
<file>tests</file> <file>tests</file>
<exclude-pattern>/config/config.php</exclude-pattern>
<rule ref="PSR12" /> <rule ref="PSR12" />
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses"> <rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
@ -21,32 +19,4 @@
<property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" /> <property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" />
</properties> </properties>
</rule> </rule>
<rule ref="Generic.Files.LineLength.TooLong">
<exclude-pattern>/includes</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
<exclude-pattern>/includes</exclude-pattern>
<exclude name="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingTraversableTypeHintSpecification" />
</rule>
<rule ref="SlevomatCodingStandard.Classes.RequireConstructorPropertyPromotion" />
<rule ref="SlevomatCodingStandard.Commenting.EmptyComment" />
<rule ref="SlevomatCodingStandard.Commenting.UselessFunctionDocComment" />
<rule ref="Generic.Formatting.SpaceAfterCast" />
<rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma"/>
<rule ref="SlevomatCodingStandard.Arrays.SingleLineArrayWhitespace"/>
<rule ref="Squiz.Strings.DoubleQuoteUsage" />
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
<exclude-pattern>/includes</exclude-pattern>
<properties>
<property name="spacesCountAroundEqualsSign" value="0" />
</properties>
</rule>
</ruleset> </ruleset>

View File

@ -1,5 +0,0 @@
{
"printWidth": 120,
"tabWidth": 2,
"singleQuote": true
}

View File

@ -2,30 +2,12 @@
## Coding guide lines ## Coding guide lines
* Make sure your code follows the [PSR-12](https://www.php-fig.org/psr/psr-12/) code style and is [.editorconfig](.editorconfig) valid. * Make sure your code follows the [PSR-12](https://www.php-fig.org/psr/psr-12/) code style and is [.editorconfig](.editorconfig) valid.
You may use `composer run phpcs` and [Editorconfig-Checker](https://editorconfig-checker.github.io) to verify that. You may use `composer run phpcs` and [Editorconfig-Checker](https://editorconfig-checker.github.io) to verify that.
* You should use an [editorconfig plugin for your editor](https://editorconfig.org/#pre-installed) for automatic basic code formatting.
* Use `use` statements wherever possible instead of writing the fully qualified name. * Use `use` statements wherever possible instead of writing the fully qualified name.
* Code must pass PHPStan checks (`composer phpstan`)
* Order the composer/npm dependencies alphabetically. * Order the composer/npm dependencies alphabetically.
* Do not use code from the [includes](includes) directory anywhere else. * Do not use code from the [includes](./includes) directory anywhere else.
* Don't refactor [includes](includes) code just for the sake of change, it is legacy code that must only be replaced. * Please cover your code by unit tests. Code under `includes` does not require tests.
* Please cover your code by unit tests, our goal is to stay at 100% line coverage.
Code under `includes` does not require tests as it's mostly not testable and needs to be rewritten.
* Do not use vendor prefixes like `-webkit` in styles. * Do not use vendor prefixes like `-webkit` in styles.
This is done by PostCSS + Autoprefixer according to the [`.browserslistrc`](.browserslistrc). This is done by PostCSS + Autoprefixer according to the [`.browserslistrc`](./.browserslistrc).
* Translations must be abbreviated, for example `form.save`.
The `default.po` files contain translations that can be auto-detected using Poedit, `additional.po` contains generated messages like validations.
* JavaScript code must pass the checks `yarn lint`.
Auto-fixing is supported via `yarn lint:fix`.
* Don't put function calls in a template-literal (template-strings).
## Pull requests ## Pull requests
* The PR should contain a short overview of the changes. Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite.
* Before implementing bigger changes, please open an issue to discuss the feature and possible implementation options.
* Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite.
* Squash similar commits to make the review easier.
* For visual changes, include both before and after screenshots to easily compare and discuss changes.
## Commits
* The commit message must be meaningful. It should serve as a short overview of the changes.
If needed, an additional description can be provided.
* A commit should be self-contained and result in a working Engelsystem.

View File

@ -8,86 +8,7 @@ Please also read the [CONTRIBUTING.md](CONTRIBUTING.md).
* Yarn (Development/Building only) * Yarn (Development/Building only)
* PHP Composer (Development/Building only) * PHP Composer (Development/Building only)
## Code style ## Local build
Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.org/psr/psr-12/) coding style guide.
You can check that by running
```bash
composer run phpcs
```
You may auto fix reported issues by running
```bash
composer run phpcbf
```
## Pre-commit hooks
You should set up the pre-commit hook to check the code style and run tests on commit:
Docker (recommended):
```sh
echo "docker exec engelsystem_dev-es_workspace-1 bin/pre-commit" > .git/hooks/pre-commit
chmod u+x .git/hooks/pre-commit
```
Host machine:
```sh
ln -s ../../bin/pre-commit .git/hooks/pre-commit
```
## Docker
We suggest using Docker for the Development local build.
If unspecific issues appear try using Docker version >= 20.10.14.
This repo [ships a docker setup](docker/dev) for a quick development start.
If you use another uid/gid than 1000 on your machine you have to adjust it in [docker/dev/.env](docker/dev/.env).
Run this once
```bash
cd docker/dev
docker compose up
```
Run these commands once initially and then as required after changes
```bash
# Install composer dependencies
docker compose exec es_workspace composer i
# Install node packages
docker compose exec es_workspace yarn install
# Run a full front-end build
docker compose exec es_workspace yarn build
# Or run a front-end build for specific themes only, e.g.
docker compose exec -e THEMES=0,1 es_workspace yarn build
# Update the translation files
docker compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
# Run the migrations
docker compose exec es_workspace bin/migrate
```
While developing you may use the watch mode to rebuild the system on changes
```bash
# Run a front-end build and update on change
docker compose exec es_workspace yarn build:watch
# Or run a front-end build and update on change for specific themes only, e.g.
docker compose exec -e THEMES=0,1 es_workspace yarn build:watch
```
## Localhost
You can find your local Engelsystem on [http://localhost:5080](http://localhost:5080).
## Local build without Docker
The following instructions explain how to get, build and run the latest Engelsystem version directly from the git main branch (may be unstable!). The following instructions explain how to get, build and run the latest Engelsystem version directly from the git main branch (may be unstable!).
* Clone the main branch: `git clone https://github.com/engelsystem/engelsystem.git` * Clone the main branch: `git clone https://github.com/engelsystem/engelsystem.git`
@ -118,7 +39,7 @@ The following instructions explain how to get, build and run the latest Engelsys
``` ```
## Testing ## Testing
To run only unit tests (tests that should not change the Engelsystem state) use To run the unit tests use
```bash ```bash
vendor/bin/phpunit --testsuite Unit vendor/bin/phpunit --testsuite Unit
``` ```
@ -127,34 +48,19 @@ If a database is configured and the Engelsystem is allowed to mess around with s
The tests can potentially delete some database entries, so they should never be run on a production system! The tests can potentially delete some database entries, so they should never be run on a production system!
```bash ```bash
vendor/bin/phpunit --testsuite Feature vendor/bin/phpunit --testsuite Feature
``` # or for unit- and feature tests:
When you want to run unit and feature tests at once:
```bash
vendor/bin/phpunit vendor/bin/phpunit
``` ```
To generate code coverage reports it's highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or To run code coverage reports its highly recommended to use [`pcov`](https://github.com/krakjoe/pcov) or
at least `phpdbg -qrr`(which has problems with switch case statements) as using Xdebug slows down execution. at least `phpdbg -qrr`(which has problems with switch case statements) as using Xdebug slows down execution.
```bash ```bash
php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit --coverage-text php -d pcov.enabled=1 -d pcov.directory=. vendor/bin/phpunit --testsuite Unit --coverage-text
``` ```
For better debug output, adding `-vvv` might be helpful.
Adding `--coverage-html public/coverage/` exports the coverage reports to the `public/` dir which then can be viewed at [localhost:5080/coverage/index.html](http://localhost:5080/coverage/index.html).
### Docker
If using the Docker-based development environment you can run the following script to retrieve a coverage report.
```sh
docker compose exec es_workspace composer phpunit:coverage
```
A browsable HTML version is available at http://localhost:5080/coverage/index.html .
### Var Dump server ### Var Dump server
Symfony Var Dump server is configured to allow for easier debugging. It is not meant as a replacement for xdebug but can actually be used together with xdebug. Symfony Var Dump server is configured to allow for easier debugging. It is not meant as a replacement for xdebug but can actually be used together with xdebug.
The Var Dump Server is especially useful if you want to debug a request without messing up the output e.g. of API calls or the HTML layout. This Var Dump Server is especially useful for when you want to debug a request without messing up the output e.g API calls ot HTML layout.
To use simply call the method `dump` and pass the arguments in exactly the same way you would when using `var_dump`. To use simply call the method `dump` and pass the arguments in exactly the same way you would when using `var_dump`.
@ -168,7 +74,7 @@ To view the output of `dump` call the following commands:
```bash ```bash
vendor/bin/var-dump-server vendor/bin/var-dump-server
# or for running in docker # or for running in docker
docker compose exec es_server vendor/bin/var-dump-server docker-compose exec es_server vendor/bin/var-dump-server
``` ```
For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper) For more information check out the Var Dump Server documentation: [Symfony VarDumper](https://symfony.com/components/VarDumper)
@ -177,6 +83,16 @@ For more information check out the Var Dump Server documentation: [Symfony VarDu
We use gettext. You may use POEdit to extract new texts from the sourcecode. We use gettext. You may use POEdit to extract new texts from the sourcecode.
Please config POEdit to extract also the twig template files using the following settings: https://gist.github.com/jlambe/a868d9b63d70902a12254ce47069d0e6 Please config POEdit to extract also the twig template files using the following settings: https://gist.github.com/jlambe/a868d9b63d70902a12254ce47069d0e6
## Code style
Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.org/psr/psr-12/) coding style guide.
You can check that by running
```bash
composer run phpcs
```
You may auto fix reported issues by running
```bash
composer run phpcbf
```
## CI & Build Pipeline ## CI & Build Pipeline
@ -192,12 +108,51 @@ PRODUCTION_REMOTE # Same as STAGING_REMOTE but for the production environm
PRODUCTION_REMOTE_PATH # Same as STAGING_REMOTE_PATH but for the production environment PRODUCTION_REMOTE_PATH # Same as STAGING_REMOTE_PATH but for the production environment
``` ```
## Static code analysis ## Docker
You can run a static code analysis with this command: If unspecific issues appear try using Docker version >= 20.10.14.
This repo [ships a docker setup](docker/dev) for a quick development start.
If you use another uid/gid than 1000 on your machine you have to adjust it in [docker/dev/.env](docker/dev/.env).
Run this once
```bash ```bash
composer phpstan cd docker/dev
docker-compose up
```
Run these commands once initially and then as required after changes
```bash
# Install composer dependencies
docker-compose exec es_workspace composer i
# Install node packages
docker-compose exec es_workspace yarn install
# Run a full front-end build
docker-compose exec es_workspace yarn build
# Or run a front-end build for specific themes only, e.g.
docker-compose exec -e THEMES=0,1 es_workspace yarn build
# Update the translation files
docker-compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
# Run the migrations
docker-compose exec es_workspace bin/migrate
```
While developing you may use the watch mode to rebuild the system on changes
```bash
# Run a front-end build and update on change
docker-compose exec es_workspace yarn build:watch
# Or run a front-end build and update on change for specific themes only, e.g.
docker-compose exec -e THEMES=0,1 es_workspace yarn build:watch
``` ```
**Hint for using Xdebug with *PhpStorm*** **Hint for using Xdebug with *PhpStorm***

View File

@ -15,7 +15,7 @@ Please read the [CONTRIBUTING.md](CONTRIBUTING.md) and [DEVELOPMENT.md](DEVELOPM
The Engelsystem may be installed manually or by using the provided [docker setup](#docker). The Engelsystem may be installed manually or by using the provided [docker setup](#docker).
### Requirements ### Requirements
* PHP >= 8.1 * PHP >= 7.4
* Required modules: * Required modules:
* dom * dom
* json * json
@ -33,16 +33,16 @@ The Engelsystem may be installed manually or by using the provided [docker setup
* Extract the files to your webroot and continue with the directions for configurations and setup. * Extract the files to your webroot and continue with the directions for configurations and setup.
### Configuration and Setup ### Configuration and Setup
* The webserver must have write access to the `storage` directory and read access for all other directories * The webserver must have write access to the ```storage``` directory and read access for all other directories
* The webserver must point to the `public` directory. * The webserver must point to the ```public``` directory.
* The webserver must read the `.htaccess` file and `mod_rewrite` must be enabled * The webserver must read the ```.htaccess``` file and ```mod_rewrite``` must be enabled
* Recommended: Directory Listing should be disabled. * Recommended: Directory Listing should be disabled.
* There must be a MySQL database set up with a user who has full rights to that database. * There must be a MySQL database set up with a user who has full rights to that database.
* If necessary, create a `config/config.php` to override values from `config/config.default.php`. * If necessary, create a ```config/config.php``` to override values from ```config/config.default.php```.
* To edit values from the `footer_items`, `themes`, `locales`, `tshirt_sizes` or `headers` lists, directly modify the `config/config.default.php` file or rename it to `config/config.php`. * To edit values from the `footer_items`, `themes`, `locales`, `tshirt_sizes` or `headers` lists, directly modify the ```config/config.default.php``` file or rename it to ```config/config.php```.
* To import the database, the `bin/migrate` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip. * To import the database, the ```bin/migrate``` script has to be run. If you can't execute scripts, you can use the `initial-install.sql` file from the release zip.
* In the browser, login with credentials `admin` : `asdfasdf` and change the password. * In the browser, login with credentials ```admin``` : ```asdfasdf``` and change the password.
The Engelsystem can now be used. The Engelsystem can now be used.
@ -55,7 +55,7 @@ The Engelsystem can now be used.
To build the `es_server` container: To build the `es_server` container:
```bash ```bash
cd docker cd docker
docker compose build docker-compose build
``` ```
or to build the container by its own: or to build the container by its own:
@ -67,14 +67,14 @@ docker build -f docker/Dockerfile . -t es_server
Start the Engelsystem Start the Engelsystem
```bash ```bash
cd docker cd docker
docker compose up -d docker-compose up -d
``` ```
#### Migrate #### Migrate
Import database changes to migrate it to the newest version Import database changes to migrate it to the newest version
```bash ```bash
cd docker cd docker
docker compose exec es_server bin/migrate docker-compose exec es_server bin/migrate
``` ```
### Scripts ### Scripts

View File

@ -4,9 +4,7 @@
use Composer\Autoload\ClassLoader; use Composer\Autoload\ClassLoader;
use Engelsystem\Application; use Engelsystem\Application;
use Engelsystem\Database\Migration\Migrate; use Engelsystem\Database\Migration\Migrate;
use Engelsystem\Database\Migration\Direction;
use Engelsystem\Database\Migration\MigrationServiceProvider; use Engelsystem\Database\Migration\MigrationServiceProvider;
use Engelsystem\Environment;
use Engelsystem\Exceptions\Handler; use Engelsystem\Exceptions\Handler;
use Engelsystem\Exceptions\Handlers\NullHandler; use Engelsystem\Exceptions\Handlers\NullHandler;
@ -21,7 +19,7 @@ $app->register(MigrationServiceProvider::class);
/** @var Handler $errorHandler */ /** @var Handler $errorHandler */
$errorHandler = $app->get(Handler::class); $errorHandler = $app->get(Handler::class);
$errorHandler->setHandler(Environment::PRODUCTION, new NullHandler()); $errorHandler->setHandler(Handler::ENV_PRODUCTION, new NullHandler());
/** @var Migrate $migration */ /** @var Migrate $migration */
$migration = $app->get('db.migration'); $migration = $app->get('db.migration');
@ -34,10 +32,10 @@ if (in_array('help', $argv) || in_array('--help', $argv) || in_array('-h', $argv
exit; exit;
} }
$direction = Direction::UP; $method = Migrate::UP;
if (in_array('down', $argv)) { if (in_array('down', $argv)) {
$argv = array_values($argv); $argv = array_values($argv);
$direction = Direction::DOWN; $method = Migrate::DOWN;
} }
$oneStep = false; $oneStep = false;
@ -50,4 +48,4 @@ if (in_array('force', $argv) || in_array('--force', $argv) || in_array('-f', $ar
$force = true; $force = true;
} }
$migration->run($baseDir, $direction, $oneStep, $force); $migration->run($baseDir, $method, $oneStep, $force);

View File

@ -1,12 +0,0 @@
#!/usr/bin/env sh
# immediate exit after an error
set -e
yarn check
yarn lint
composer validate
composer phpcs
composer phpstan
./vendor/bin/phpunit

View File

@ -14,59 +14,47 @@
} }
], ],
"scripts": { "scripts": {
"phpcs:setup": "phpcs --config-set php_version 80100", "phpcs": "phpcs -p",
"phpcs": [ "phpcbf": "phpcbf -p"
"composer phpcs:setup",
"phpcs -p --cache"
],
"phpcbf": [
"composer phpcs:setup",
"phpcbf -p"
],
"phpstan": "phpstan",
"phpunit": "phpunit",
"phpunit:coverage": "phpunit --coverage-text --coverage-html ./public/coverage/"
}, },
"require": { "require": {
"php": ">=8.1.0", "php": ">=7.4.0",
"ext-json": "*", "ext-json": "*",
"ext-libxml": "*", "ext-libxml": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-xml": "*", "ext-xml": "*",
"doctrine/dbal": "^3.5", "doctrine/dbal": "^3.2",
"erusev/parsedown": "^1.7", "erusev/parsedown": "^1.7",
"gettext/gettext": "^5.7", "gettext/gettext": "^5.6",
"gettext/translator": "^1.1", "gettext/translator": "^1.0",
"guzzlehttp/guzzle": "^7.5", "guzzlehttp/guzzle": "^7.4",
"illuminate/container": "^9.43", "illuminate/container": "^8.76",
"illuminate/database": "^9.43", "illuminate/database": "^8.76",
"illuminate/support": "^9.43", "illuminate/support": "^8.76",
"league/oauth2-client": "^2.6", "league/oauth2-client": "^2.6",
"nikic/fast-route": "^1.3", "nikic/fast-route": "^1.3",
"nyholm/psr7": "^1.5", "nyholm/psr7": "^1.4",
"psr/container": "^2.0", "psr/container": "^1.1",
"psr/http-server-middleware": "^1.0", "psr/http-server-middleware": "^1.0",
"psr/log": "^3.0", "psr/log": "^1.1",
"rcrowe/twigbridge": "^0.14.0", "rcrowe/twigbridge": "^0.14.0",
"respect/validation": "^1.1", "respect/validation": "^1.1",
"symfony/http-foundation": "^6.2", "symfony/http-foundation": "^5.4",
"symfony/mailer": "^6.2", "symfony/mailer": "^5.4",
"symfony/psr-http-message-bridge": "^2.1", "symfony/psr-http-message-bridge": "^2.1",
"twig/twig": "^3.4", "twig/twig": "^3.3",
"vlucas/phpdotenv": "^5.5" "vlucas/phpdotenv": "^5.4"
}, },
"require-dev": { "require-dev": {
"dms/phpunit-arraysubset-asserts": "^0.4", "dms/phpunit-arraysubset-asserts": "^0.3.1",
"fakerphp/faker": "^1.20", "fakerphp/faker": "^1.17",
"fig/log-test": "^1.1",
"filp/whoops": "^2.14", "filp/whoops": "^2.14",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5",
"slevomat/coding-standard": "^8.6", "slevomat/coding-standard": "^7.1",
"squizlabs/php_codesniffer": "^3.7", "squizlabs/php_codesniffer": "^3.6",
"symfony/var-dumper": "^6.2" "symfony/var-dumper": "^5.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

2250
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
// Application config // Application config
return [ return [
@ -48,7 +46,6 @@ return [
// Changes of request/response parameters // Changes of request/response parameters
\Engelsystem\Middleware\SetLocale::class, \Engelsystem\Middleware\SetLocale::class,
\Engelsystem\Middleware\ETagHandler::class,
\Engelsystem\Middleware\AddHeaders::class, \Engelsystem\Middleware\AddHeaders::class,
// The application code // The application code
@ -67,19 +64,11 @@ return [
// a list of // a list of
// 'Class@method' or 'Class' (which uses @handle), // 'Class@method' or 'Class' (which uses @handle),
// ['Class', 'method'], // ['Class', 'method'],
// callable like [$instance, 'method'] or 'function' // callable like [$instance, 'method] or 'function'
// or $function // or $function
// ] // ]
'message.created' => \Engelsystem\Events\Listener\Messages::class . '@created',
'news.created' => \Engelsystem\Events\Listener\News::class . '@created', 'news.created' => \Engelsystem\Events\Listener\News::class . '@created',
'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login', 'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login',
'shift.entry.deleting' => [
\Engelsystem\Events\Listener\Shift::class . '@deletedEntryCreateWorklog',
\Engelsystem\Events\Listener\Shift::class . '@deletedEntrySendEmail',
],
], ],
]; ];

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
// To change settings create a config.php // To change settings create a config.php
return [ return [
@ -13,19 +11,19 @@ return [
'password' => env('MYSQL_PASSWORD', ''), 'password' => env('MYSQL_PASSWORD', ''),
], ],
// For accessing /metrics (and /stats) // For accessing stats
'api_key' => env('API_KEY', ''), 'api_key' => '',
// Enable maintenance mode (show a static page) // Enable maintenance mode (show a static page)
'maintenance' => (bool) env('MAINTENANCE', false), 'maintenance' => (bool)env('MAINTENANCE', false),
// Application name (not the event name) // Application name (not the event name!)
'app_name' => env('APP_NAME', 'Engelsystem'), 'app_name' => env('APP_NAME', 'Engelsystem'),
// Set to development to enable debugging messages // Set to development to enable debugging messages
'environment' => env('ENVIRONMENT', 'production'), 'environment' => env('ENVIRONMENT', 'production'),
// Application URL and base path to use instead of the auto-detected one // Application URL and base path to use instead of the auto detected one
'url' => env('APP_URL', null), 'url' => env('APP_URL', null),
// Header links // Header links
@ -47,7 +45,7 @@ return [
'faq_text' => env('FAQ_TEXT', null), 'faq_text' => env('FAQ_TEXT', null),
// Link to documentation/help // Link to documentation/help
'documentation_url' => env('DOCUMENTATION_URL', 'https://engelsystem.de/doc/'), 'documentation_url' => 'https://engelsystem.de/doc/',
// Email config // Email config
'email' => [ 'email' => [
@ -69,7 +67,7 @@ return [
], ],
# Your privacy@ contact address # Your privacy@ contact address
'privacy_email' => env('PRIVACY_EMAIL', null), 'privacy_email' => '',
// Initial admin password // Initial admin password
'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null), 'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null),
@ -90,8 +88,6 @@ return [
'url_token' => '[generated by provider]', 'url_token' => '[generated by provider]',
// User info URL which provides userdata // User info URL which provides userdata
'url_info' => '[generated by provider]', 'url_info' => '[generated by provider]',
// OAuth Scopes
// 'scope' => ['openid'],
// Info unique user id field // Info unique user id field
'id' => 'uuid', 'id' => 'uuid',
// The following fields are used for registration // The following fields are used for registration
@ -218,17 +214,17 @@ return [
// Must be one of news, meetings, user_shifts, angeltypes, questions // Must be one of news, meetings, user_shifts, angeltypes, questions
'home_site' => env('HOME_SITE', 'news'), 'home_site' => env('HOME_SITE', 'news'),
// Number of News shown on one site and for feed readers (minimum 1) // Number of News shown on one site
'display_news' => env('DISPLAY_NEWS', 10), 'display_news' => env('DISPLAY_NEWS', 10),
// Users are able to sign up // Users are able to sign up
'registration_enabled' => (bool) env('REGISTRATION_ENABLED', true), 'registration_enabled' => (bool)env('REGISTRATION_ENABLED', true),
// Only arrived angels can sign up for shifts // Only arrived angels can sign up for shifts
'signup_requires_arrival' => (bool) env('SIGNUP_REQUIRES_ARRIVAL', false), 'signup_requires_arrival' => (bool)env('SIGNUP_REQUIRES_ARRIVAL', false),
// Whether newly-registered user should automatically be marked as arrived // Whether newly-registered user should automatically be marked as arrived
'autoarrive' => (bool) env('ANGEL_AUTOARRIVE', false), 'autoarrive' => (bool)env('ANGEL_AUTOARRIVE', false),
// Only allow shift signup this number of hours in advance // Only allow shift signup this number of hours in advance
// Setting this to 0 disables the feature // Setting this to 0 disables the feature
@ -250,7 +246,7 @@ return [
// Define the algorithm to use for `password_verify()` // Define the algorithm to use for `password_verify()`
// If the user uses an old algorithm the password will be converted to the new format // If the user uses an old algorithm the password will be converted to the new format
// See https://secure.php.net/manual/en/password.constants.php for a complete list // See https://secure.php.net/manual/en/password.constants.php for a complete list
'password_algorithm' => env('PASSWORD_ALGORITHM', PASSWORD_DEFAULT), 'password_algorithm' => PASSWORD_DEFAULT,
// The minimum length for passwords // The minimum length for passwords
'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8), 'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8),
@ -258,52 +254,38 @@ return [
// Whether the Password field should be enabled on registration. // Whether the Password field should be enabled on registration.
// This is useful when using oauth, disabling it also disables normal // This is useful when using oauth, disabling it also disables normal
// registration without oauth. // registration without oauth.
'enable_password' => (bool) env('ENABLE_PASSWORD', true), 'enable_password' => (bool)env('ENABLE_PASSWORD', true),
// Whether the DECT field should be enabled // Whether the DECT field should be enabled
'enable_dect' => (bool) env('ENABLE_DECT', true), 'enable_dect' => (bool)env('ENABLE_DECT', true),
// Whether the mobile number can be shown to other users // Enables prename and lastname
'enable_mobile_show' => (bool) env('ENABLE_MOBILE_SHOW', false), 'enable_user_name' => (bool)env('ENABLE_USER_NAME', false),
// Regular expression describing a FALSE username.
// Per default usernames must only contain alphanumeric chars, "-", "_" or ".".
'username_regex' => (string) env('USERNAME_REGEX', '/([^\p{L}\p{N}\-_.]+)/ui'),
// Enables first name and last name
'enable_user_name' => (bool) env('ENABLE_USER_NAME', false),
// Show a users first name and last name instead of username
'display_full_name' => env('DISPLAY_FULL_NAME', false)
&& env('ENABLE_USER_NAME', false),
// Enable displaying the pronoun fields // Enable displaying the pronoun fields
'enable_pronoun' => (bool) env('ENABLE_PRONOUN', true), 'enable_pronoun' => (bool)env('ENABLE_PRONOUN', true),
// Enables the planned arrival/leave date // Enables the planned arrival/leave date
'enable_planned_arrival' => (bool) env('ENABLE_PLANNED_ARRIVAL', true), 'enable_planned_arrival' => (bool)env('ENABLE_PLANNED_ARRIVAL', true),
// Resembles the Goodie Type. There are three options: // Enables the T-Shirt configuration on signup and profile
// 'none' => no goodie at all 'enable_tshirt_size' => (bool)env('ENABLE_TSHIRT_SIZE', true),
// 'goodie' => a goodie which has no sizing options
// 'tshirt' => goodie that is called tshirt and has sizing options // Enables the goody configuration on signup and profile
'goodie_type' => env('GOODIE_TYPE', 'goodie'), 'enable_goody' => (bool)env('ENABLE_GOODY', false),
// Enables the food voucher in the user profile // Enables the food voucher in the user profile
'enable_voucher' => (bool) env('ENABLE_VOUCHER', true), 'enable_voucher' => (bool)env('ENABLE_VOUCHER', true),
// Number of shifts to freeload until angel is locked for shift signup. // Number of shifts to freeload until angel is locked for shift signup.
'max_freeloadable_shifts' => env('MAX_FREELOADABLE_SHIFTS', 2), 'max_freeloadable_shifts' => env('MAX_FREELOADABLE_SHIFTS', 2),
// Hide columns in backend user view. Possible values are any sortable parameters of the table.
'disabled_user_view_columns' => [],
// Local timezone // Local timezone
'timezone' => env('TIMEZONE', 'Europe/Berlin'), 'timezone' => env('TIMEZONE', ini_get('date.timezone') ?: 'Europe/Berlin'),
// Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 6 exclusive) by 2 // Multiply 'night shifts' and freeloaded shifts (start or end between 2 and 6 exclusive) by 2
'night_shifts' => [ 'night_shifts' => [
'enabled' => (bool) env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same 'enabled' => (bool)env('NIGHT_SHIFTS', true), // Disable to weigh every shift the same
'start' => env('NIGHT_SHIFTS_START', 2), 'start' => env('NIGHT_SHIFTS_START', 2),
'end' => env('NIGHT_SHIFTS_END', 6), 'end' => env('NIGHT_SHIFTS_END', 6),
'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2), 'multiplier' => env('NIGHT_SHIFTS_MULTIPLIER', 2),
@ -360,16 +342,13 @@ return [
// Cookie name // Cookie name
'name' => env('SESSION_NAME', 'session'), 'name' => env('SESSION_NAME', 'session'),
// Lifetime in days
'lifetime' => env('SESSION_LIFETIME', 30),
], ],
// IP addresses of reverse proxies that are trusted, can be an array or a comma separated list // IP addresses of reverse proxies that are trusted, can be an array or a comma separated list
'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']), 'trusted_proxies' => env('TRUSTED_PROXIES', ['127.0.0.0/8', '::ffff:127.0.0.0/8', '::1/128']),
// Add additional headers // Add additional headers
'add_headers' => (bool) env('ADD_HEADERS', true), 'add_headers' => (bool)env('ADD_HEADERS', true),
'headers' => [ 'headers' => [
'X-Content-Type-Options' => 'nosniff', 'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'sameorigin', 'X-Frame-Options' => 'sameorigin',
@ -385,7 +364,7 @@ return [
'credits' => [ 'credits' => [
'Contribution' => 'Please visit [engelsystem/engelsystem](https://github.com/engelsystem/engelsystem) if ' 'Contribution' => 'Please visit [engelsystem/engelsystem](https://github.com/engelsystem/engelsystem) if '
. 'you want to contribute, have found any [bugs](https://github.com/engelsystem/engelsystem/issues) ' . 'you want to contribute, have found any [bugs](https://github.com/engelsystem/engelsystem/issues) '
. 'or need help.', . 'or need help.'
], ],
// var dump server // var dump server

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
use FastRoute\RouteCollector; use FastRoute\RouteCollector;
/** @var RouteCollector $route */ /** @var RouteCollector $route */
@ -17,195 +15,114 @@ $route->post('/login', 'AuthController@postLogin');
$route->get('/logout', 'AuthController@logout'); $route->get('/logout', 'AuthController@logout');
// OAuth // OAuth
$route->addGroup( $route->get('/oauth/{provider}', 'OAuthController@index');
'/oauth/{provider}', $route->post('/oauth/{provider}/connect', 'OAuthController@connect');
function (RouteCollector $route): void { $route->post('/oauth/{provider}/disconnect', 'OAuthController@disconnect');
$route->get('', 'OAuthController@index');
$route->post('/connect', 'OAuthController@connect');
$route->post('/disconnect', 'OAuthController@disconnect');
}
);
// User settings // User settings
$route->addGroup( $route->get('/settings/password', 'SettingsController@password');
'/settings', $route->post('/settings/password', 'SettingsController@savePassword');
function (RouteCollector $route): void { $route->get('/settings/theme', 'SettingsController@theme');
$route->get('/profile', 'SettingsController@profile'); $route->post('/settings/theme', 'SettingsController@saveTheme');
$route->post('/profile', 'SettingsController@saveProfile'); $route->get('/settings/language', 'SettingsController@language');
$route->get('/password', 'SettingsController@password'); $route->post('/settings/language', 'SettingsController@saveLanguage');
$route->post('/password', 'SettingsController@savePassword'); $route->get('/settings/oauth', 'SettingsController@oauth');
$route->get('/theme', 'SettingsController@theme');
$route->post('/theme', 'SettingsController@saveTheme');
$route->get('/language', 'SettingsController@language');
$route->post('/language', 'SettingsController@saveLanguage');
$route->get('/oauth', 'SettingsController@oauth');
}
);
// Password recovery // Password recovery
$route->addGroup( $route->get('/password/reset', 'PasswordResetController@reset');
'/password/reset', $route->post('/password/reset', 'PasswordResetController@postReset');
function (RouteCollector $route): void { $route->get('/password/reset/{token:.+}', 'PasswordResetController@resetPassword');
$route->get('', 'PasswordResetController@reset'); $route->post('/password/reset/{token:.+}', 'PasswordResetController@postResetPassword');
$route->post('', 'PasswordResetController@postReset');
$route->get('/{token:.+}', 'PasswordResetController@resetPassword');
$route->post('/{token:.+}', 'PasswordResetController@postResetPassword');
}
);
// Stats // Stats
$route->get('/metrics', 'Metrics\\Controller@metrics'); $route->get('/metrics', 'Metrics\\Controller@metrics');
$route->get('/stats', 'Metrics\\Controller@stats'); $route->get('/stats', 'Metrics\\Controller@stats');
// Angeltypes
$route->addGroup('/angeltypes', function (RouteCollector $route): void {
$route->get('/about', 'AngelTypesController@about');
});
// News // News
$route->get('/news', 'NewsController@index');
$route->get('/meetings', 'NewsController@meetings'); $route->get('/meetings', 'NewsController@meetings');
$route->addGroup( $route->get('/news/{id:\d+}', 'NewsController@show');
'/news', $route->post('/news/{id:\d+}', 'NewsController@comment');
function (RouteCollector $route): void { $route->post('/news/comment/{id:\d+}', 'NewsController@deleteComment');
$route->get('', 'NewsController@index');
$route->get('/{news_id:\d+}', 'NewsController@show');
$route->post('/{news_id:\d+}', 'NewsController@comment');
$route->post('/comment/{comment_id:\d+}', 'NewsController@deleteComment');
}
);
// FAQ // FAQ
$route->get('/faq', 'FaqController@index'); $route->get('/faq', 'FaqController@index');
// Questions // Questions
$route->addGroup( $route->get('/questions', 'QuestionsController@index');
'/questions', $route->post('/questions', 'QuestionsController@delete');
function (RouteCollector $route): void { $route->get('/questions/new', 'QuestionsController@add');
$route->get('', 'QuestionsController@index'); $route->post('/questions/new', 'QuestionsController@save');
$route->post('', 'QuestionsController@delete');
$route->get('/new', 'QuestionsController@add');
$route->post('/new', 'QuestionsController@save');
}
);
// Messages // Messages
$route->addGroup( $route->get('/messages', 'MessagesController@index');
'/messages', $route->post('/messages', 'MessagesController@redirectToConversation');
function (RouteCollector $route): void { $route->get('/messages/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->get('', 'MessagesController@index'); $route->post('/messages/{user_id:\d+}', 'MessagesController@send');
$route->post('', 'MessagesController@redirectToConversation'); $route->post('/messages/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
$route->get('/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->post('/{user_id:\d+}', 'MessagesController@send');
$route->post('/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
}
);
// API // API
$route->get('/api[/{resource:.+}]', 'ApiController@index'); $route->get('/api[/{resource:.+}]', 'ApiController@index');
// Feeds
$route->get('/atom', 'FeedController@atom');
$route->get('/ical', 'FeedController@ical');
$route->get('/rss', 'FeedController@rss');
$route->get('/shifts-json-export', 'FeedController@shifts');
// Design // Design
$route->get('/design', 'DesignController@index'); $route->get('/design', 'DesignController@index');
// Administration // Administration
$route->addGroup( $route->addGroup(
'/admin', '/admin',
function (RouteCollector $route): void { function (RouteCollector $route) {
// FAQ // FAQ
$route->addGroup( $route->addGroup(
'/faq', '/faq',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('[/{faq_id:\d+}]', 'Admin\\FaqController@edit'); $route->get('[/{id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{faq_id:\d+}]', 'Admin\\FaqController@save'); $route->post('[/{id:\d+}]', 'Admin\\FaqController@save');
} }
); );
// Log // Log
$route->addGroup( $route->get('/logs', 'Admin\\LogsController@index');
'/logs', $route->post('/logs', 'Admin\\LogsController@index');
function (RouteCollector $route): void {
$route->get('', 'Admin\\LogsController@index');
$route->post('', 'Admin\\LogsController@index');
}
);
// Schedule // Schedule
$route->addGroup( $route->addGroup(
'/schedule', '/schedule',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('', 'Admin\\Schedule\\ImportSchedule@index'); $route->get('', 'Admin\\Schedule\\ImportSchedule@index');
$route->get('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit'); $route->get('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit');
$route->post('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save'); $route->post('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save');
$route->get('/load/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule'); $route->get('/load/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule');
$route->post('/import/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule'); $route->post('/import/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule');
} }
); );
// Questions // Questions
$route->addGroup( $route->addGroup(
'/questions', '/questions',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('', 'Admin\\QuestionsController@index'); $route->get('', 'Admin\\QuestionsController@index');
$route->post('', 'Admin\\QuestionsController@delete'); $route->post('', 'Admin\\QuestionsController@delete');
$route->get('/{question_id:\d+}', 'Admin\\QuestionsController@edit'); $route->get('/{id:\d+}', 'Admin\\QuestionsController@edit');
$route->post('/{question_id:\d+}', 'Admin\\QuestionsController@save'); $route->post('/{id:\d+}', 'Admin\\QuestionsController@save');
}
);
// Rooms
$route->addGroup(
'/rooms',
function (RouteCollector $route): void {
$route->get('', 'Admin\\RoomsController@index');
$route->post('', 'Admin\\RoomsController@delete');
$route->get('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@edit');
$route->post('/edit[/{room_id:\d+}]', 'Admin\\RoomsController@save');
} }
); );
// User // User
$route->addGroup( $route->addGroup(
'/user/{user_id:\d+}', '/user/{id:\d+}',
function (RouteCollector $route): void {
// Shirts // Shirts
$route->addGroup( function (RouteCollector $route) {
'/goodie', $route->get('/shirt', 'Admin\\UserShirtController@editShirt');
function (RouteCollector $route): void { $route->post('/shirt', 'Admin\\UserShirtController@saveShirt');
$route->get('', 'Admin\\UserShirtController@editShirt');
$route->post('', 'Admin\\UserShirtController@saveShirt');
}
);
// Worklogs
$route->addGroup(
'/worklog',
function (RouteCollector $route): void {
$route->get('[/{worklog_id:\d+}]', 'Admin\\UserWorkLogController@editWorklog');
$route->post('[/{worklog_id:\d+}]', 'Admin\\UserWorkLogController@saveWorklog');
$route->get(
'/{worklog_id:\d+}/delete',
'Admin\\UserWorkLogController@showDeleteWorklog'
);
$route->post(
'/{worklog_id:\d+}/delete',
'Admin\\UserWorkLogController@deleteWorklog'
);
}
);
} }
); );
// News // News
$route->addGroup( $route->addGroup(
'/news', '/news',
function (RouteCollector $route): void { function (RouteCollector $route) {
$route->get('[/{news_id:\d+}]', 'Admin\\NewsController@edit'); $route->get('[/{id:\d+}]', 'Admin\\NewsController@edit');
$route->post('[/{news_id:\d+}]', 'Admin\\NewsController@save'); $route->post('[/{id:\d+}]', 'Admin\\NewsController@save');
} }
); );
} }

View File

@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\AngelType;
use Illuminate\Database\Eloquent\Factories\Factory;
class AngelTypeFactory extends Factory
{
/** @var string */
protected $model = AngelType::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->firstName(),
'description' => $this->faker->text(),
'contact_name' => $this->faker->firstName(),
'contact_dect' => $this->faker->randomNumber(4),
'contact_email' => $this->faker->email(),
'restricted' => $this->faker->boolean(),
'requires_driver_license' => $this->faker->boolean(),
'no_self_signup' => $this->faker->boolean(),
'show_on_dashboard' => $this->faker->boolean(),
'hide_register' => $this->faker->boolean(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Faq; use Engelsystem\Models\Faq;
@ -10,9 +8,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class FaqFactory extends Factory class FaqFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Faq::class; // phpcs:ignore protected $model = Faq::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'question' => $this->faker->text(100), 'question' => $this->faker->text(100),

View File

@ -1,21 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Group;
use Illuminate\Database\Eloquent\Factories\Factory;
class GroupFactory extends Factory
{
/** @var string */
protected $model = Group::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->word(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Message; use Engelsystem\Models\Message;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class MessageFactory extends Factory class MessageFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Message::class; // phpcs:ignore protected $model = Message::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -12,9 +10,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsCommentFactory extends Factory class NewsCommentFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = NewsComment::class; // phpcs:ignore protected $model = NewsComment::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'news_id' => News::factory(), 'news_id' => News::factory(),

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\News; use Engelsystem\Models\News;
@ -11,16 +9,18 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class NewsFactory extends Factory class NewsFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = News::class; // phpcs:ignore protected $model = News::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'title' => $this->faker->text(50), 'title' => $this->faker->text(50),
'text' => $this->faker->realText(), 'text' => $this->faker->realText(),
'is_meeting' => $this->faker->boolean(), 'is_meeting' => $this->faker->boolean(),
'is_pinned' => $this->faker->boolean(.1), 'is_pinned' => $this->faker->boolean(.1),
'is_important' => $this->faker->boolean(.1),
'user_id' => User::factory(), 'user_id' => User::factory(),
]; ];
} }

View File

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Privilege;
use Illuminate\Database\Eloquent\Factories\Factory;
class PrivilegeFactory extends Factory
{
/** @var string */
protected $model = Privilege::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->word(),
'description' => $this->faker->text(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Carbon\Carbon; use Carbon\Carbon;
@ -12,9 +10,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class QuestionFactory extends Factory class QuestionFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Question::class; // phpcs:ignore protected $model = Question::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Room; use Engelsystem\Models\Room;
@ -10,9 +8,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class RoomFactory extends Factory class RoomFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Room::class; // phpcs:ignore protected $model = Room::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->firstName(), 'name' => $this->faker->unique()->firstName(),

View File

@ -1,29 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Factories\Factory;
class NeededAngelTypeFactory extends Factory
{
/** @var string */
protected $model = NeededAngelType::class; // phpcs:ignore
public function definition(): array
{
$forRoom = $this->faker->boolean();
return [
'room_id' => $forRoom ? Room::factory() : null,
'shift_id' => $forRoom ? null : Shift::factory(),
'angel_type_id' => AngelType::factory(),
'count' => $this->faker->numberBetween(1, 5),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts; namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Shifts\Schedule; use Engelsystem\Models\Shifts\Schedule;
@ -10,12 +8,15 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class ScheduleFactory extends Factory class ScheduleFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Schedule::class; // phpcs:ignore protected $model = Schedule::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->words(4, true), 'name' => $this->faker->words(4, true),
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'), 'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
'shift_type' => $this->faker->numberBetween(1, 5), 'shift_type' => $this->faker->numberBetween(1, 5),
'minutes_before' => 15, 'minutes_before' => 15,

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftEntryFactory extends Factory
{
/** @var string */
protected $model = ShiftEntry::class; // phpcs:ignore
public function definition(): array
{
$freeloaded = $this->faker->optional(.01, false)->boolean();
return [
'shift_id' => Shift::factory(),
'angel_type_id' => AngelType::factory(),
'user_id' => User::factory(),
'user_comment' => $this->faker->optional(.05, '')->text(),
'freeloaded' => $freeloaded,
'freeloaded_comment' => $freeloaded ? $this->faker->text() : '',
];
}
}

View File

@ -1,34 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Room;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftType;
use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftFactory extends Factory
{
/** @var string */
protected $model = Shift::class; // phpcs:ignore
public function definition(): array
{
$start = $this->faker->dateTimeThisMonth('2 weeks');
return [
'title' => $this->faker->unique()->text(15),
'description' => $this->faker->text(),
'url' => $this->faker->url(),
'start' => $start,
'end' => $this->faker->dateTimeInInterval($start, '+3 hours'),
'shift_type_id' => ShiftType::factory(),
'room_id' => Room::factory(),
'transaction_id' => $this->faker->optional()->uuid(),
'created_by' => User::factory(),
'updated_by' => $this->faker->optional(.3)->boolean() ? User::factory() : null,
];
}
}

View File

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\Shifts\ShiftType;
use Illuminate\Database\Eloquent\Factories\Factory;
class ShiftTypeFactory extends Factory
{
/** @var string */
protected $model = ShiftType::class; // phpcs:ignore
public function definition(): array
{
return [
'name' => $this->faker->unique()->firstName(),
'description' => $this->faker->text(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Contact; use Engelsystem\Models\User\Contact;
@ -10,9 +8,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class ContactFactory extends Factory class ContactFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Contact::class; // phpcs:ignore protected $model = Contact::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'dect' => $this->faker->optional()->numberBetween(1000, 9999), 'dect' => $this->faker->optional()->numberBetween(1000, 9999),

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\License; use Engelsystem\Models\User\License;
@ -10,9 +8,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class LicenseFactory extends Factory class LicenseFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = License::class; // phpcs:ignore protected $model = License::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
$drive_car = $this->faker->boolean(.8); $drive_car = $this->faker->boolean(.8);
$drive_3_5t = $drive_car && $this->faker->boolean(.7); $drive_3_5t = $drive_car && $this->faker->boolean(.7);

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\PasswordReset; use Engelsystem\Models\User\PasswordReset;
@ -10,12 +8,15 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class PasswordResetFactory extends Factory class PasswordResetFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = PasswordReset::class; // phpcs:ignore protected $model = PasswordReset::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'token' => bin2hex(random_bytes(16)), 'token' => md5($this->faker->unique()->password()),
]; ];
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class PersonalDataFactory extends Factory class PersonalDataFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = PersonalData::class; // phpcs:ignore protected $model = PersonalData::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
$arrival = $this->faker->optional()->dateTimeThisMonth('2 weeks'); $arrival = $this->faker->optional()->dateTimeThisMonth('2 weeks');
$departure = $this->faker->optional()->dateTimeThisMonth('2 weeks'); $departure = $this->faker->optional()->dateTimeThisMonth('2 weeks');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\Settings;
@ -10,19 +8,20 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class SettingsFactory extends Factory class SettingsFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Settings::class; // phpcs:ignore protected $model = Settings::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'language' => $this->faker->locale(), 'language' => $this->faker->locale(),
'theme' => $this->faker->numberBetween(1, 20), 'theme' => $this->faker->numberBetween(1, 20),
'email_human' => $this->faker->boolean(), 'email_human' => $this->faker->boolean(),
'email_messages' => $this->faker->boolean(),
'email_goody' => $this->faker->boolean(), 'email_goody' => $this->faker->boolean(),
'email_shiftinfo' => $this->faker->boolean(), 'email_shiftinfo' => $this->faker->boolean(),
'email_news' => $this->faker->boolean(), 'email_news' => $this->faker->boolean(),
'mobile_show' => $this->faker->boolean(),
]; ];
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
@ -11,14 +9,17 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class StateFactory extends Factory class StateFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = State::class; // phpcs:ignore protected $model = State::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
$arrival = $this->faker->optional()->dateTimeThisMonth(); $arrival = $this->faker->optional()->dateTimeThisMonth();
return [ return [
'arrived' => (bool) $arrival, 'arrived' => (bool)$arrival,
'arrival_date' => $arrival ? Carbon::instance($arrival) : null, 'arrival_date' => $arrival ? Carbon::instance($arrival) : null,
'active' => $this->faker->boolean(.3), 'active' => $this->faker->boolean(.3),
'force_active' => $this->faker->boolean(.1), 'force_active' => $this->faker->boolean(.1),
@ -29,8 +30,10 @@ class StateFactory extends Factory
/** /**
* Indicate that the user is arrived * Indicate that the user is arrived
*
* @return self
*/ */
public function arrived(): self public function arrived()
{ {
return $this->state( return $this->state(
function (array $attributes) { function (array $attributes) {

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User; namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
@ -10,15 +8,18 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class UserFactory extends Factory class UserFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = User::class; // phpcs:ignore protected $model = User::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'name' => $this->faker->unique()->userName(), 'name' => $this->faker->unique()->userName(),
'password' => crypt(random_bytes(16), '$1$salt$'), 'password' => password_hash($this->faker->password(), PASSWORD_DEFAULT),
'email' => $this->faker->unique()->safeEmail(), 'email' => $this->faker->unique()->safeEmail(),
'api_key' => bin2hex(random_bytes(32)), 'api_key' => md5($this->faker->unique()->password()),
]; ];
} }
} }

View File

@ -1,26 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Illuminate\Database\Eloquent\Factories\Factory;
class UserAngelTypeFactory extends Factory
{
/** @var string */
protected $model = UserAngelType::class; // phpcs:ignore
public function definition(): array
{
return [
'user_id' => User::factory(),
'angel_type_id' => AngelType::factory(),
'confirm_user_id' => $this->faker->optional()->passthrough(User::factory()),
'supporter' => $this->faker->boolean(),
];
}
}

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models; namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\User\User; use Engelsystem\Models\User\User;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class WorklogFactory extends Factory class WorklogFactory extends Factory
{ {
/** @var string */ /** @var string */
protected $model = Worklog::class; // phpcs:ignore protected $model = Worklog::class;
public function definition(): array /**
* @return array
*/
public function definition()
{ {
return [ return [
'user_id' => User::factory(), 'user_id' => User::factory(),

View File

@ -1,15 +1,12 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
class ImportInstallSql extends Migration class ImportInstallSql extends Migration
{ {
/** @var array<string> */ protected $oldTables = [
protected array $oldTables = [
'AngelTypes', 'AngelTypes',
'EventConfig', 'EventConfig',
'GroupPrivileges', 'GroupPrivileges',
@ -34,7 +31,7 @@ class ImportInstallSql extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
foreach ($this->oldTables as $table) { foreach ($this->oldTables as $table) {
if ($this->schema->hasTable($table)) { if ($this->schema->hasTable($table)) {
@ -50,7 +47,7 @@ class ImportInstallSql extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;'); $this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class ImportUpdateSql extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if ($this->schema->hasTable('UserWorkLog')) { if ($this->schema->hasTable('UserWorkLog')) {
return; return;
@ -24,7 +22,7 @@ class ImportUpdateSql extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->dropIfExists('UserWorkLog'); $this->schema->dropIfExists('UserWorkLog');
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,7 +10,7 @@ class FixOldTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -31,9 +29,16 @@ class FixOldTables extends Migration
->where($column, '<', '0001-01-01 00:00:00') ->where($column, '<', '0001-01-01 00:00:00')
->update([$column => '0001-01-01 00:00:00']); ->update([$column => '0001-01-01 00:00:00']);
$this->schema->table($table, function (Blueprint $table) use ($column): void { $this->schema->table($table, function (Blueprint $table) use ($column) {
$table->dateTime($column)->default('0001-01-01 00:00:00')->change(); $table->dateTime($column)->default('0001-01-01 00:00:00')->change();
}); });
} }
} }
/**
* Reverse the migration
*/
public function down()
{
}
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -45,7 +43,7 @@ class CleanupGroupPrivileges extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -9,7 +7,7 @@ use Engelsystem\Database\Migration\Migration;
class AddAngelSupporterPermissions extends Migration class AddAngelSupporterPermissions extends Migration
{ {
/** @var string[] */ /** @var string[] */
protected array $data = [ protected $data = [
'2-Engel', '2-Engel',
'shiftentry_edit_angeltype_supporter', 'shiftentry_edit_angeltype_supporter',
]; ];
@ -17,7 +15,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -41,7 +39,7 @@ class AddAngelSupporterPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -54,7 +52,11 @@ class AddAngelSupporterPermissions extends Migration
); );
} }
private function getQuery(string $type): string /**
* @param string $type
* @return string
*/
protected function getQuery($type)
{ {
return sprintf(' return sprintf('
%s FROM GroupPrivileges %s FROM GroupPrivileges

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('log_entries', function (Blueprint $table): void { $this->schema->create('log_entries', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');
@ -34,9 +32,9 @@ class CreateLogEntriesTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->create('LogEntries', function (Blueprint $table): void { $this->schema->create('LogEntries', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('level', 20); $table->string('level', 20);
$table->text('message'); $table->text('message');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class CreateSessionsTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('sessions', function (Blueprint $table): void { $this->schema->create('sessions', function (Blueprint $table) {
$table->string('id')->unique(); $table->string('id')->unique();
$table->text('payload'); $table->text('payload');
$table->dateTime('last_activity')->useCurrent(); $table->dateTime('last_activity')->useCurrent();
@ -24,7 +22,7 @@ class CreateSessionsTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->dropIfExists('sessions'); $this->schema->dropIfExists('sessions');
} }

View File

@ -1,18 +1,16 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\EventConfig;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;
class CreateEventConfigTable extends Migration class CreateEventConfigTable extends Migration
{ {
protected array $mapping = [ protected $mapping = [
'buildup_start_date' => 'buildup_start', 'buildup_start_date' => 'buildup_start',
'event_start_date' => 'event_start', 'event_start_date' => 'event_start',
'event_end_date' => 'event_end', 'event_end_date' => 'event_end',
@ -22,11 +20,11 @@ class CreateEventConfigTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
foreach (['json', 'text'] as $type) { foreach (['json', 'text'] as $type) {
try { try {
$this->schema->create('event_config', function (Blueprint $table) use ($type): void { $this->schema->create('event_config', function (Blueprint $table) use ($type) {
$table->string('name')->index()->unique(); $table->string('name')->index()->unique();
$table->{$type}('value'); $table->{$type}('value');
$table->timestamps(); $table->timestamps();
@ -43,24 +41,26 @@ class CreateEventConfigTable extends Migration
} }
if ($this->schema->hasTable('EventConfig')) { if ($this->schema->hasTable('EventConfig')) {
$connection = $this->schema->getConnection(); $config = $this->schema->getConnection()
$config = $connection
->table('EventConfig') ->table('EventConfig')
->first(); ->first();
if (!empty($config)) { if (!empty($config)) {
$connection->table('event_config') (new EventConfig([
->insert([ 'name' => 'name',
['name' => 'name', 'value' => $config->event_name], 'value' => $config->event_name,
['name' => 'welcome_msg', 'value' => $config->event_welcome_msg], ]))->save();
]);
(new EventConfig([
'name' => 'welcome_msg',
'value' => $config->event_welcome_msg,
]))->save();
foreach ($this->mapping as $old => $new) { foreach ($this->mapping as $old => $new) {
$connection->table('event_config') (new EventConfig([
->insert([
'name' => $new, 'name' => $new,
'value' => (new Carbon())->setTimestamp($config->{$old}), 'value' => (new Carbon())->setTimestamp($config->{$old}),
]); ]))->save();
} }
} }
@ -71,11 +71,9 @@ class CreateEventConfigTable extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$connection = $this->schema->getConnection(); $this->schema->create('EventConfig', function (Blueprint $table) {
$this->schema->create('EventConfig', function (Blueprint $table): void {
$table->string('event_name')->nullable(); $table->string('event_name')->nullable();
$table->integer('buildup_start_date')->nullable(); $table->integer('buildup_start_date')->nullable();
$table->integer('event_start_date')->nullable(); $table->integer('event_start_date')->nullable();
@ -84,19 +82,19 @@ class CreateEventConfigTable extends Migration
$table->string('event_welcome_msg')->nullable(); $table->string('event_welcome_msg')->nullable();
}); });
$config = $connection->table('event_config')->get(); $config = new EventConfig();
$data = [ $data = [
'event_name' => $this->getConfigValue($config, 'name'), 'event_name' => $config->findOrNew('name')->value,
'event_welcome_msg' => $this->getConfigValue($config, 'welcome_msg'), 'event_welcome_msg' => $config->findOrNew('welcome_msg')->value,
]; ];
foreach ($this->mapping as $new => $old) { foreach ($this->mapping as $new => $old) {
$value = $this->getConfigValue($config, $old); /** @var Carbon $value */
$value = $config->findOrNew($old)->value;
if (!$value) { if (!$value) {
continue; continue;
} }
$value = Carbon::make($value);
$data[$new] = $value->getTimestamp(); $data[$new] = $value->getTimestamp();
} }
@ -113,11 +111,4 @@ class CreateEventConfigTable extends Migration
$this->schema->dropIfExists('event_config'); $this->schema->dropIfExists('event_config');
} }
private function getConfigValue(Collection $config, string $name): mixed
{
$value = $config->where('name', $name)->first('value', (object) ['value' => null])->value;
return $value ? json_decode($value, true) : null;
}
} }

View File

@ -1,11 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\User\Contact;
use Engelsystem\Models\User\PasswordReset;
use Engelsystem\Models\User\PersonalData;
use Engelsystem\Models\User\Settings;
use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -17,9 +21,9 @@ class CreateUsersTables extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('users', function (Blueprint $table): void { $this->schema->create('users', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('name', 24)->unique(); $table->string('name', 24)->unique();
@ -31,7 +35,7 @@ class CreateUsersTables extends Migration
$table->timestamps(); $table->timestamps();
}); });
$this->schema->create('users_personal_data', function (Blueprint $table): void { $this->schema->create('users_personal_data', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('first_name', 64)->nullable(); $table->string('first_name', 64)->nullable();
@ -42,7 +46,7 @@ class CreateUsersTables extends Migration
$table->date('planned_departure_date')->nullable(); $table->date('planned_departure_date')->nullable();
}); });
$this->schema->create('users_contact', function (Blueprint $table): void { $this->schema->create('users_contact', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('dect', 5)->nullable(); $table->string('dect', 5)->nullable();
@ -50,7 +54,7 @@ class CreateUsersTables extends Migration
$table->string('email', 254)->nullable(); $table->string('email', 254)->nullable();
}); });
$this->schema->create('users_settings', function (Blueprint $table): void { $this->schema->create('users_settings', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->string('language', 64); $table->string('language', 64);
@ -59,7 +63,7 @@ class CreateUsersTables extends Migration
$table->boolean('email_shiftinfo')->default(false); $table->boolean('email_shiftinfo')->default(false);
}); });
$this->schema->create('users_state', function (Blueprint $table): void { $this->schema->create('users_state', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('arrived')->default(false); $table->boolean('arrived')->default(false);
@ -70,7 +74,7 @@ class CreateUsersTables extends Migration
$table->integer('got_voucher')->default(0); $table->integer('got_voucher')->default(0);
}); });
$this->schema->create('password_resets', function (Blueprint $table): void { $this->schema->create('password_resets', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->text('token'); $table->text('token');
@ -79,33 +83,33 @@ class CreateUsersTables extends Migration
}); });
if ($this->schema->hasTable('User')) { if ($this->schema->hasTable('User')) {
$connection = $this->schema->getConnection();
$emptyDates = ['0000-00-00 00:00:00', '0001-01-01 00:00:00', '1000-01-01 00:00:00']; $emptyDates = ['0000-00-00 00:00:00', '0001-01-01 00:00:00', '1000-01-01 00:00:00'];
/** @var stdClass[] $users */ /** @var stdClass[] $users */
$users = $connection->table('User')->get(); $users = $this->schema->getConnection()->table('User')->get();
foreach ($users as $data) { foreach ($users as $data) {
$user = [ $user = new User([
'id' => $data->UID,
'name' => $data->Nick, 'name' => $data->Nick,
'password' => $data->Passwort, 'password' => $data->Passwort,
'email' => $data->email, 'email' => $data->email,
'api_key' => $data->api_key, 'api_key' => $data->api_key,
'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null, 'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null,
]; ]);
$user->setAttribute('id', $data->UID);
if (!in_array($data->CreateDate, $emptyDates)) { if (!in_array($data->CreateDate, $emptyDates)) {
$user['created_at'] = new Carbon($data->CreateDate); $user->setAttribute('created_at', new Carbon($data->CreateDate));
} }
$connection->table('users')->insert($user); $user->save();
$connection->table('users_contact')->insert([ $contact = new Contact([
'user_id' => $data->UID, 'dect' => $data->DECT ? $data->DECT : null,
'dect' => $data->DECT ?: null,
'mobile' => $data->Handy ?: ($data->Telefon ?: null), 'mobile' => $data->Handy ?: ($data->Telefon ?: null),
]); ]);
$contact->user()
->associate($user)
->save();
$connection->table('users_personal_data')->insert([ $personalData = new PersonalData([
'user_id' => $data->UID,
'first_name' => $data->Vorname ?: null, 'first_name' => $data->Vorname ?: null,
'last_name' => $data->Name ?: null, 'last_name' => $data->Name ?: null,
'shirt_size' => $data->Size ?: null, 'shirt_size' => $data->Size ?: null,
@ -116,17 +120,24 @@ class CreateUsersTables extends Migration
? Carbon::createFromTimestamp($data->planned_departure_date) ? Carbon::createFromTimestamp($data->planned_departure_date)
: null, : null,
]); ]);
$personalData->user()
->associate($user)
->save();
$connection->table('users_settings')->insert([ $settings = new Settings([
'user_id' => $data->UID,
'language' => $data->Sprache, 'language' => $data->Sprache,
'theme' => $data->color, 'theme' => $data->color,
'email_human' => $data->email_by_human_allowed, 'email_human' => $data->email_by_human_allowed,
'email_shiftinfo' => $data->email_shiftinfo, 'email_shiftinfo' => $data->email_shiftinfo,
]); ]);
unset($settings->email_news);
unset($settings->email_goody);
$connection->table('users_state')->insert([ $settings->user()
'user_id' => $data->UID, ->associate($user)
->save();
$state = new State([
'arrived' => $data->Gekommen, 'arrived' => $data->Gekommen,
'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null, 'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null,
'active' => $data->Aktiv, 'active' => $data->Aktiv,
@ -134,12 +145,17 @@ class CreateUsersTables extends Migration
'got_shirt' => $data->Tshirt, 'got_shirt' => $data->Tshirt,
'got_voucher' => $data->got_voucher, 'got_voucher' => $data->got_voucher,
]); ]);
$state->user()
->associate($user)
->save();
if ($data->password_recovery_token) { if ($data->password_recovery_token) {
$connection->table('password_resets')->insert([ $passwordReset = new PasswordReset([
'user_id' => $data->UID,
'token' => $data->password_recovery_token, 'token' => $data->password_recovery_token,
]); ]);
$passwordReset->user()
->associate($user)
->save();
} }
} }
@ -157,12 +173,10 @@ class CreateUsersTables extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$connection = $this->schema->getConnection(); $this->schema->create('User', function (Blueprint $table) {
$table->integer('UID', true, false);
$this->schema->create('User', function (Blueprint $table): void {
$table->integer('UID', true);
$table->string('Nick', 23)->unique()->default(''); $table->string('Nick', 23)->unique()->default('');
$table->string('Name', 23)->nullable(); $table->string('Name', 23)->nullable();
@ -203,16 +217,12 @@ class CreateUsersTables extends Migration
$table->index('planned_departure_date', 'planned_departure_date'); $table->index('planned_departure_date', 'planned_departure_date');
}); });
foreach ($connection->table('users')->get() as $user) { foreach (User::all() as $user) {
/** @var stdClass $user */ /** @var User $user */
/** @var stdClass $contact */ $contact = $user->contact;
$contact = $connection->table('users_contact')->where('user_id', $user->id)->first(); $personal = $user->personalData;
/** @var stdClass $personal */ $settings = $user->settings;
$personal = $connection->table('users_personal_data')->where('user_id', $user->id)->first(); $state = $user->state;
/** @var stdClass $settings */
$settings = $connection->table('users_settings')->where('user_id', $user->id)->first();
/** @var stdClass $state */
$state = $connection->table('users_state')->where('user_id', $user->id)->first();
$this->schema $this->schema
->getConnection() ->getConnection()
@ -234,28 +244,23 @@ class CreateUsersTables extends Migration
'Tshirt' => $state->got_shirt, 'Tshirt' => $state->got_shirt,
'color' => $settings->theme, 'color' => $settings->theme,
'Sprache' => $settings->language, 'Sprache' => $settings->language,
'lastLogIn' => $user->last_login_at 'lastLogIn' => $user->last_login_at ? $user->last_login_at->getTimestamp() : null,
? Carbon::make($user->last_login_at)->getTimestamp() 'CreateDate' => $user->created_at ? $user->created_at->toDateTimeString() : null,
: null,
'CreateDate' => $user->created_at
? Carbon::make($user->created_at)->toDateTimeString()
: '0001-01-01 00:00:00',
'api_key' => $user->api_key, 'api_key' => $user->api_key,
'got_voucher' => $state->got_voucher, 'got_voucher' => $state->got_voucher,
'arrival_date' => $state->arrival_date 'arrival_date' => $state->arrival_date ? $state->arrival_date->getTimestamp() : null,
? Carbon::make($state->arrival_date)->getTimestamp()
: null,
'planned_arrival_date' => $personal->planned_arrival_date 'planned_arrival_date' => $personal->planned_arrival_date
? Carbon::make($personal->planned_arrival_date)->getTimestamp() ? $personal->planned_arrival_date->getTimestamp()
: 0, : null,
'planned_departure_date' => $personal->planned_departure_date 'planned_departure_date' => $personal->planned_departure_date
? Carbon::make($personal->planned_departure_date)->getTimestamp() ? $personal->planned_departure_date->getTimestamp()
: null, : null,
'email_by_human_allowed' => $settings->email_human, 'email_by_human_allowed' => $settings->email_human,
]); ]);
} }
foreach ($connection->table('password_resets')->get() as $passwordReset) { foreach (PasswordReset::all() as $passwordReset) {
/** @var PasswordReset $passwordReset */
$this->schema->getConnection() $this->schema->getConnection()
->table('User') ->table('User')
->where('UID', '=', $passwordReset->user_id) ->where('UID', '=', $passwordReset->user_id)

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -10,7 +8,7 @@ use Illuminate\Database\Schema\Blueprint;
class ChangeUsersContactDectFieldSize extends Migration class ChangeUsersContactDectFieldSize extends Migration
{ {
/** @var array */ /** @var array */
protected array $tables = [ protected $tables = [
'AngelTypes' => 'contact_dect', 'AngelTypes' => 'contact_dect',
'users_contact' => 'dect', 'users_contact' => 'dect',
]; ];
@ -18,7 +16,7 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->changeDectTo(40); $this->changeDectTo(40);
} }
@ -26,19 +24,22 @@ class ChangeUsersContactDectFieldSize extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->changeDectTo(5); $this->changeDectTo(5);
} }
private function changeDectTo(int $length): void /**
* @param int $length
*/
protected function changeDectTo(int $length)
{ {
foreach ($this->tables as $table => $column) { foreach ($this->tables as $table => $column) {
if (!$this->schema->hasTable($table)) { if (!$this->schema->hasTable($table)) {
continue; continue;
} }
$this->schema->table($table, function (Blueprint $table) use ($column, $length): void { $this->schema->table($table, function (Blueprint $table) use ($column, $length) {
$table->string($column, $length)->change(); $table->string($column, $length)->change();
}); });
} }

View File

@ -1,37 +1,28 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use stdClass; use Engelsystem\Models\User\State;
class FixMissingArrivalDates extends Migration class FixMissingArrivalDates extends Migration
{ {
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $states = State::whereArrived(true)->whereArrivalDate(null)->get();
/** @var stdClass[] $states */
$states = $connection
->table('users_state')
->where('arrived', true)
->where('arrival_date', null)
->get();
foreach ($states as $state) { foreach ($states as $state) {
/** @var stdClass $personalData */ $state->arrival_date = $state->user->personalData->planned_arrival_date;
$personalData = $connection $state->save();
->table('users_personal_data')
->where('user_id', $state->user_id)
->first();
$state->arrival_date = $personalData->planned_arrival_date;
$connection->table('users_state')
->update((array) $state);
} }
} }
/**
* Down is not possible and not needed since this is a bugfix.
*/
public function down()
{
}
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,26 +9,26 @@ class FixUserLanguages extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update([ ->update([
'language' => $connection->raw('REPLACE(language, ".UTF-8", "")'), 'language' => $connection->raw('REPLACE(language, ".UTF-8", "")')
]); ]);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update([ ->update([
'language' => $connection->raw('CONCAT(language, ".UTF-8")'), 'language' => $connection->raw('CONCAT(language, ".UTF-8")')
]); ]);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;
@ -31,7 +29,7 @@ class MigrateAdminSchedulePermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,14 +12,19 @@ class CreateScheduleShiftTable extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('schedules', function (Blueprint $table): void { $this->schema->create(
'schedules',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('url'); $table->string('url');
}); }
);
$this->schema->create('schedule_shift', function (Blueprint $table): void { $this->schema->create(
'schedule_shift',
function (Blueprint $table) {
$table->integer('shift_id')->index()->unique(); $table->integer('shift_id')->index()->unique();
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
// Legacy table access // Legacy table access
@ -33,36 +36,52 @@ class CreateScheduleShiftTable extends Migration
$this->references($table, 'schedules'); $this->references($table, 'schedules');
$table->uuid('guid'); $table->uuid('guid');
}); }
);
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
'Shifts',
function (Blueprint $table) {
$table->dropColumn('PSID'); $table->dropColumn('PSID');
}); }
);
} }
if ($this->schema->hasTable('Room')) { if ($this->schema->hasTable('Room')) {
$this->schema->table('Room', function (Blueprint $table): void { $this->schema->table(
'Room',
function (Blueprint $table) {
$table->dropColumn('from_frab'); $table->dropColumn('from_frab');
}); }
);
} }
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if ($this->schema->hasTable('Room')) { if ($this->schema->hasTable('Room')) {
$this->schema->table('Room', function (Blueprint $table): void { $this->schema->table(
$table->boolean('from_frab')->default(false); 'Room',
}); function (Blueprint $table) {
$table->boolean('from_frab')
->default(false);
}
);
} }
if ($this->schema->hasTable('Shifts')) { if ($this->schema->hasTable('Shifts')) {
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
$table->integer('PSID')->nullable()->default(null)->unique(); 'Shifts',
}); function (Blueprint $table) {
$table->integer('PSID')
->nullable()->default(null)
->unique();
}
);
} }
$this->schema->drop('schedule_shift'); $this->schema->drop('schedule_shift');

View File

@ -64,9 +64,12 @@ class CreateNewsTable extends Migration
$this->schema->drop('new_news'); $this->schema->drop('new_news');
} }
/**
* @return void
*/
private function createNewNewsTable(): void private function createNewNewsTable(): void
{ {
$this->schema->create('news', function (Blueprint $table): void { $this->schema->create('news', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('title', 150); $table->string('title', 150);
$table->text('text'); $table->text('text');
@ -76,6 +79,9 @@ class CreateNewsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsTable(): void private function copyPreviousToNewNewsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -98,18 +104,25 @@ class CreateNewsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsTable(): void private function createPreviousNewsTable(): void
{ {
$this->schema->create('News', function (Blueprint $table): void { $this->schema->create('News', function (Blueprint $table) {
$table->increments('ID'); $table->increments('ID');
$table->integer('Datum'); $table->integer('Datum');
$table->string('Betreff', 150)->default(''); $table->string('Betreff', 150)
->default('');
$table->text('Text'); $table->text('Text');
$this->references($table, 'users', 'UID'); $this->references($table, 'users', 'UID');
$table->boolean('Treffen')->default(false); $table->boolean('Treffen')->default(false);
}); });
} }
/**
* @return void
*/
private function copyNewToPreviousNewsTable(): void private function copyNewToPreviousNewsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -53,9 +53,12 @@ class CreateNewsCommentsTable extends Migration
$this->schema->drop('news_comments'); $this->schema->drop('news_comments');
} }
/**
* @return void
*/
private function createNewNewsCommentsTable(): void private function createNewNewsCommentsTable(): void
{ {
$this->schema->create('news_comments', function (Blueprint $table): void { $this->schema->create('news_comments', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->references($table, 'news', 'news_id'); $this->references($table, 'news', 'news_id');
$table->text('text'); $table->text('text');
@ -64,6 +67,9 @@ class CreateNewsCommentsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyPreviousToNewNewsCommentsTable(): void private function copyPreviousToNewNewsCommentsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -84,9 +90,12 @@ class CreateNewsCommentsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousNewsCommentsTable(): void private function createPreviousNewsCommentsTable(): void
{ {
$this->schema->create('NewsComments', function (Blueprint $table): void { $this->schema->create('NewsComments', function (Blueprint $table) {
$table->increments('ID'); $table->increments('ID');
$this->references($table, 'news', 'Refid'); $this->references($table, 'news', 'Refid');
$table->dateTime('Datum'); $table->dateTime('Datum');
@ -95,6 +104,9 @@ class CreateNewsCommentsTable extends Migration
}); });
} }
/**
* @return void
*/
private function copyNewToPreviousNewsCommentsTable(): void private function copyNewToPreviousNewsCommentsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -64,18 +64,27 @@ class CreateMessagesTable extends Migration
$this->schema->drop('new_messages'); $this->schema->drop('new_messages');
} }
/**
* @return void
*/
private function createNewMessagesTable(): void private function createNewMessagesTable(): void
{ {
$this->schema->create('messages', function (Blueprint $table): void { $this->schema->create(
'messages',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$this->references($table, 'users', 'receiver_id'); $this->references($table, 'users', 'receiver_id');
$table->boolean('read')->default(0); $table->boolean('read')->default(0);
$table->text('text'); $table->text('text');
$table->timestamps(); $table->timestamps();
}); }
);
} }
/**
* @return void
*/
private function copyPreviousToNewMessagesTable(): void private function copyPreviousToNewMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -100,18 +109,28 @@ class CreateMessagesTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousMessagesTable(): void private function createPreviousMessagesTable(): void
{ {
$this->schema->create('Messages', function (Blueprint $table): void { $this->schema->create(
'Messages',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->integer('Datum'); $table->integer('Datum');
$this->references($table, 'users', 'SUID'); $this->references($table, 'users', 'SUID');
$this->references($table, 'users', 'RUID'); $this->references($table, 'users', 'RUID');
$table->char('isRead')->default('N'); $table->char('isRead')
->default('N');
$table->text('Text'); $table->text('Text');
}); }
);
} }
/**
* @return void
*/
private function copyNewToPreviousMessagesTable(): void private function copyNewToPreviousMessagesTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -17,6 +17,9 @@ class CreateQuestionsTable extends Migration
use ChangesReferences; use ChangesReferences;
use Reference; use Reference;
/**
* @return void
*/
public function up(): void public function up(): void
{ {
$hasPreviousQuestionsTable = $this->schema->hasTable('Questions'); $hasPreviousQuestionsTable = $this->schema->hasTable('Questions');
@ -40,6 +43,9 @@ class CreateQuestionsTable extends Migration
} }
} }
/**
* @return void
*/
public function down(): void public function down(): void
{ {
// Rename as some SQL DBMS handle identifiers case insensitive // Rename as some SQL DBMS handle identifiers case insensitive
@ -57,17 +63,28 @@ class CreateQuestionsTable extends Migration
$this->schema->drop('new_questions'); $this->schema->drop('new_questions');
} }
/**
* @return void
*/
private function createNewQuestionsTable(): void private function createNewQuestionsTable(): void
{ {
$this->schema->create('questions', function (Blueprint $table): void { $this->schema->create(
'questions',
function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->text('text'); $table->text('text');
$table->text('answer')->nullable(); $table->text('answer')
$this->references($table, 'users', 'answerer_id')->nullable(); ->nullable();
}); $this->references($table, 'users', 'answerer_id')
->nullable();
}
);
} }
/**
* @return void
*/
private function copyPreviousToNewQuestionsTable(): void private function copyPreviousToNewQuestionsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();
@ -87,17 +104,28 @@ class CreateQuestionsTable extends Migration
} }
} }
/**
* @return void
*/
private function createPreviousQuestionsTable(): void private function createPreviousQuestionsTable(): void
{ {
$this->schema->create('Questions', function (Blueprint $table): void { $this->schema->create(
'Questions',
function (Blueprint $table) {
$table->increments('QID'); $table->increments('QID');
$this->references($table, 'users', 'UID'); $this->references($table, 'users', 'UID');
$table->text('Question'); $table->text('Question');
$this->references($table, 'users', 'AID')->nullable(); $this->references($table, 'users', 'AID')
$table->text('Answer')->nullable(); ->nullable();
}); $table->text('Answer')
->nullable();
}
);
} }
/**
* @return void
*/
private function copyNewToPreviousQuestionsTable(): void private function copyNewToPreviousQuestionsTable(): void
{ {
$connection = $this->schema->getConnection(); $connection = $this->schema->getConnection();

View File

@ -14,8 +14,11 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->string('pronoun', 15)->nullable()->default(null)->after('last_name'); $table->string('pronoun', 15)
->nullable()
->default(null)
->after('last_name');
}); });
} }
@ -24,7 +27,7 @@ class UserPersonalDataAddPronounField extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->dropColumn('pronoun'); $table->dropColumn('pronoun');
}); });
} }

View File

@ -28,5 +28,11 @@ class ChangeMysqlDatabaseEncodingToUtf8mb4 extends Migration
} }
} }
// As utf8mb4 is a superset of utf8, there is nothing to do in the downgrade /**
* Reverse the migration
*/
public function down(): void
{
// As utf8mb4 is a superset of utf8, there is nothing to do here
}
} }

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Room;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -18,7 +19,7 @@ class CreateRoomsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('rooms', function (Blueprint $table): void { $this->schema->create('rooms', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('name', 35)->unique(); $table->string('name', 35)->unique();
$table->string('map_url', 300)->nullable(); $table->string('map_url', 300)->nullable();
@ -34,13 +35,13 @@ class CreateRoomsTable extends Migration
->get(); ->get();
foreach ($previousRecords as $previousRecord) { foreach ($previousRecords as $previousRecord) {
$connection->table('rooms') $room = new Room([
->insert([
'id' => $previousRecord->RID,
'name' => $previousRecord->Name, 'name' => $previousRecord->Name,
'map_url' => $previousRecord->map_url ?: null, 'map_url' => $previousRecord->map_url ?: null,
'description' => $previousRecord->description ?: null, 'description' => $previousRecord->description ?: null,
]); ]);
$room->setAttribute('id', $previousRecord->RID);
$room->save();
} }
$this->changeReferences( $this->changeReferences(
@ -59,18 +60,16 @@ class CreateRoomsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$connection = $this->schema->getConnection(); $this->schema->create('Room', function (Blueprint $table) {
$this->schema->create('Room', function (Blueprint $table): void {
$table->increments('RID'); $table->increments('RID');
$table->string('Name', 35)->unique(); $table->string('Name', 35)->unique();
$table->string('map_url', 300)->nullable(); $table->string('map_url', 300)->nullable();
$table->mediumText('description')->nullable(); $table->mediumText('description')->nullable();
}); });
foreach ($connection->table('rooms')->get() as $room) { foreach (Room::all() as $room) {
/** @var stdClass $room */ $this->schema
$connection ->getConnection()
->table('Room') ->table('Room')
->insert([ ->insert([
'RID' => $room->id, 'RID' => $room->id,

View File

@ -6,6 +6,7 @@ namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Worklog;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use stdClass; use stdClass;
@ -19,7 +20,7 @@ class CreateWorklogsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('worklogs', function (Blueprint $table): void { $this->schema->create('worklogs', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$this->references($table, 'users', 'creator_id'); $this->references($table, 'users', 'creator_id');
@ -37,19 +38,18 @@ class CreateWorklogsTable extends Migration
->get(); ->get();
foreach ($previousRecords as $previousRecord) { foreach ($previousRecords as $previousRecord) {
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp); $room = new Worklog([
$this->schema->getConnection()
->table('worklogs')
->insert([
'id' => $previousRecord->id,
'user_id' => $previousRecord->user_id, 'user_id' => $previousRecord->user_id,
'creator_id' => $previousRecord->created_user_id, 'creator_id' => $previousRecord->created_user_id,
'worked_at' => $previousRecord->work_timestamp, 'worked_at' => $previousRecord->work_timestamp,
'hours' => $previousRecord->work_hours, 'hours' => $previousRecord->work_hours,
'comment' => $previousRecord->comment, 'comment' => $previousRecord->comment,
'created_at' => $created_at,
'updated_at' => $created_at,
]); ]);
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
$room->setAttribute('id', $previousRecord->id);
$room->setAttribute('created_at', $created_at);
$room->setAttribute('updated_at', $created_at);
$room->save();
} }
$this->changeReferences( $this->changeReferences(
@ -68,9 +68,7 @@ class CreateWorklogsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$connection = $this->schema->getConnection(); $this->schema->create('UserWorkLog', function (Blueprint $table) {
$this->schema->create('UserWorkLog', function (Blueprint $table): void {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->integer('work_timestamp'); $table->integer('work_timestamp');
@ -80,9 +78,10 @@ class CreateWorklogsTable extends Migration
$table->integer('created_timestamp')->index(); $table->integer('created_timestamp')->index();
}); });
foreach ($connection->table('worklogs')->get() as $record) { foreach (Worklog::all() as $record) {
/** @var stdClass $record */ /** @var Worklog $record */
$connection $this->schema
->getConnection()
->table('UserWorkLog') ->table('UserWorkLog')
->insert([ ->insert([
'id' => $record->id, 'id' => $record->id,

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Groups')) { if (!$this->schema->hasTable('Groups')) {
return; return;
@ -40,7 +38,7 @@ class CreateWelcomeAngelPermissionsGroup extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Groups')) { if (!$this->schema->hasTable('Groups')) {
return; return;

View File

@ -1,11 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Question;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
class AddTimestampsToQuestions extends Migration class AddTimestampsToQuestions extends Migration
@ -17,20 +16,17 @@ class AddTimestampsToQuestions extends Migration
*/ */
public function up(): void public function up(): void
{ {
$connection = $this->schema->getConnection(); $this->schema->table('questions', function (Blueprint $table) {
$now = Carbon::now();
$this->schema->table('questions', function (Blueprint $table): void {
$table->timestamp('answered_at')->after('answerer_id')->nullable(); $table->timestamp('answered_at')->after('answerer_id')->nullable();
$table->timestamps(); $table->timestamps();
}); });
$connection->table('questions') $now = Carbon::now();
->update([ Question::query()->update([
'created_at' => $now, 'created_at' => $now,
'updated_at' => $now, 'updated_at' => $now,
]); ]);
$connection->table('questions') Question::query()
->whereNotNull('answerer_id') ->whereNotNull('answerer_id')
->update([ ->update([
'answered_at' => $now, 'answered_at' => $now,
@ -42,7 +38,7 @@ class AddTimestampsToQuestions extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->table('questions', function (Blueprint $table): void { $this->schema->table('questions', function (Blueprint $table) {
$table->dropColumn('answered_at'); $table->dropColumn('answered_at');
$table->dropTimestamps(); $table->dropTimestamps();
}); });

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class CreateFaqTableAndPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->create('faq', function (Blueprint $table): void { $this->schema->create('faq', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('question'); $table->string('question');
$table->text('text'); $table->text('text');
@ -48,7 +46,7 @@ class CreateFaqTableAndPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->drop('faq'); $this->schema->drop('faq');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if ($this->schema->hasTable('Privileges')) { if ($this->schema->hasTable('Privileges')) {
$db = $this->schema->getConnection(); $db = $this->schema->getConnection();
@ -38,7 +36,7 @@ class CreateQuestionsPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -16,7 +16,7 @@ class CreateOauthTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('oauth', function (Blueprint $table): void { $this->schema->create('oauth', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$this->referencesUser($table); $this->referencesUser($table);
$table->string('provider'); $table->string('provider');

View File

@ -1,11 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\Shifts\Schedule;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
class AddNameMinutesAndTimestampsToSchedules extends Migration class AddNameMinutesAndTimestampsToSchedules extends Migration
@ -15,34 +14,39 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $this->schema->table(
'schedules',
$this->schema->table('schedules', function (Blueprint $table): void { function (Blueprint $table) {
$table->string('name')->default('')->after('id'); $table->string('name')->default('')->after('id');
$table->integer('shift_type')->default(0)->after('name'); $table->integer('shift_type')->default(0)->after('name');
$table->integer('minutes_before')->default(0)->after('shift_type'); $table->integer('minutes_before')->default(0)->after('shift_type');
$table->integer('minutes_after')->default(0)->after('minutes_before'); $table->integer('minutes_after')->default(0)->after('minutes_before');
$table->timestamps(); $table->timestamps();
}); }
);
$connection->table('schedules') Schedule::query()
->update([ ->update([
'created_at' => Carbon::now(), 'created_at' => Carbon::now(),
'minutes_before' => 15, 'minutes_before' => 15,
'minutes_after' => 15, 'minutes_after' => 15,
]); ]);
$this->schema->table('schedules', function (Blueprint $table): void { $this->schema->table(
'schedules',
function (Blueprint $table) {
$table->string('name')->default(null)->change(); $table->string('name')->default(null)->change();
$table->integer('shift_type')->default(null)->change(); $table->integer('shift_type')->default(null)->change();
$table->integer('minutes_before')->default(null)->change(); $table->integer('minutes_before')->default(null)->change();
$table->integer('minutes_after')->default(null)->change(); $table->integer('minutes_after')->default(null)->change();
}); }
);
// Add legacy reference // Add legacy reference
if ($this->schema->hasTable('ShiftTypes')) { if ($this->schema->hasTable('ShiftTypes')) {
$connection = $this->schema->getConnection();
$query = $connection $query = $connection
->table('Shifts') ->table('Shifts')
->select('Shifts.shifttype_id') ->select('Shifts.shifttype_id')
@ -50,29 +54,33 @@ class AddNameMinutesAndTimestampsToSchedules extends Migration
->where('schedule_shift.schedule_id', $connection->raw('schedules.id')) ->where('schedule_shift.schedule_id', $connection->raw('schedules.id'))
->limit(1); ->limit(1);
$connection->table('schedules') Schedule::query()
->update([ ->update(['shift_type' => $connection->raw('(' . $query->toSql() . ')')]);
'shift_type' => $connection->raw('(' . $query->toSql() . ')'),
]);
$this->schema->table('schedules', function (Blueprint $table): void { $this->schema->table(
'schedules',
function (Blueprint $table) {
$this->addReference($table, 'shift_type', 'ShiftTypes'); $this->addReference($table, 'shift_type', 'ShiftTypes');
}); }
);
} }
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('schedules', function (Blueprint $table): void { $this->schema->table(
'schedules',
function (Blueprint $table) {
$table->dropForeign('schedules_shift_type_foreign'); $table->dropForeign('schedules_shift_type_foreign');
$table->dropColumn('name'); $table->dropColumn('name');
$table->dropColumn('shift_type'); $table->dropColumn('shift_type');
$table->dropColumn('minutes_before'); $table->dropColumn('minutes_before');
$table->dropColumn('minutes_after'); $table->dropColumn('minutes_after');
$table->dropTimestamps(); $table->dropTimestamps();
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,20 +12,26 @@ class AddEmailNewsToUsersSettings extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('users_settings', function (Blueprint $table): void { $this->schema->table(
'users_settings',
function (Blueprint $table) {
$table->boolean('email_news')->default(false)->after('email_shiftinfo'); $table->boolean('email_news')->default(false)->after('email_shiftinfo');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('users_settings', function (Blueprint $table): void { $this->schema->table(
'users_settings',
function (Blueprint $table) {
$table->dropColumn('email_news'); $table->dropColumn('email_news');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,24 +12,30 @@ class OauthAddTokens extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->string('access_token')->nullable()->default(null)->after('identifier'); $table->string('access_token')->nullable()->default(null)->after('identifier');
$table->string('refresh_token')->nullable()->default(null)->after('access_token'); $table->string('refresh_token')->nullable()->default(null)->after('access_token');
$table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token'); $table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->dropColumn('access_token'); $table->dropColumn('access_token');
$table->dropColumn('refresh_token'); $table->dropColumn('refresh_token');
$table->dropColumn('expires_at'); $table->dropColumn('expires_at');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,20 +12,26 @@ class NewsAddIsPinned extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('news', function (Blueprint $table): void { $this->schema->table(
'news',
function (Blueprint $table) {
$table->boolean('is_pinned')->default(false)->after('is_meeting'); $table->boolean('is_pinned')->default(false)->after('is_meeting');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('news', function (Blueprint $table): void { $this->schema->table(
'news',
function (Blueprint $table) {
$table->dropColumn('is_pinned'); $table->dropColumn('is_pinned');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,22 +12,28 @@ class OauthChangeTokensToText extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->text('access_token')->change(); $table->text('access_token')->change();
$table->text('refresh_token')->change(); $table->text('refresh_token')->change();
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('oauth', function (Blueprint $table): void { $this->schema->table(
'oauth',
function (Blueprint $table) {
$table->string('access_token')->change(); $table->string('access_token')->change();
$table->string('refresh_token')->change(); $table->string('refresh_token')->change();
}); }
);
} }
} }

View File

@ -1,28 +1,42 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Config\Config; use Engelsystem\Config\Config;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Authenticator; use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
use Illuminate\Database\Schema\Builder as SchemaBuilder; use Illuminate\Database\Schema\Builder as SchemaBuilder;
class SetAdminPassword extends Migration class SetAdminPassword extends Migration
{ {
use Reference; use Reference;
public function __construct(SchemaBuilder $schemaBuilder, protected Authenticator $auth, protected Config $config) /** @var Authenticator */
protected $auth;
/** @var Config */
protected $config;
/**
* @param SchemaBuilder $schemaBuilder
* @param Authenticator $auth
* @param Config $config
*/
public function __construct(SchemaBuilder $schemaBuilder, Authenticator $auth, Config $config)
{ {
parent::__construct($schemaBuilder); parent::__construct($schemaBuilder);
$this->auth = $auth;
$this->config = $config;
} }
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
/** @var User $admin */
$admin = $this->auth->authenticate('admin', 'asdfasdf'); $admin = $this->auth->authenticate('admin', 'asdfasdf');
$setupPassword = $this->config->get('setup_admin_password'); $setupPassword = $this->config->get('setup_admin_password');
if (!$admin || !$setupPassword) { if (!$admin || !$setupPassword) {

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class AddShirtEditPermissions extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -42,7 +40,7 @@ class AddShirtEditPermissions extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,28 +12,34 @@ class AddShiftsDescription extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Shifts')) { if (!$this->schema->hasTable('Shifts')) {
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
'Shifts',
function (Blueprint $table) {
$table->text('description')->nullable()->after('shifttype_id'); $table->text('description')->nullable()->after('shifttype_id');
}); }
);
} }
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Shifts')) { if (!$this->schema->hasTable('Shifts')) {
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table(
'Shifts',
function (Blueprint $table) {
$table->dropColumn('description'); $table->dropColumn('description');
}); }
);
} }
} }

View File

@ -16,7 +16,7 @@ class CreateUserLicensesTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
$this->schema->create('users_licenses', function (Blueprint $table): void { $this->schema->create('users_licenses', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('has_car')->default(false); $table->boolean('has_car')->default(false);
$table->boolean('drive_forklift')->default(false); $table->boolean('drive_forklift')->default(false);
@ -54,7 +54,7 @@ class CreateUserLicensesTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
$this->schema->create('UserDriverLicenses', function (Blueprint $table): void { $this->schema->create('UserDriverLicenses', function (Blueprint $table) {
$this->referencesUser($table, true); $this->referencesUser($table, true);
$table->boolean('has_car'); $table->boolean('has_car');
$table->boolean('has_license_car'); $table->boolean('has_license_car');

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class IncreaseSessionsTablePayloadSize extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('sessions', function (Blueprint $table): void { $this->schema->table('sessions', function (Blueprint $table) {
$table->mediumText('payload')->change(); $table->mediumText('payload')->change();
}); });
} }
@ -22,9 +20,9 @@ class IncreaseSessionsTablePayloadSize extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('sessions', function (Blueprint $table): void { $this->schema->table('sessions', function (Blueprint $table) {
$table->text('payload')->change(); $table->text('payload')->change();
}); });
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -14,14 +12,16 @@ class UsersSettingsAddEmailGoody extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$connection = $this->schema->getConnection(); $this->schema->table(
'users_settings',
$this->schema->table('users_settings', function (Blueprint $table): void { function (Blueprint $table) {
$table->boolean('email_goody')->default(false)->after('email_human'); $table->boolean('email_goody')->default(false)->after('email_human');
}); }
);
$connection = $this->schema->getConnection();
$connection $connection
->table('users_settings') ->table('users_settings')
->update(['email_goody' => $connection->raw('email_human')]); ->update(['email_goody' => $connection->raw('email_human')]);
@ -30,10 +30,13 @@ class UsersSettingsAddEmailGoody extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('users_settings', function (Blueprint $table): void { $this->schema->table(
'users_settings',
function (Blueprint $table) {
$table->dropColumn('email_goody'); $table->dropColumn('email_goody');
}); }
);
} }
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class RemoveAdminNewsHtmlPrivilege extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;
@ -29,7 +27,7 @@ class RemoveAdminNewsHtmlPrivilege extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('GroupPrivileges')) { if (!$this->schema->hasTable('GroupPrivileges')) {
return; return;

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -15,9 +13,9 @@ class IncreaseTshirtFieldWidth extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->string('shirt_size', 10)->change(); $table->string('shirt_size', 10)->change();
}); });
} }
@ -25,9 +23,9 @@ class IncreaseTshirtFieldWidth extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
$this->schema->table('users_personal_data', function (Blueprint $table): void { $this->schema->table('users_personal_data', function (Blueprint $table) {
$table->string('shirt_size', 4)->change(); $table->string('shirt_size', 4)->change();
}); });
} }

View File

@ -1,7 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace Engelsystem\Migrations; namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration; use Engelsystem\Database\Migration\Migration;
@ -11,7 +9,7 @@ class CreateVoucherEditPermission extends Migration
/** /**
* Run the migration * Run the migration
*/ */
public function up(): void public function up()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;
@ -38,7 +36,7 @@ class CreateVoucherEditPermission extends Migration
/** /**
* Reverse the migration * Reverse the migration
*/ */
public function down(): void public function down()
{ {
if (!$this->schema->hasTable('Privileges')) { if (!$this->schema->hasTable('Privileges')) {
return; return;

View File

@ -18,7 +18,7 @@ class ShiftsAddTransactionId extends Migration
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table('Shifts', function (Blueprint $table) {
$table->uuid('transaction_id')->index()->nullable()->default(null); $table->uuid('transaction_id')->index()->nullable()->default(null);
}); });
} }
@ -32,7 +32,7 @@ class ShiftsAddTransactionId extends Migration
return; return;
} }
$this->schema->table('Shifts', function (Blueprint $table): void { $this->schema->table('Shifts', function (Blueprint $table) {
$table->dropColumn('transaction_id'); $table->dropColumn('transaction_id');
}); });
} }

View File

@ -1,82 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class FixOldGroupsTableIdAndName extends Migration
{
/** @var string[] */
protected array $naming = [
'1-Gast' => 'Guest',
'2-Engel' => 'Angel',
'Shirt-Manager' => 'Shirt Manager',
'3-Shift Coordinator' => 'Shift Coordinator',
'4-Team Coordinator' => 'Team Coordinator',
'5-Bürokrat' => 'Bureaucrat',
'6-Developer' => 'Developer',
];
/** @var int[] */
protected array $ids = [
-25 => -30,
-26 => -35,
-30 => -50,
-40 => -60,
-50 => -65,
-60 => -80,
-65 => -85,
-70 => -90,
];
/**
* Run the migration
*/
public function up(): void
{
$this->migrate($this->naming, $this->ids);
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->migrate(array_flip($this->naming), array_flip($this->ids));
}
/**
* @param string[] $naming
* @param int[] $ids
*/
private function migrate(array $naming, array $ids): void
{
if (!$this->schema->hasTable('Groups')) {
return;
}
$connection = $this->schema->getConnection();
foreach ($connection->table('Groups')->orderByDesc('UID')->get() as $data) {
if (isset($naming[$data->Name])) {
$data->Name = $naming[$data->Name];
}
$data->oldId = $data->UID;
if (isset($ids[$data->oldId])) {
$data->UID = $ids[$data->oldId];
} elseif (isset($ids[$data->oldId * -1])) {
$data->UID = $ids[$data->oldId * -1] * -1;
}
$connection
->table('Groups')
->where('UID', $data->oldId)
->update([
'UID' => $data->UID * -1,
'Name' => $data->Name,
]);
}
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddMobileShowToUsersSettings extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->boolean('mobile_show')->default(false)->after('email_news');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->dropColumn('mobile_show');
});
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddDectToRooms extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('rooms', function (Blueprint $table): void {
$table->text('dect')->nullable()->after('description');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('rooms', function (Blueprint $table): void {
$table->dropColumn('dect');
});
}
}

View File

@ -1,39 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddHideRegisterToAngeltypes extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
$this->schema->table('AngelTypes', function (Blueprint $table): void {
$table->boolean('hide_register')->default(false)->after('show_on_dashboard');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
$this->schema->table('AngelTypes', function (Blueprint $table): void {
$table->dropColumn('hide_register');
});
}
}

View File

@ -1,262 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreatePrivilegesAndGroupsRelatedTables extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one.
*/
public function up(): void
{
$hasPrevious = $this->schema->hasTable('Privileges');
if ($hasPrevious) {
// Rename because some DBMS handle identifiers case-insensitive
$this->schema->rename('Groups', 'groups_old');
$this->schema->rename('Privileges', 'privileges_old');
}
$this->createNew();
if ($hasPrevious) {
$this->copyOldToNew();
$this->changeReferences(
'groups_old',
'UID',
'groups',
'id'
);
$this->changeReferences(
'privileges_old',
'id',
'privileges',
'id'
);
$this->changeReferences(
'UserGroups',
'id',
'users_groups',
'id'
);
$this->changeReferences(
'GroupPrivileges',
'id',
'group_privileges',
'id'
);
$this->schema->drop('UserGroups');
$this->schema->drop('GroupPrivileges');
$this->schema->drop('groups_old');
$this->schema->drop('privileges_old');
}
}
/**
* Recreates the previous table, copies the data and drops the new one.
*/
public function down(): void
{
// Rename because some DBMS handle identifiers case-insensitive
$this->schema->rename('groups', 'groups_new');
$this->schema->rename('privileges', 'privileges_new');
$this->createOldTable();
$this->copyNewToOld();
$this->changeReferences(
'groups_new',
'id',
'Groups',
'UID',
'integer'
);
$this->changeReferences(
'privileges_new',
'id',
'Privileges',
'id'
);
$this->changeReferences(
'users_groups',
'id',
'UserGroups',
'id'
);
$this->changeReferences(
'group_privileges',
'id',
'GroupPrivileges',
'id'
);
$this->schema->drop('users_groups');
$this->schema->drop('group_privileges');
$this->schema->drop('groups_new');
$this->schema->drop('privileges_new');
}
private function createNew(): void
{
$this->schema->create('groups', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 35)->unique();
});
$this->schema->create('privileges', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 128)->unique();
$table->string('description', 1024);
});
$this->schema->create('users_groups', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table)->index();
$this->references($table, 'groups')->index();
});
$this->schema->create('group_privileges', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'groups')->index();
$this->references($table, 'privileges')->index();
});
}
private function createOldTable(): void
{
$this->schema->create('Groups', function (Blueprint $table): void {
$table->string('Name', 35);
$table->integer('UID')->primary();
});
$this->schema->create('Privileges', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 128)->unique();
$table->string('desc', 1024);
});
$this->schema->create('UserGroups', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'users', 'uid');
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer')->index();
$table->index(['uid', 'group_id']);
});
$this->schema->create('GroupPrivileges', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'Groups', 'group_id', 'UID', false, 'integer');
$this->references($table, 'Privileges', 'privilege_id')->index();
$table->index(['group_id', 'privilege_id']);
});
}
private function copyOldToNew(): void
{
$connection = $this->schema->getConnection();
/** @var stdClass[] $records */
$records = $connection
->table('groups_old')
->get();
foreach ($records as $record) {
$connection->table('groups')->insert([
'id' => $record->UID,
'name' => $record->Name,
]);
}
$records = $connection
->table('privileges_old')
->get();
foreach ($records as $record) {
$connection->table('privileges')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->desc,
]);
}
$records = $connection
->table('UserGroups')
->get();
foreach ($records as $record) {
$connection->table('users_groups')->insert([
'id' => $record->id,
'user_id' => $record->uid,
'group_id' => $record->group_id,
]);
}
$records = $connection
->table('GroupPrivileges')
->get();
foreach ($records as $record) {
$connection->table('group_privileges')->insert([
'id' => $record->id,
'group_id' => $record->group_id,
'privilege_id' => $record->privilege_id,
]);
}
}
private function copyNewToOld(): void
{
$connection = $this->schema->getConnection();
/** @var Collection|stdClass[] $records */
$records = $connection
->table('groups_new')
->get();
foreach ($records as $record) {
$connection->table('Groups')->insert([
'Name' => $record->name,
'UID' => $record->id,
]);
}
$records = $connection
->table('privileges_new')
->get();
foreach ($records as $record) {
$connection->table('Privileges')->insert([
'id' => $record->id,
'name' => $record->name,
'desc' => $record->description,
]);
}
$records = $connection
->table('users_groups')
->get();
foreach ($records as $record) {
$connection->table('UserGroups')->insert([
'id' => $record->id,
'uid' => $record->user_id,
'group_id' => $record->group_id,
]);
}
$records = $connection
->table('group_privileges')
->get();
foreach ($records as $record) {
$connection->table('GroupPrivileges')->insert([
'id' => $record->id,
'group_id' => $record->group_id,
'privilege_id' => $record->privilege_id,
]);
}
}
}

View File

@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class ShifttypeRemoveAngeltype extends Migration
{
use Reference;
/**
* Run the migration
*/
public function up(): void
{
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
$this->schema->table('ShiftTypes', function (Blueprint $table): void {
$table->dropForeign('shifttypes_ibfk_1');
$table->dropColumn('angeltype_id');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
$this->schema->table('ShiftTypes', function (Blueprint $table): void {
$table->integer('angeltype_id')->after('name')->index()->nullable();
$this->addReference($table, 'angeltype_id', 'AngelTypes', null, 'shifttypes_ibfk_1');
});
}
}

View File

@ -1,86 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftTypesTable extends Migration
{
use ChangesReferences;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('shift_types', function (Blueprint $table): void {
$table->increments('id');
$table->string('name')->unique();
$table->text('description');
});
if (!$this->schema->hasTable('ShiftTypes')) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('ShiftTypes')
->get();
foreach ($records as $record) {
$connection->table('shift_types')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
]);
}
$this->changeReferences(
'ShiftTypes',
'id',
'shift_types',
'id'
);
$this->schema->drop('ShiftTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('ShiftTypes', function (Blueprint $table): void {
$table->increments('id');
$table->string('name', 255);
$table->mediumText('description');
});
/** @var stdClass[] $records */
$records = $connection
->table('shift_types')
->get();
foreach ($records as $record) {
$connection->table('ShiftTypes')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
]);
}
$this->changeReferences(
'shift_types',
'id',
'ShiftTypes',
'id'
);
$this->schema->drop('shift_types');
}
}

View File

@ -1,126 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Support\Collection;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateAngelTypesTable extends Migration
{
use ChangesReferences;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('angel_types', function (Blueprint $table): void {
$table->increments('id');
$table->string('name')->unique();
$table->text('description')->default('');
$table->string('contact_name')->default('');
$table->string('contact_dect')->default('');
$table->string('contact_email')->default('');
$table->boolean('restricted')->default(false);
$table->boolean('requires_driver_license')->default(false);
$table->boolean('no_self_signup')->default(false);
$table->boolean('show_on_dashboard')->default(true);
$table->boolean('hide_register')->default(false);
});
if (!$this->schema->hasTable('AngelTypes')) {
return;
}
/** @var Collection|stdClass[] $records */
$records = $connection
->table('AngelTypes')
->get();
foreach ($records as $record) {
$connection->table('angel_types')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
'contact_name' => (string) $record->contact_name,
'contact_dect' => (string) $record->contact_dect,
'contact_email' => (string) $record->contact_email,
'restricted' => $record->restricted,
'requires_driver_license' => $record->requires_driver_license,
'no_self_signup' => $record->no_self_signup,
'show_on_dashboard' => $record->show_on_dashboard,
'hide_register' => $record->hide_register,
]);
}
$this->changeReferences(
'AngelTypes',
'id',
'angel_types',
'id'
);
$this->schema->drop('AngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('AngelTypes', function (Blueprint $table): void {
$table->integer('id', true);
$table->string('name', 50)->default('')->unique();
$table->boolean('restricted');
$table->mediumText('description');
$table->boolean('requires_driver_license');
$table->boolean('no_self_signup');
$table->string('contact_name', 250)->nullable();
$table->string('contact_dect', 40)->nullable();
$table->string('contact_email', 250)->nullable();
$table->boolean('show_on_dashboard');
$table->boolean('hide_register')->default(false);
});
/** @var Collection|stdClass[] $records */
$records = $connection
->table('angel_types')
->get();
foreach ($records as $record) {
$connection->table('AngelTypes')->insert([
'id' => $record->id,
'name' => $record->name,
'description' => $record->description,
'contact_name' => $record->contact_name ?: null,
'contact_dect' => $record->contact_dect ?: null,
'contact_email' => $record->contact_email ?: null,
'restricted' => $record->restricted,
'requires_driver_license' => $record->requires_driver_license,
'no_self_signup' => $record->no_self_signup,
'show_on_dashboard' => $record->show_on_dashboard,
'hide_register' => $record->hide_register,
]);
}
$this->changeReferences(
'angel_types',
'id',
'AngelTypes',
'id',
'integer'
);
$this->schema->drop('angel_types');
}
}

View File

@ -1,101 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateUserAngelTypesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('user_angel_type', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types')->index();
$this->references($table, 'users', 'confirm_user_id')->nullable()->default(null)->index();
$table->boolean('supporter')->default(false)->index();
$table->index(['user_id', 'angel_type_id', 'confirm_user_id']);
$table->unique(['user_id', 'angel_type_id']);
});
if (!$this->schema->hasTable('UserAngelTypes')) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('UserAngelTypes')
->get();
foreach ($records as $record) {
$connection->table('user_angel_type')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angel_type_id' => $record->angeltype_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool) $record->supporter,
]);
}
$this->changeReferences(
'UserAngelTypes',
'id',
'user_angel_type',
'id'
);
$this->schema->drop('UserAngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('UserAngelTypes', function (Blueprint $table): void {
$table->increments('id');
$this->referencesUser($table);
$this->references($table, 'angel_types', 'angeltype_id')->index('angeltype_id');
$this->references($table, 'users', 'confirm_user_id')->nullable()->index('confirm_user_id');
$table->boolean('supporter')->nullable()->index('coordinator');
$table->index(['user_id', 'angeltype_id', 'confirm_user_id'], 'user_id');
});
/** @var stdClass[] $records */
$records = $connection
->table('user_angel_type')
->get();
foreach ($records as $record) {
$connection->table('UserAngelTypes')->insert([
'id' => $record->id,
'user_id' => $record->user_id,
'angeltype_id' => $record->angel_type_id,
'confirm_user_id' => $record->confirm_user_id ?: null,
'supporter' => (bool) $record->supporter,
]);
}
$this->changeReferences(
'user_angel_type',
'id',
'UserAngelTypes',
'id',
'integer'
);
$this->schema->drop('user_angel_type');
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class ChangeApiKeyLength extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users', function (Blueprint $table): void {
$table->string('api_key', 64)->change();
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('users', function (Blueprint $table): void {
$table->string('api_key', 32)->change();
});
}
}

View File

@ -1,149 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Helpers\Carbon;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftsTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('Shifts');
if ($previous) {
$this->schema->rename('Shifts', 'shifts_old');
}
$this->schema->create('shifts', function (Blueprint $table): void {
$table->increments('id');
$table->string('title');
$table->text('description')->default('');
$table->string('url')->default('');
$table->dateTime('start')->index();
$table->dateTime('end');
$this->references($table, 'shift_types');
$this->references($table, 'rooms');
$table->uuid('transaction_id')->nullable()->default(null)->index();
$this->references($table, 'users', 'created_by');
$this->references($table, 'users', 'updated_by')->nullable()->default(null);
$table->timestamps();
});
if (!$previous) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('shifts_old')
->get();
foreach ($records as $record) {
$isUpdated = !empty($record->edited_at_timestamp)
&& $record->edited_at_timestamp != $record->created_at_timestamp;
$connection->table('shifts')->insert([
'id' => $record->SID,
'title' => (string) $record->title,
'description' => (string) $record->description,
'url' => (string) $record->URL,
'start' => Carbon::createFromTimestamp($record->start),
'end' => Carbon::createFromTimestamp($record->end),
'shift_type_id' => $record->shifttype_id,
'room_id' => $record->RID,
'transaction_id' => $record->transaction_id,
'created_by' => $record->created_by_user_id,
'updated_by' => $isUpdated ? $record->edited_by_user_id : null,
'created_at' => Carbon::createFromTimestamp($record->created_at_timestamp),
'updated_at' => $isUpdated ? Carbon::createFromTimestamp($record->edited_at_timestamp) : null,
]);
}
$this->changeReferences(
'shifts_old',
'SID',
'shifts',
'id'
);
$this->schema->drop('shifts_old');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->rename('shifts', 'shifts_old');
$this->schema->create('Shifts', function (Blueprint $table): void {
$table->increments('SID');
$table->mediumText('title')->nullable()->default(null);
$this->references($table, 'shift_types', 'shifttype_id');
$table->text('description')->nullable()->default(null);
$table->integer('start')->index();
$table->integer('end');
$this->references($table, 'rooms', 'RID')->default(0);
$table->mediumText('URL')->nullable()->default(null);
$this->references($table, 'users', 'created_by_user_id')->nullable()->default(null);
$table->integer('created_at_timestamp');
$this->references($table, 'users', 'edited_by_user_id')->nullable()->default(null);
$table->integer('edited_at_timestamp');
$table->uuid('transaction_id')->nullable()->default(null)->index();
});
/** @var stdClass[] $records */
$records = $connection
->table('shifts_old')
->get();
$now = Carbon::now()->getTimestamp();
foreach ($records as $record) {
$createdAt = $record->created_at ? Carbon::make($record->created_at)->getTimestamp() : $now;
$updatedAt = $record->updated_at ? Carbon::make($record->updated_at)->getTimestamp() : $createdAt;
$connection->table('Shifts')->insert([
'SID' => $record->id,
'title' => $record->title,
'shifttype_id' => $record->shift_type_id,
'description' => $record->description ?: null,
'start' => Carbon::make($record->start)->getTimestamp(),
'end' => Carbon::make($record->end)->getTimestamp(),
'RID' => $record->room_id,
'URL' => $record->url ?: null,
'created_by_user_id' => $record->created_by,
'created_at_timestamp' => $createdAt,
'edited_by_user_id' => $record->updated_by,
'edited_at_timestamp' => $updatedAt,
'transaction_id' => $record->transaction_id,
]);
}
$this->changeReferences(
'shifts_old',
'id',
'Shifts',
'SID'
);
$this->schema->drop('shifts_old');
}
}

View File

@ -1,114 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateShiftEntriesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('ShiftEntry');
$this->schema->create('shift_entries', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'shifts');
$this->references($table, 'angel_types');
$this->referencesUser($table);
$table->mediumText('user_comment')->default('');
$table->boolean('freeloaded')->default(false)->index();
$table->mediumText('freeloaded_comment')->default('');
$table->index(['angel_type_id', 'shift_id']);
});
if (!$previous) {
return;
}
/** @var stdClass[] $records */
$records = $connection
->table('ShiftEntry')
->get();
foreach ($records as $record) {
$connection->table('shift_entries')->insert([
'id' => $record->id,
'shift_id' => $record->SID,
'angel_type_id' => $record->TID,
'user_id' => $record->UID,
'user_comment' => $record->Comment,
'freeloaded' => (bool) $record->freeloaded,
'freeloaded_comment' => $record->freeload_comment,
]);
}
$this->changeReferences(
'ShiftEntry',
'id',
'shift_entries',
'id'
);
$this->schema->drop('ShiftEntry');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('ShiftEntry', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'shifts', 'SID')->default(0);
$this->references($table, 'angel_types', 'TID')->default(0);
$this->references($table, 'users', 'UID')->default(0);
$table->mediumText('Comment')->nullable();
$table->mediumText('freeload_comment')->nullable()->default(null);
$table->boolean('freeloaded')->index();
$table->index(['SID', 'TID']);
});
/** @var stdClass[] $records */
$records = $connection
->table('shift_entries')
->get();
foreach ($records as $record) {
$connection->table('ShiftEntry')->insert([
'id' => $record->id,
'SID' => $record->shift_id,
'TID' => $record->angel_type_id,
'UID' => $record->user_id,
'Comment' => $record->user_comment,
'freeloaded' => (bool) $record->freeloaded,
'freeload_comment' => $record->freeloaded_comment,
]);
}
$this->changeReferences(
'shift_entries',
'id',
'ShiftEntry',
'id'
);
$this->schema->drop('shift_entries');
}
}

View File

@ -1,108 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
use stdClass;
class CreateNeededAngelTypesTable extends Migration
{
use ChangesReferences;
use Reference;
/**
* Creates the new table, copies the data and drops the old one
*/
public function up(): void
{
$connection = $this->schema->getConnection();
$previous = $this->schema->hasTable('NeededAngelTypes');
$this->schema->create('needed_angel_types', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'rooms')->nullable();
$this->references($table, 'shifts')->nullable();
$this->references($table, 'angel_types');
$table->integer('count')->index();
$table->index(['room_id', 'angel_type_id']);
});
if (!$previous) {
return;
}
// Delete old entries which don't need angels
$connection
->table('NeededAngelTypes')
->where('count', 0)
->delete();
/** @var stdClass[] $records */
$records = $connection
->table('NeededAngelTypes')
->get();
foreach ($records as $record) {
$connection->table('needed_angel_types')->insert([
'id' => $record->id,
'room_id' => $record->room_id,
'shift_id' => $record->shift_id,
'angel_type_id' => $record->angel_type_id,
'count' => $record->count,
]);
}
$this->changeReferences(
'NeededAngelTypes',
'id',
'needed_angel_types',
'id'
);
$this->schema->drop('NeededAngelTypes');
}
/**
* Recreates the previous table, copies the data and drops the new one
*/
public function down(): void
{
$connection = $this->schema->getConnection();
$this->schema->create('NeededAngelTypes', function (Blueprint $table): void {
$table->increments('id');
$this->references($table, 'rooms')->nullable();
$this->references($table, 'shifts')->nullable();
$this->references($table, 'angel_types');
$table->integer('count')->index();
$table->index(['room_id', 'angel_type_id']);
});
/** @var stdClass[] $records */
$records = $connection
->table('needed_angel_types')
->get();
foreach ($records as $record) {
$connection->table('NeededAngelTypes')->insert([
'id' => $record->id,
'room_id' => $record->room_id,
'shift_id' => $record->shift_id,
'angel_type_id' => $record->angel_type_id,
'count' => $record->count,
]);
}
$this->changeReferences(
'needed_angel_types',
'id',
'NeededAngelTypes',
'id'
);
$this->schema->drop('needed_angel_types');
}
}

View File

@ -1,42 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class AddSetNewsFlagImportantPermissions extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$db = $this->schema->getConnection();
$db->table('privileges')
->insert(['name' => 'news.important', 'description' => 'Make News Important']);
$newsImportant = $db->table('privileges')
->where('name', 'news.important')
->get(['id'])
->first();
$buerocrat = 80;
$db->table('group_privileges')
->insertOrIgnore([
['group_id' => $buerocrat, 'privilege_id' => $newsImportant->id],
]);
}
/**
* Reverse the migration
*/
public function down(): void
{
$db = $this->schema->getConnection();
$db->table('privileges')
->where(['name' => 'news.important'])
->delete();
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddIsImportantToNews extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('news', function (Blueprint $table): void {
$table->boolean('is_important')->default(false)->after('is_pinned');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('news', function (Blueprint $table): void {
$table->dropColumn('is_important');
});
}
}

View File

@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class FixEmailMessagesMigrationName extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$this->schema->getConnection()
->table('migrations')
->where('migration', '2023_02_26_000000_AddEmailMessagesToUsersSettings')
->update([
'migration' => '2023_02_26_000000_add_email_messages_to_users_settings',
]);
}
// Down migration not needed when on same version
}

View File

@ -1,33 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddEmailMessagesToUsersSettings extends Migration
{
use Reference;
/**
* Run the migration
*/
public function up(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->boolean('email_messages')->default(false)->after('email_human');
});
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->schema->table('users_settings', function (Blueprint $table): void {
$table->dropColumn('email_messages');
});
}
}

View File

@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
class RenameShirtManager extends Migration
{
/**
* Run the migration
*/
public function up(): void
{
$db = $this->schema->getConnection();
$db->table('groups')
->where('name', 'Shirt Manager')
->update(['name' => 'Goodie Manager']);
}
/**
* Reverse the migration
*/
public function down(): void
{
$db = $this->schema->getConnection();
$db->table('groups')
->where('name', 'Goodie Manager')
->update(['name' => 'Shirt Manager']);
}
}

Some files were not shown because too many files have changed in this diff Show More