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
max_line_length = 120
[{.babelrc,package.json,.eslintrc.json,.prettierrc.json}]
[{.babelrc,package.json}]
indent_size = 2
[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
/config/config.php
/config/lang/
/public/*.xml
/public/coverage
/test/coverage
/public/coverage
/coverage
/unittests.xml
/resources/lang/*/*.mo
@ -42,4 +40,3 @@ _vimrc_local.vim
/public/assets
/package-lock.json
/yarn-error.log
/.yarn-cache

View File

@ -12,7 +12,6 @@ variables:
DOCROOT: /var/www/
stages:
- prepare
- validate
- build
- test
@ -21,90 +20,44 @@ stages:
- deploy-production
- 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
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:
- composer --no-ansi validate --strict
composer install:
<<: *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:
validate-yarn:
image: node:alpine
stage: prepare
stage: validate
before_script:
- yarn global add package-json-validator
- export PATH=$PATH:~/.yarn/bin
script:
- 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:
image: alpine
stage: prepare
stage: validate
artifacts:
name: "${CI_JOB_NAME}_${CI_JOB_ID}_version"
expire_in: 1 day
@ -117,44 +70,6 @@ generate-version:
- echo "${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
#
@ -172,24 +87,39 @@ build-image:
<<: *container_definition
stage: build
needs:
- phpcs
- phpstan
- composer validate
- yarn check
- yarn lint
- check-editorconfig
- check-style
- generate-version
- validate-composer
- validate-yarn
dependencies:
- generate-version
script:
- /kaniko/executor --context ${CI_PROJECT_DIR}
--dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile
--destination "${TEST_IMAGE}"
--cache=true
#
# 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:
image:
name: ${TEST_IMAGE}
@ -218,7 +148,7 @@ test:
- ./bin/migrate
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/"
--log-junit "${HOMEDIR}/unittests.xml"
after_script:
@ -271,11 +201,7 @@ release-image:
- test
dependencies: [ ]
script:
- echo -e "FROM ${TEST_IMAGE}"
| /kaniko/executor
--dockerfile /dev/stdin
--destination "${RELEASE_IMAGE}"
--cache=true
- echo -e "FROM ${TEST_IMAGE}" | /kaniko/executor --dockerfile /dev/stdin --destination "${RELEASE_IMAGE}"
only:
- main
@ -292,8 +218,8 @@ build-release-file:
stage: release
needs:
- build-image
- yarn audit
- composer audit
- audit-yarn
- audit-composer
- test
- dump-database
- generate-assets
@ -348,7 +274,6 @@ deploy:
dependencies: *deploy_needs
environment:
name: rsync-staging
deployment_tier: development
only:
- main
script:
@ -371,10 +296,7 @@ deploy:
- test
- build-image
before_script:
- &kubectl_deployment_script |-
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
- &kubectl_deployment_script if [[ -z "${KUBE_INGRESS_BASE_DOMAIN}" ]]; then echo "Skipping deployment"; exit; fi
.deploy_k8s: &deploy_k8s
<<: *kubectl_deployment
@ -389,12 +311,8 @@ deploy:
# 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_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_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
# 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}"}
@ -403,24 +321,19 @@ deploy:
- export CI_CLUSTER_ISSUER=${CI_CLUSTER_ISSUER:-letsencrypt}
- export CI_SETUP_ADMIN_PASSWORD=${CI_SETUP_ADMIN_PASSWORD}
- echo "Generating config"
- cp deployment.tpl.yaml deployment.yaml
- >-
for env in ${!CI_*}; do
sed -i "s#<${env}>#$( echo "${!env}" | head -n1 | sed -e 's~\\~\\\\~' -e 's~#~\\#~' )#g" deployment.yaml;
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}"
- kubectl -n "${CI_KUBE_NAMESPACE}" diff -f deployment.yaml || true
- kubectl -n "${CI_KUBE_NAMESPACE}" apply -f deployment.yaml
- kubectl 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
- >-
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
.deploy_k8s_stop: &deploy_k8s_stop
@ -440,7 +353,6 @@ deploy-k8s-review:
on_stop: stop-k8s-review
auto_stop_in: 1 week
url: https://${CI_PROJECT_PATH_SLUG}-review.${KUBE_INGRESS_BASE_DOMAIN}/${CI_COMMIT_REF_SLUG}
deployment_tier: development
variables:
CI_REPLICAS_REVIEW: 1
CI_APP_NAME: review/${CI_COMMIT_REF_NAME}
@ -454,7 +366,6 @@ stop-k8s-review:
environment:
name: review/${CI_COMMIT_REF_NAME}
action: stop
deployment_tier: development
#
# Deploy production
@ -465,8 +376,8 @@ deploy-production:
stage: deploy-production
needs:
- test
- yarn audit
- composer audit
- audit-yarn
- audit-composer
- build-image
- generate-assets
dependencies:
@ -474,7 +385,6 @@ deploy-production:
- generate-assets
environment:
name: rsync-production
deployment_tier: production
when: manual
only:
- main
@ -494,8 +404,8 @@ deploy-k8s-production:
stage: deploy-production
needs:
- release-image
- yarn audit
- composer audit
- audit-yarn
- audit-composer
environment:
name: production
on_stop: stop-k8s-production

View File

@ -4,11 +4,9 @@
<file>config</file>
<file>db</file>
<file>includes</file>
<file>public/index.php</file>
<file>src</file>
<file>tests</file>
<exclude-pattern>/config/config.php</exclude-pattern>
<rule ref="PSR12" />
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
@ -21,32 +19,4 @@
<property name="ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach" value="true" />
</properties>
</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>

View File

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

View File

@ -2,30 +2,12 @@
## 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.
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.
* Code must pass PHPStan checks (`composer phpstan`)
* Order the composer/npm dependencies alphabetically.
* 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, 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 code from the [includes](./includes) directory anywhere else.
* Please cover your code by unit tests. Code under `includes` does not require tests.
* Do not use vendor prefixes like `-webkit` in styles.
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).
This is done by PostCSS + Autoprefixer according to the [`.browserslistrc`](./.browserslistrc).
## Pull requests
* The PR should contain a short overview of the changes.
* 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.
Please create single pull requests for every feature instead of creating one big monster of pull request containing a complete rewrite.

View File

@ -8,86 +8,7 @@ Please also read the [CONTRIBUTING.md](CONTRIBUTING.md).
* Yarn (Development/Building only)
* PHP Composer (Development/Building only)
## 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
```
## 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
## Local build
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`
@ -118,7 +39,7 @@ The following instructions explain how to get, build and run the latest Engelsys
```
## Testing
To run only unit tests (tests that should not change the Engelsystem state) use
To run the unit tests use
```bash
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!
```bash
vendor/bin/phpunit --testsuite Feature
```
When you want to run unit and feature tests at once:
```bash
# or for unit- and feature tests:
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.
```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
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`.
@ -168,7 +74,7 @@ To view the output of `dump` call the following commands:
```bash
vendor/bin/var-dump-server
# 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)
@ -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.
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
@ -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
```
## 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
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***

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).
### Requirements
* PHP >= 8.1
* PHP >= 7.4
* Required modules:
* dom
* 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.
### Configuration and Setup
* 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 read the `.htaccess` file and `mod_rewrite` must be enabled
* 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 read the ```.htaccess``` file and ```mod_rewrite``` must be enabled
* Recommended: Directory Listing should be disabled.
* 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`.
* 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.
* In the browser, login with credentials `admin` : `asdfasdf` and change the password.
* 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 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.
The Engelsystem can now be used.
@ -55,7 +55,7 @@ The Engelsystem can now be used.
To build the `es_server` container:
```bash
cd docker
docker compose build
docker-compose build
```
or to build the container by its own:
@ -67,14 +67,14 @@ docker build -f docker/Dockerfile . -t es_server
Start the Engelsystem
```bash
cd docker
docker compose up -d
docker-compose up -d
```
#### Migrate
Import database changes to migrate it to the newest version
```bash
cd docker
docker compose exec es_server bin/migrate
docker-compose exec es_server bin/migrate
```
### Scripts

View File

@ -4,9 +4,7 @@
use Composer\Autoload\ClassLoader;
use Engelsystem\Application;
use Engelsystem\Database\Migration\Migrate;
use Engelsystem\Database\Migration\Direction;
use Engelsystem\Database\Migration\MigrationServiceProvider;
use Engelsystem\Environment;
use Engelsystem\Exceptions\Handler;
use Engelsystem\Exceptions\Handlers\NullHandler;
@ -21,7 +19,7 @@ $app->register(MigrationServiceProvider::class);
/** @var Handler $errorHandler */
$errorHandler = $app->get(Handler::class);
$errorHandler->setHandler(Environment::PRODUCTION, new NullHandler());
$errorHandler->setHandler(Handler::ENV_PRODUCTION, new NullHandler());
/** @var Migrate $migration */
$migration = $app->get('db.migration');
@ -34,10 +32,10 @@ if (in_array('help', $argv) || in_array('--help', $argv) || in_array('-h', $argv
exit;
}
$direction = Direction::UP;
$method = Migrate::UP;
if (in_array('down', $argv)) {
$argv = array_values($argv);
$direction = Direction::DOWN;
$method = Migrate::DOWN;
}
$oneStep = false;
@ -50,4 +48,4 @@ if (in_array('force', $argv) || in_array('--force', $argv) || in_array('-f', $ar
$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": {
"phpcs:setup": "phpcs --config-set php_version 80100",
"phpcs": [
"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/"
"phpcs": "phpcs -p",
"phpcbf": "phpcbf -p"
},
"require": {
"php": ">=8.1.0",
"php": ">=7.4.0",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"doctrine/dbal": "^3.5",
"doctrine/dbal": "^3.2",
"erusev/parsedown": "^1.7",
"gettext/gettext": "^5.7",
"gettext/translator": "^1.1",
"guzzlehttp/guzzle": "^7.5",
"illuminate/container": "^9.43",
"illuminate/database": "^9.43",
"illuminate/support": "^9.43",
"gettext/gettext": "^5.6",
"gettext/translator": "^1.0",
"guzzlehttp/guzzle": "^7.4",
"illuminate/container": "^8.76",
"illuminate/database": "^8.76",
"illuminate/support": "^8.76",
"league/oauth2-client": "^2.6",
"nikic/fast-route": "^1.3",
"nyholm/psr7": "^1.5",
"psr/container": "^2.0",
"nyholm/psr7": "^1.4",
"psr/container": "^1.1",
"psr/http-server-middleware": "^1.0",
"psr/log": "^3.0",
"psr/log": "^1.1",
"rcrowe/twigbridge": "^0.14.0",
"respect/validation": "^1.1",
"symfony/http-foundation": "^6.2",
"symfony/mailer": "^6.2",
"symfony/http-foundation": "^5.4",
"symfony/mailer": "^5.4",
"symfony/psr-http-message-bridge": "^2.1",
"twig/twig": "^3.4",
"vlucas/phpdotenv": "^5.5"
"twig/twig": "^3.3",
"vlucas/phpdotenv": "^5.4"
},
"require-dev": {
"dms/phpunit-arraysubset-asserts": "^0.4",
"fakerphp/faker": "^1.20",
"fig/log-test": "^1.1",
"dms/phpunit-arraysubset-asserts": "^0.3.1",
"fakerphp/faker": "^1.17",
"filp/whoops": "^2.14",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^9.5",
"slevomat/coding-standard": "^8.6",
"squizlabs/php_codesniffer": "^3.7",
"symfony/var-dumper": "^6.2"
"slevomat/coding-standard": "^7.1",
"squizlabs/php_codesniffer": "^3.6",
"symfony/var-dumper": "^5.4"
},
"autoload": {
"psr-4": {

2250
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
// Application config
return [
@ -48,7 +46,6 @@ return [
// Changes of request/response parameters
\Engelsystem\Middleware\SetLocale::class,
\Engelsystem\Middleware\ETagHandler::class,
\Engelsystem\Middleware\AddHeaders::class,
// The application code
@ -67,19 +64,11 @@ return [
// a list of
// 'Class@method' or 'Class' (which uses @handle),
// ['Class', 'method'],
// callable like [$instance, 'method'] or 'function'
// callable like [$instance, 'method] or 'function'
// or $function
// ]
'message.created' => \Engelsystem\Events\Listener\Messages::class . '@created',
'news.created' => \Engelsystem\Events\Listener\News::class . '@created',
'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
declare(strict_types=1);
// To change settings create a config.php
return [
@ -13,19 +11,19 @@ return [
'password' => env('MYSQL_PASSWORD', ''),
],
// For accessing /metrics (and /stats)
'api_key' => env('API_KEY', ''),
// For accessing stats
'api_key' => '',
// Enable maintenance mode (show a static page)
'maintenance' => (bool)env('MAINTENANCE', false),
// Application name (not the event name)
// Application name (not the event name!)
'app_name' => env('APP_NAME', 'Engelsystem'),
// Set to development to enable debugging messages
'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),
// Header links
@ -47,7 +45,7 @@ return [
'faq_text' => env('FAQ_TEXT', null),
// Link to documentation/help
'documentation_url' => env('DOCUMENTATION_URL', 'https://engelsystem.de/doc/'),
'documentation_url' => 'https://engelsystem.de/doc/',
// Email config
'email' => [
@ -69,7 +67,7 @@ return [
],
# Your privacy@ contact address
'privacy_email' => env('PRIVACY_EMAIL', null),
'privacy_email' => '',
// Initial admin password
'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null),
@ -90,8 +88,6 @@ return [
'url_token' => '[generated by provider]',
// User info URL which provides userdata
'url_info' => '[generated by provider]',
// OAuth Scopes
// 'scope' => ['openid'],
// Info unique user id field
'id' => 'uuid',
// The following fields are used for registration
@ -218,7 +214,7 @@ return [
// Must be one of news, meetings, user_shifts, angeltypes, questions
'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),
// Users are able to sign up
@ -250,7 +246,7 @@ return [
// Define the algorithm to use for `password_verify()`
// 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
'password_algorithm' => env('PASSWORD_ALGORITHM', PASSWORD_DEFAULT),
'password_algorithm' => PASSWORD_DEFAULT,
// The minimum length for passwords
'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8),
@ -263,31 +259,20 @@ return [
// Whether the DECT field should be enabled
'enable_dect' => (bool)env('ENABLE_DECT', true),
// Whether the mobile number can be shown to other users
'enable_mobile_show' => (bool) env('ENABLE_MOBILE_SHOW', 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
// Enables prename and lastname
'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_pronoun' => (bool)env('ENABLE_PRONOUN', true),
// Enables the planned arrival/leave date
'enable_planned_arrival' => (bool)env('ENABLE_PLANNED_ARRIVAL', true),
// Resembles the Goodie Type. There are three options:
// 'none' => no goodie at all
// 'goodie' => a goodie which has no sizing options
// 'tshirt' => goodie that is called tshirt and has sizing options
'goodie_type' => env('GOODIE_TYPE', 'goodie'),
// Enables the T-Shirt configuration on signup and profile
'enable_tshirt_size' => (bool)env('ENABLE_TSHIRT_SIZE', true),
// Enables the goody configuration on signup and profile
'enable_goody' => (bool)env('ENABLE_GOODY', false),
// Enables the food voucher in the user profile
'enable_voucher' => (bool)env('ENABLE_VOUCHER', true),
@ -295,11 +280,8 @@ return [
// Number of shifts to freeload until angel is locked for shift signup.
'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
'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
'night_shifts' => [
@ -360,9 +342,6 @@ return [
// Cookie name
'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
@ -385,7 +364,7 @@ return [
'credits' => [
'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) '
. 'or need help.',
. 'or need help.'
],
// var dump server

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
use FastRoute\RouteCollector;
/** @var RouteCollector $route */
@ -17,195 +15,114 @@ $route->post('/login', 'AuthController@postLogin');
$route->get('/logout', 'AuthController@logout');
// OAuth
$route->addGroup(
'/oauth/{provider}',
function (RouteCollector $route): void {
$route->get('', 'OAuthController@index');
$route->post('/connect', 'OAuthController@connect');
$route->post('/disconnect', 'OAuthController@disconnect');
}
);
$route->get('/oauth/{provider}', 'OAuthController@index');
$route->post('/oauth/{provider}/connect', 'OAuthController@connect');
$route->post('/oauth/{provider}/disconnect', 'OAuthController@disconnect');
// User settings
$route->addGroup(
'/settings',
function (RouteCollector $route): void {
$route->get('/profile', 'SettingsController@profile');
$route->post('/profile', 'SettingsController@saveProfile');
$route->get('/password', 'SettingsController@password');
$route->post('/password', 'SettingsController@savePassword');
$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');
}
);
$route->get('/settings/password', 'SettingsController@password');
$route->post('/settings/password', 'SettingsController@savePassword');
$route->get('/settings/theme', 'SettingsController@theme');
$route->post('/settings/theme', 'SettingsController@saveTheme');
$route->get('/settings/language', 'SettingsController@language');
$route->post('/settings/language', 'SettingsController@saveLanguage');
$route->get('/settings/oauth', 'SettingsController@oauth');
// Password recovery
$route->addGroup(
'/password/reset',
function (RouteCollector $route): void {
$route->get('', 'PasswordResetController@reset');
$route->post('', 'PasswordResetController@postReset');
$route->get('/{token:.+}', 'PasswordResetController@resetPassword');
$route->post('/{token:.+}', 'PasswordResetController@postResetPassword');
}
);
$route->get('/password/reset', 'PasswordResetController@reset');
$route->post('/password/reset', 'PasswordResetController@postReset');
$route->get('/password/reset/{token:.+}', 'PasswordResetController@resetPassword');
$route->post('/password/reset/{token:.+}', 'PasswordResetController@postResetPassword');
// Stats
$route->get('/metrics', 'Metrics\\Controller@metrics');
$route->get('/stats', 'Metrics\\Controller@stats');
// Angeltypes
$route->addGroup('/angeltypes', function (RouteCollector $route): void {
$route->get('/about', 'AngelTypesController@about');
});
// News
$route->get('/news', 'NewsController@index');
$route->get('/meetings', 'NewsController@meetings');
$route->addGroup(
'/news',
function (RouteCollector $route): void {
$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');
}
);
$route->get('/news/{id:\d+}', 'NewsController@show');
$route->post('/news/{id:\d+}', 'NewsController@comment');
$route->post('/news/comment/{id:\d+}', 'NewsController@deleteComment');
// FAQ
$route->get('/faq', 'FaqController@index');
// Questions
$route->addGroup(
'/questions',
function (RouteCollector $route): void {
$route->get('', 'QuestionsController@index');
$route->post('', 'QuestionsController@delete');
$route->get('/new', 'QuestionsController@add');
$route->post('/new', 'QuestionsController@save');
}
);
$route->get('/questions', 'QuestionsController@index');
$route->post('/questions', 'QuestionsController@delete');
$route->get('/questions/new', 'QuestionsController@add');
$route->post('/questions/new', 'QuestionsController@save');
// Messages
$route->addGroup(
'/messages',
function (RouteCollector $route): void {
$route->get('', 'MessagesController@index');
$route->post('', 'MessagesController@redirectToConversation');
$route->get('/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->post('/{user_id:\d+}', 'MessagesController@send');
$route->post('/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
}
);
$route->get('/messages', 'MessagesController@index');
$route->post('/messages', 'MessagesController@redirectToConversation');
$route->get('/messages/{user_id:\d+}', 'MessagesController@messagesOfConversation');
$route->post('/messages/{user_id:\d+}', 'MessagesController@send');
$route->post('/messages/{user_id:\d+}/{msg_id:\d+}', 'MessagesController@delete');
// API
$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
$route->get('/design', 'DesignController@index');
// Administration
$route->addGroup(
'/admin',
function (RouteCollector $route): void {
function (RouteCollector $route) {
// FAQ
$route->addGroup(
'/faq',
function (RouteCollector $route): void {
$route->get('[/{faq_id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{faq_id:\d+}]', 'Admin\\FaqController@save');
function (RouteCollector $route) {
$route->get('[/{id:\d+}]', 'Admin\\FaqController@edit');
$route->post('[/{id:\d+}]', 'Admin\\FaqController@save');
}
);
// Log
$route->addGroup(
'/logs',
function (RouteCollector $route): void {
$route->get('', 'Admin\\LogsController@index');
$route->post('', 'Admin\\LogsController@index');
}
);
$route->get('/logs', 'Admin\\LogsController@index');
$route->post('/logs', 'Admin\\LogsController@index');
// Schedule
$route->addGroup(
'/schedule',
function (RouteCollector $route): void {
function (RouteCollector $route) {
$route->get('', 'Admin\\Schedule\\ImportSchedule@index');
$route->get('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit');
$route->post('/edit[/{schedule_id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save');
$route->get('/load/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule');
$route->post('/import/{schedule_id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule');
$route->get('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@edit');
$route->post('/edit[/{id:\d+}]', 'Admin\\Schedule\\ImportSchedule@save');
$route->get('/load/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@loadSchedule');
$route->post('/import/{id:\d+}', 'Admin\\Schedule\\ImportSchedule@importSchedule');
}
);
// Questions
$route->addGroup(
'/questions',
function (RouteCollector $route): void {
function (RouteCollector $route) {
$route->get('', 'Admin\\QuestionsController@index');
$route->post('', 'Admin\\QuestionsController@delete');
$route->get('/{question_id:\d+}', 'Admin\\QuestionsController@edit');
$route->post('/{question_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');
$route->get('/{id:\d+}', 'Admin\\QuestionsController@edit');
$route->post('/{id:\d+}', 'Admin\\QuestionsController@save');
}
);
// User
$route->addGroup(
'/user/{user_id:\d+}',
function (RouteCollector $route): void {
'/user/{id:\d+}',
// Shirts
$route->addGroup(
'/goodie',
function (RouteCollector $route): void {
$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'
);
}
);
function (RouteCollector $route) {
$route->get('/shirt', 'Admin\\UserShirtController@editShirt');
$route->post('/shirt', 'Admin\\UserShirtController@saveShirt');
}
);
// News
$route->addGroup(
'/news',
function (RouteCollector $route): void {
$route->get('[/{news_id:\d+}]', 'Admin\\NewsController@edit');
$route->post('[/{news_id:\d+}]', 'Admin\\NewsController@save');
function (RouteCollector $route) {
$route->get('[/{id:\d+}]', 'Admin\\NewsController@edit');
$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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Faq;
@ -10,9 +8,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class FaqFactory extends Factory
{
/** @var string */
protected $model = Faq::class; // phpcs:ignore
protected $model = Faq::class;
public function definition(): array
/**
* @return array
*/
public function definition()
{
return [
'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
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models;
use Engelsystem\Models\Message;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class MessageFactory extends Factory
{
/** @var string */
protected $model = Message::class; // phpcs:ignore
protected $model = Message::class;
public function definition(): array
/**
* @return array
*/
public function definition()
{
return [
'user_id' => User::factory(),

View File

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

View File

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

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\License;
@ -10,9 +8,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class LicenseFactory extends Factory
{
/** @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_3_5t = $drive_car && $this->faker->boolean(.7);

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class PersonalDataFactory extends Factory
{
/** @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');
$departure = $this->faker->optional()->dateTimeThisMonth('2 weeks');

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Database\Factories\Engelsystem\Models\User;
use Carbon\Carbon;
@ -11,9 +9,12 @@ use Illuminate\Database\Eloquent\Factories\Factory;
class StateFactory extends Factory
{
/** @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();
@ -29,8 +30,10 @@ class StateFactory extends Factory
/**
* Indicate that the user is arrived
*
* @return self
*/
public function arrived(): self
public function arrived()
{
return $this->state(
function (array $attributes) {

View File

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

View File

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

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -12,7 +10,7 @@ class FixOldTables extends Migration
/**
* Run the migration
*/
public function up(): void
public function up()
{
$connection = $this->schema->getConnection();
@ -31,9 +29,16 @@ class FixOldTables extends Migration
->where($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();
});
}
}
/**
* Reverse the migration
*/
public function down()
{
}
}

View File

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

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class CreateLogEntriesTable extends 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->string('level', 20);
$table->text('message');
@ -34,9 +32,9 @@ class CreateLogEntriesTable extends 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->string('level', 20);
$table->text('message');

View File

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

View File

@ -1,18 +1,16 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Carbon\Carbon;
use Engelsystem\Database\Migration\Migration;
use Engelsystem\Models\EventConfig;
use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;
class CreateEventConfigTable extends Migration
{
protected array $mapping = [
protected $mapping = [
'buildup_start_date' => 'buildup_start',
'event_start_date' => 'event_start',
'event_end_date' => 'event_end',
@ -22,11 +20,11 @@ class CreateEventConfigTable extends Migration
/**
* Run the migration
*/
public function up(): void
public function up()
{
foreach (['json', 'text'] as $type) {
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->{$type}('value');
$table->timestamps();
@ -43,24 +41,26 @@ class CreateEventConfigTable extends Migration
}
if ($this->schema->hasTable('EventConfig')) {
$connection = $this->schema->getConnection();
$config = $connection
$config = $this->schema->getConnection()
->table('EventConfig')
->first();
if (!empty($config)) {
$connection->table('event_config')
->insert([
['name' => 'name', 'value' => $config->event_name],
['name' => 'welcome_msg', 'value' => $config->event_welcome_msg],
]);
(new EventConfig([
'name' => 'name',
'value' => $config->event_name,
]))->save();
(new EventConfig([
'name' => 'welcome_msg',
'value' => $config->event_welcome_msg,
]))->save();
foreach ($this->mapping as $old => $new) {
$connection->table('event_config')
->insert([
(new EventConfig([
'name' => $new,
'value' => (new Carbon())->setTimestamp($config->{$old}),
]);
]))->save();
}
}
@ -71,11 +71,9 @@ class CreateEventConfigTable extends Migration
/**
* Reverse the migration
*/
public function down(): void
public function down()
{
$connection = $this->schema->getConnection();
$this->schema->create('EventConfig', function (Blueprint $table): void {
$this->schema->create('EventConfig', function (Blueprint $table) {
$table->string('event_name')->nullable();
$table->integer('buildup_start_date')->nullable();
$table->integer('event_start_date')->nullable();
@ -84,19 +82,19 @@ class CreateEventConfigTable extends Migration
$table->string('event_welcome_msg')->nullable();
});
$config = $connection->table('event_config')->get();
$config = new EventConfig();
$data = [
'event_name' => $this->getConfigValue($config, 'name'),
'event_welcome_msg' => $this->getConfigValue($config, 'welcome_msg'),
'event_name' => $config->findOrNew('name')->value,
'event_welcome_msg' => $config->findOrNew('welcome_msg')->value,
];
foreach ($this->mapping as $new => $old) {
$value = $this->getConfigValue($config, $old);
/** @var Carbon $value */
$value = $config->findOrNew($old)->value;
if (!$value) {
continue;
}
$value = Carbon::make($value);
$data[$new] = $value->getTimestamp();
}
@ -113,11 +111,4 @@ class CreateEventConfigTable extends Migration
$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
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Carbon\Carbon;
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 stdClass;
@ -17,9 +21,9 @@ class CreateUsersTables extends 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->string('name', 24)->unique();
@ -31,7 +35,7 @@ class CreateUsersTables extends Migration
$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);
$table->string('first_name', 64)->nullable();
@ -42,7 +46,7 @@ class CreateUsersTables extends Migration
$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);
$table->string('dect', 5)->nullable();
@ -50,7 +54,7 @@ class CreateUsersTables extends Migration
$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);
$table->string('language', 64);
@ -59,7 +63,7 @@ class CreateUsersTables extends Migration
$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);
$table->boolean('arrived')->default(false);
@ -70,7 +74,7 @@ class CreateUsersTables extends Migration
$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);
$table->text('token');
@ -79,33 +83,33 @@ class CreateUsersTables extends Migration
});
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'];
/** @var stdClass[] $users */
$users = $connection->table('User')->get();
$users = $this->schema->getConnection()->table('User')->get();
foreach ($users as $data) {
$user = [
'id' => $data->UID,
$user = new User([
'name' => $data->Nick,
'password' => $data->Passwort,
'email' => $data->email,
'api_key' => $data->api_key,
'last_login_at' => $data->lastLogIn ? Carbon::createFromTimestamp($data->lastLogIn) : null,
];
]);
$user->setAttribute('id', $data->UID);
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([
'user_id' => $data->UID,
'dect' => $data->DECT ?: null,
$contact = new Contact([
'dect' => $data->DECT ? $data->DECT : null,
'mobile' => $data->Handy ?: ($data->Telefon ?: null),
]);
$contact->user()
->associate($user)
->save();
$connection->table('users_personal_data')->insert([
'user_id' => $data->UID,
$personalData = new PersonalData([
'first_name' => $data->Vorname ?: null,
'last_name' => $data->Name ?: null,
'shirt_size' => $data->Size ?: null,
@ -116,17 +120,24 @@ class CreateUsersTables extends Migration
? Carbon::createFromTimestamp($data->planned_departure_date)
: null,
]);
$personalData->user()
->associate($user)
->save();
$connection->table('users_settings')->insert([
'user_id' => $data->UID,
$settings = new Settings([
'language' => $data->Sprache,
'theme' => $data->color,
'email_human' => $data->email_by_human_allowed,
'email_shiftinfo' => $data->email_shiftinfo,
]);
unset($settings->email_news);
unset($settings->email_goody);
$connection->table('users_state')->insert([
'user_id' => $data->UID,
$settings->user()
->associate($user)
->save();
$state = new State([
'arrived' => $data->Gekommen,
'arrival_date' => $data->arrival_date ? Carbon::createFromTimestamp($data->arrival_date) : null,
'active' => $data->Aktiv,
@ -134,12 +145,17 @@ class CreateUsersTables extends Migration
'got_shirt' => $data->Tshirt,
'got_voucher' => $data->got_voucher,
]);
$state->user()
->associate($user)
->save();
if ($data->password_recovery_token) {
$connection->table('password_resets')->insert([
'user_id' => $data->UID,
$passwordReset = new PasswordReset([
'token' => $data->password_recovery_token,
]);
$passwordReset->user()
->associate($user)
->save();
}
}
@ -157,12 +173,10 @@ class CreateUsersTables extends Migration
/**
* Reverse the migration
*/
public function down(): void
public function down()
{
$connection = $this->schema->getConnection();
$this->schema->create('User', function (Blueprint $table): void {
$table->integer('UID', true);
$this->schema->create('User', function (Blueprint $table) {
$table->integer('UID', true, false);
$table->string('Nick', 23)->unique()->default('');
$table->string('Name', 23)->nullable();
@ -203,16 +217,12 @@ class CreateUsersTables extends Migration
$table->index('planned_departure_date', 'planned_departure_date');
});
foreach ($connection->table('users')->get() as $user) {
/** @var stdClass $user */
/** @var stdClass $contact */
$contact = $connection->table('users_contact')->where('user_id', $user->id)->first();
/** @var stdClass $personal */
$personal = $connection->table('users_personal_data')->where('user_id', $user->id)->first();
/** @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();
foreach (User::all() as $user) {
/** @var User $user */
$contact = $user->contact;
$personal = $user->personalData;
$settings = $user->settings;
$state = $user->state;
$this->schema
->getConnection()
@ -234,28 +244,23 @@ class CreateUsersTables extends Migration
'Tshirt' => $state->got_shirt,
'color' => $settings->theme,
'Sprache' => $settings->language,
'lastLogIn' => $user->last_login_at
? Carbon::make($user->last_login_at)->getTimestamp()
: null,
'CreateDate' => $user->created_at
? Carbon::make($user->created_at)->toDateTimeString()
: '0001-01-01 00:00:00',
'lastLogIn' => $user->last_login_at ? $user->last_login_at->getTimestamp() : null,
'CreateDate' => $user->created_at ? $user->created_at->toDateTimeString() : null,
'api_key' => $user->api_key,
'got_voucher' => $state->got_voucher,
'arrival_date' => $state->arrival_date
? Carbon::make($state->arrival_date)->getTimestamp()
: null,
'arrival_date' => $state->arrival_date ? $state->arrival_date->getTimestamp() : null,
'planned_arrival_date' => $personal->planned_arrival_date
? Carbon::make($personal->planned_arrival_date)->getTimestamp()
: 0,
? $personal->planned_arrival_date->getTimestamp()
: null,
'planned_departure_date' => $personal->planned_departure_date
? Carbon::make($personal->planned_departure_date)->getTimestamp()
? $personal->planned_departure_date->getTimestamp()
: null,
'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()
->table('User')
->where('UID', '=', $passwordReset->user_id)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -14,20 +12,26 @@ class AddEmailNewsToUsersSettings extends 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');
});
}
);
}
/**
* 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');
});
}
);
}
}

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -14,24 +12,30 @@ class OauthAddTokens extends 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('refresh_token')->nullable()->default(null)->after('access_token');
$table->dateTime('expires_at')->nullable()->default(null)->after('refresh_token');
});
}
);
}
/**
* 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('refresh_token');
$table->dropColumn('expires_at');
});
}
);
}
}

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -14,20 +12,26 @@ class NewsAddIsPinned extends 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');
});
}
);
}
/**
* 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');
});
}
);
}
}

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -14,22 +12,28 @@ class OauthChangeTokensToText extends 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('refresh_token')->change();
});
}
);
}
/**
* 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('refresh_token')->change();
});
}
);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -12,9 +10,9 @@ class IncreaseSessionsTablePayloadSize extends 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();
});
}
@ -22,9 +20,9 @@ class IncreaseSessionsTablePayloadSize extends 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();
});
}

View File

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

View File

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

View File

@ -1,7 +1,5 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
@ -15,9 +13,9 @@ class IncreaseTshirtFieldWidth extends 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();
});
}
@ -25,9 +23,9 @@ class IncreaseTshirtFieldWidth extends 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();
});
}

View File

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

View File

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