diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d7c41ed2d..7a66c8486 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -113,7 +113,14 @@ generate-version:
before_script:
- apk add -q git
script:
- - VERSION="$(git describe --abbrev=0 --tags)-${CI_COMMIT_REF_NAME}+${CI_PIPELINE_ID}.${CI_COMMIT_SHORT_SHA}"
+ - >
+ VERSION="$(\
+ git describe --exact-match --tags HEAD 2> /dev/null\
+ || (\
+ (git describe --abbrev=0 --tags | tr -d '\n')\
+ && echo "-${CI_COMMIT_REF_NAME}+${CI_PIPELINE_ID}.${CI_COMMIT_SHORT_SHA}"\
+ )\
+ )"
- echo "${VERSION}"
- echo -n "${VERSION}" > storage/app/VERSION
@@ -155,6 +162,15 @@ yarn lint:
- apk add --no-cache git
- yarn lint
+translations lint:
+ image: alpine
+ stage: prepare
+ before_script:
+ - apk add gettext
+ script:
+ - find resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
+ - '[[ $(find resources/lang -type f -name "*.po" | wc -l) == $(find resources/lang -type f -name "*.mo" | wc -l) ]]'
+
#
# Build
#
@@ -177,6 +193,7 @@ build-image:
- composer validate
- yarn check
- yarn lint
+ - translations lint
- generate-version
dependencies:
- generate-version
@@ -184,6 +201,7 @@ build-image:
- /kaniko/executor --context ${CI_PROJECT_DIR}
--dockerfile ${CI_PROJECT_DIR}/docker/Dockerfile
--destination "${TEST_IMAGE}"
+ --cache=true
#
# Test
@@ -241,6 +259,9 @@ dump-database:
- cd "${DOCROOT}"
- ./bin/migrate
script:
+ - >-
+ mysql -h "${MYSQL_HOST}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}"
+ -e 'UPDATE users SET api_key="" WHERE name="admin"'
- >-
mysqldump -h "${MYSQL_HOST}" -u "${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}"
> "${HOMEDIR}/initial-install.sql"
@@ -270,7 +291,11 @@ release-image:
- test
dependencies: [ ]
script:
- - echo -e "FROM ${TEST_IMAGE}" | /kaniko/executor --dockerfile /dev/stdin --destination "${RELEASE_IMAGE}"
+ - echo -e "FROM ${TEST_IMAGE}"
+ | /kaniko/executor
+ --dockerfile /dev/stdin
+ --destination "${RELEASE_IMAGE}"
+ --cache=true
only:
- main
@@ -426,7 +451,8 @@ deploy:
GIT_STRATEGY: none
when: manual
script:
- - kubectl delete all,ingress,pvc -l app=$CI_PROJECT_PATH_SLUG -l environment=$CI_ENVIRONMENT_SLUG
+ - TARGETS=all,ingress,pvc,certificate
+ - kubectl -n "${KUBE_NAMESPACE}" delete $TARGETS -l app=$CI_PROJECT_PATH_SLUG -l environment=$CI_ENVIRONMENT_SLUG
deploy-k8s-review:
<<: *deploy_k8s
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6f775e381..0d043be70 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -7,6 +7,7 @@
* 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 vendor prefixes like `-webkit` in styles.
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index d2a03217f..49f8ed054 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -13,10 +13,14 @@ Please ensure that your pull requests follow the [PSR-12](https://www.php-fig.or
You can check that by running
```bash
composer run phpcs
+# with docker
+docker exec engelsystem_dev-es_workspace-1 composer run phpcs
```
You may auto fix reported issues by running
```bash
composer run phpcbf
+# with docker
+docker exec engelsystem_dev-es_workspace-1 composer run phpcbf
```
## Pre-commit hooks
@@ -68,7 +72,7 @@ docker compose exec es_workspace yarn build
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"' \;
+docker compose exec es_workspace find /var/www/resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
# Run the migrations
docker compose exec es_workspace bin/migrate
@@ -114,7 +118,7 @@ The following instructions explain how to get, build and run the latest Engelsys
```
* Generate translation files
```bash
- find resources/lang/ -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
+ find resources/lang/ -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
```
## Testing
diff --git a/README.md b/README.md
index 82c7cd574..28b0184dc 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ The Engelsystem may be installed manually or by using the provided [docker setup
* 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 disable/remove values from the `themes`, `tshirt_sizes`, `headers`, `header_items`, `footer_items`, or `locales` lists, set the value of the entry to `null`.
* 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.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 000000000..943cc598b
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,16 @@
+# Security Policy
+
+## Reporting a Vulnerability
+
+If you want to contact us directly regarding a security concern, please write an e-mail to contact@engelsystem.de and explain your findings.
+Thank you!
+
+## Use of external reporting / bug bounty services
+
+We kindly ask you to not use any external reporting / bug bounty service. We do not collaborate with any external service and experiences in the past showed that these services usually add a lot of unnecessary overhead.
+
+Please send security critical bug reports to contact@engelsystem.de.
+
+If you feel like we are not reacting fast enough (generally no more than 14 days should go by until an initial response; This is a volunteer project mostly used internally after all), please feel free to go for full disclosure via our github issue tracker, and tag the issue there by creating a title prefixed with [SECURITY].
+
+If you find a critical vulnerability that warrants a CVE, we will also take care of issuing a CVE without any bug bounty platform having to be involved.
diff --git a/bin/pre-commit b/bin/pre-commit
index 8049b2d12..252b92988 100755
--- a/bin/pre-commit
+++ b/bin/pre-commit
@@ -3,10 +3,24 @@
# immediate exit after an error
set -e
+testing() {
+ echo
+ echo "π Checking ${1}"
+}
+
+testing 'JS & CSS π¨'
yarn check
yarn lint
+testing 'PHP βοΈ'
composer validate
composer phpcs
composer phpstan
./vendor/bin/phpunit
+
+testing 'translations πΊοΈ'
+find resources/lang -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
+[ "$(find resources/lang -type f -name '*.po' | wc -l)" -eq "$(find resources/lang -type f -name '*.mo' | wc -l)" ]
+find resources/lang -type f -name '*.mo' -exec rm {} \;
+
+echo 'β
Done π'
diff --git a/composer.json b/composer.json
index 0db0769c8..120de0eb2 100644
--- a/composer.json
+++ b/composer.json
@@ -35,38 +35,40 @@
"ext-pdo": "*",
"ext-simplexml": "*",
"ext-xml": "*",
- "doctrine/dbal": "^3.5",
+ "doctrine/dbal": "^3.7",
"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",
- "league/oauth2-client": "^2.6",
+ "gettext/translator": "^1.2",
+ "guzzlehttp/guzzle": "^7.8",
+ "illuminate/container": "^10.38",
+ "illuminate/database": "^10.38",
+ "illuminate/support": "^10.38",
+ "league/oauth2-client": "^2.7",
+ "league/openapi-psr7-validator": "^0.21",
"nikic/fast-route": "^1.3",
- "nyholm/psr7": "^1.5",
+ "nyholm/psr7": "^1.8",
"psr/container": "^2.0",
+ "psr/http-message": "^1.1",
"psr/http-server-middleware": "^1.0",
"psr/log": "^3.0",
- "rcrowe/twigbridge": "^0.14.0",
+ "rcrowe/twigbridge": "^0.14.1",
"respect/validation": "^1.1",
- "symfony/http-foundation": "^6.2",
- "symfony/mailer": "^6.2",
- "symfony/psr-http-message-bridge": "^2.1",
- "twig/twig": "^3.4",
- "vlucas/phpdotenv": "^5.5"
+ "symfony/http-foundation": "^6.4",
+ "symfony/mailer": "^6.4",
+ "symfony/psr-http-message-bridge": "^2.3",
+ "twig/twig": "^3.8",
+ "vlucas/phpdotenv": "^5.6"
},
"require-dev": {
- "dms/phpunit-arraysubset-asserts": "^0.4",
- "fakerphp/faker": "^1.20",
+ "dms/phpunit-arraysubset-asserts": "^0.5",
+ "fakerphp/faker": "^1.23",
"fig/log-test": "^1.1",
- "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"
+ "filp/whoops": "^2.15",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.14",
+ "squizlabs/php_codesniffer": "^3.8",
+ "symfony/var-dumper": "^6.4"
},
"autoload": {
"psr-4": {
diff --git a/composer.lock b/composer.lock
index b3d3d59ee..89a94e0b7 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,206 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "4b1eba8f27aab7aa6bd462a28843fd8c",
+ "content-hash": "df9efe0dff1f7d311e20747637f1b49f",
"packages": [
+ {
+ "name": "brick/math",
+ "version": "0.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/brick/math.git",
+ "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478",
+ "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.2",
+ "phpunit/phpunit": "^9.0",
+ "vimeo/psalm": "5.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Brick\\Math\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Arbitrary-precision arithmetic library",
+ "keywords": [
+ "Arbitrary-precision",
+ "BigInteger",
+ "BigRational",
+ "arithmetic",
+ "bigdecimal",
+ "bignum",
+ "brick",
+ "math"
+ ],
+ "support": {
+ "issues": "https://github.com/brick/math/issues",
+ "source": "https://github.com/brick/math/tree/0.11.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/BenMorel",
+ "type": "github"
+ }
+ ],
+ "time": "2023-01-15T23:15:59+00:00"
+ },
+ {
+ "name": "carbonphp/carbon-doctrine-types",
+ "version": "2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git",
+ "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb",
+ "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/dbal": "<3.7.0 || >=4.0.0"
+ },
+ "require-dev": {
+ "doctrine/dbal": "^3.7.0",
+ "nesbot/carbon": "^2.71.0 || ^3.0.0",
+ "phpunit/phpunit": "^10.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Carbon\\Doctrine\\": "src/Carbon/Doctrine/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "KyleKatarn",
+ "email": "kylekatarnls@gmail.com"
+ }
+ ],
+ "description": "Types to use Carbon in Doctrine",
+ "keywords": [
+ "carbon",
+ "date",
+ "datetime",
+ "doctrine",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues",
+ "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/kylekatarnls",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/Carbon",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-11T17:09:12+00:00"
+ },
+ {
+ "name": "devizzent/cebe-php-openapi",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/DEVizzent/cebe-php-openapi.git",
+ "reference": "de3a406a1fa5daa275da3f6aed6765c170de7954"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DEVizzent/cebe-php-openapi/zipball/de3a406a1fa5daa275da3f6aed6765c170de7954",
+ "reference": "de3a406a1fa5daa275da3f6aed6765c170de7954",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "justinrainbow/json-schema": "^5.2",
+ "php": ">=7.1.0",
+ "symfony/yaml": "^3.4 || ^4 || ^5 || ^6"
+ },
+ "conflict": {
+ "symfony/yaml": "3.4.0 - 3.4.4 || 4.0.0 - 4.4.17 || 5.0.0 - 5.1.9 || 5.2.0"
+ },
+ "require-dev": {
+ "apis-guru/openapi-directory": "1.0.0",
+ "cebe/indent": "*",
+ "mermade/openapi3-examples": "1.0.0",
+ "nexmo/api-specification": "1.0.0",
+ "oai/openapi-specification-3.0": "3.0.3",
+ "oai/openapi-specification-3.1": "3.1.0",
+ "phpstan/phpstan": "^0.12.0",
+ "phpunit/phpunit": "^6.5 || ^7.5 || ^8.5 || ^9.4"
+ },
+ "bin": [
+ "bin/php-openapi"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "cebe\\openapi\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Carsten Brandt",
+ "email": "mail@cebe.cc",
+ "homepage": "https://cebe.cc/",
+ "role": "Creator"
+ },
+ {
+ "name": "Vicent Valls",
+ "email": "vizzent@gmail.com"
+ }
+ ],
+ "description": "Read and write OpenAPI yaml/json files and make the content accessable in PHP objects.",
+ "homepage": "https://github.com/DEVizzent/cebe-php-openapi#readme",
+ "keywords": [
+ "openapi"
+ ],
+ "support": {
+ "issues": "https://github.com/DEVizzent/cebe-php-openapi/issues",
+ "source": "https://github.com/DEVizzent/cebe-php-openapi"
+ },
+ "time": "2023-10-26T20:41:58+00:00"
+ },
{
"name": "doctrine/cache",
"version": "2.2.0",
@@ -101,16 +299,16 @@
},
{
"name": "doctrine/dbal",
- "version": "3.5.1",
+ "version": "3.7.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "f38ee8aaca2d58ee88653cb34a6a3880c23f38a5"
+ "reference": "0ac3c270590e54910715e9a1a044cc368df282b2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/f38ee8aaca2d58ee88653cb34a6a3880c23f38a5",
- "reference": "f38ee8aaca2d58ee88653cb34a6a3880c23f38a5",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2",
+ "reference": "0ac3c270590e54910715e9a1a044cc368df282b2",
"shasum": ""
},
"require": {
@@ -123,16 +321,18 @@
"psr/log": "^1|^2|^3"
},
"require-dev": {
- "doctrine/coding-standard": "10.0.0",
- "jetbrains/phpstorm-stubs": "2022.2",
- "phpstan/phpstan": "1.8.10",
- "phpstan/phpstan-strict-rules": "^1.4",
- "phpunit/phpunit": "9.5.25",
- "psalm/plugin-phpunit": "0.17.0",
- "squizlabs/php_codesniffer": "3.7.1",
+ "doctrine/coding-standard": "12.0.0",
+ "fig/log-test": "^1",
+ "jetbrains/phpstorm-stubs": "2023.1",
+ "phpstan/phpstan": "1.10.42",
+ "phpstan/phpstan-strict-rules": "^1.5",
+ "phpunit/phpunit": "9.6.13",
+ "psalm/plugin-phpunit": "0.18.4",
+ "slevomat/coding-standard": "8.13.1",
+ "squizlabs/php_codesniffer": "3.7.2",
"symfony/cache": "^5.4|^6.0",
"symfony/console": "^4.4|^5.4|^6.0",
- "vimeo/psalm": "4.29.0"
+ "vimeo/psalm": "4.30.0"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
@@ -192,7 +392,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
- "source": "https://github.com/doctrine/dbal/tree/3.5.1"
+ "source": "https://github.com/doctrine/dbal/tree/3.7.2"
},
"funding": [
{
@@ -208,29 +408,33 @@
"type": "tidelift"
}
],
- "time": "2022-10-24T07:26:18+00:00"
+ "time": "2023-11-19T08:06:58+00:00"
},
{
"name": "doctrine/deprecations",
- "version": "v1.0.0",
+ "version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
- "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de"
+ "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
- "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
+ "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
"shasum": ""
},
"require": {
- "php": "^7.1|^8.0"
+ "php": "^7.1 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^9",
- "phpunit/phpunit": "^7.5|^8.5|^9.5",
- "psr/log": "^1|^2|^3"
+ "phpstan/phpstan": "1.4.10 || 1.10.15",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "psalm/plugin-phpunit": "0.18.4",
+ "psr/log": "^1 || ^2 || ^3",
+ "vimeo/psalm": "4.30.0 || 5.12.0"
},
"suggest": {
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
@@ -249,9 +453,9 @@
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
- "source": "https://github.com/doctrine/deprecations/tree/v1.0.0"
+ "source": "https://github.com/doctrine/deprecations/tree/1.1.2"
},
- "time": "2022-05-02T15:47:09+00:00"
+ "time": "2023-09-27T20:04:15+00:00"
},
{
"name": "doctrine/event-manager",
@@ -346,28 +550,28 @@
},
{
"name": "doctrine/inflector",
- "version": "2.0.6",
+ "version": "2.0.8",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
- "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024"
+ "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
- "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
+ "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
- "doctrine/coding-standard": "^10",
+ "doctrine/coding-standard": "^11.0",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
- "vimeo/psalm": "^4.25"
+ "vimeo/psalm": "^4.25 || ^5.4"
},
"type": "library",
"autoload": {
@@ -417,7 +621,7 @@
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
- "source": "https://github.com/doctrine/inflector/tree/2.0.6"
+ "source": "https://github.com/doctrine/inflector/tree/2.0.8"
},
"funding": [
{
@@ -433,35 +637,36 @@
"type": "tidelift"
}
],
- "time": "2022-10-20T09:10:12+00:00"
+ "time": "2023-06-16T13:40:37+00:00"
},
{
"name": "doctrine/lexer",
- "version": "1.2.3",
+ "version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
- "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229"
+ "reference": "84a527db05647743d50373e0ec53a152f2cde568"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229",
- "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568",
+ "reference": "84a527db05647743d50373e0ec53a152f2cde568",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0"
+ "php": "^8.1"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0",
- "phpstan/phpstan": "^1.3",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
- "vimeo/psalm": "^4.11"
+ "doctrine/coding-standard": "^10",
+ "phpstan/phpstan": "^1.9",
+ "phpunit/phpunit": "^9.5",
+ "psalm/plugin-phpunit": "^0.18.3",
+ "vimeo/psalm": "^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
+ "Doctrine\\Common\\Lexer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -493,7 +698,7 @@
],
"support": {
"issues": "https://github.com/doctrine/lexer/issues",
- "source": "https://github.com/doctrine/lexer/tree/1.2.3"
+ "source": "https://github.com/doctrine/lexer/tree/3.0.0"
},
"funding": [
{
@@ -509,31 +714,30 @@
"type": "tidelift"
}
],
- "time": "2022-02-28T11:07:21+00:00"
+ "time": "2022-12-15T16:57:16+00:00"
},
{
"name": "egulias/email-validator",
- "version": "3.2.1",
+ "version": "4.0.2",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
- "reference": "f88dcf4b14af14a98ad96b14b2b317969eab6715"
+ "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/f88dcf4b14af14a98ad96b14b2b317969eab6715",
- "reference": "f88dcf4b14af14a98ad96b14b2b317969eab6715",
+ "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e",
+ "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e",
"shasum": ""
},
"require": {
- "doctrine/lexer": "^1.2",
- "php": ">=7.2",
- "symfony/polyfill-intl-idn": "^1.15"
+ "doctrine/lexer": "^2.0 || ^3.0",
+ "php": ">=8.1",
+ "symfony/polyfill-intl-idn": "^1.26"
},
"require-dev": {
- "php-coveralls/php-coveralls": "^2.2",
- "phpunit/phpunit": "^8.5.8|^9.3.3",
- "vimeo/psalm": "^4"
+ "phpunit/phpunit": "^10.2",
+ "vimeo/psalm": "^5.12"
},
"suggest": {
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
@@ -541,7 +745,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0.x-dev"
+ "dev-master": "4.0.x-dev"
}
},
"autoload": {
@@ -569,7 +773,7 @@
],
"support": {
"issues": "https://github.com/egulias/EmailValidator/issues",
- "source": "https://github.com/egulias/EmailValidator/tree/3.2.1"
+ "source": "https://github.com/egulias/EmailValidator/tree/4.0.2"
},
"funding": [
{
@@ -577,7 +781,7 @@
"type": "github"
}
],
- "time": "2022-06-18T20:57:19+00:00"
+ "time": "2023-10-06T06:47:41+00:00"
},
{
"name": "erusev/parsedown",
@@ -779,16 +983,16 @@
},
{
"name": "gettext/translator",
- "version": "v1.1.1",
+ "version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/php-gettext/Translator.git",
- "reference": "b18ff33e8203de623854561f5e47e992fc5c50bb"
+ "reference": "a4fa5ed740f304a0ed7b3e169b2b554a195c7570"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-gettext/Translator/zipball/b18ff33e8203de623854561f5e47e992fc5c50bb",
- "reference": "b18ff33e8203de623854561f5e47e992fc5c50bb",
+ "url": "https://api.github.com/repos/php-gettext/Translator/zipball/a4fa5ed740f304a0ed7b3e169b2b554a195c7570",
+ "reference": "a4fa5ed740f304a0ed7b3e169b2b554a195c7570",
"shasum": ""
},
"require": {
@@ -833,7 +1037,7 @@
"support": {
"email": "oom@oscarotero.com",
"issues": "https://github.com/php-gettext/Translator/issues",
- "source": "https://github.com/php-gettext/Translator/tree/v1.1.1"
+ "source": "https://github.com/php-gettext/Translator/tree/v1.2.0"
},
"funding": [
{
@@ -849,28 +1053,28 @@
"type": "patreon"
}
],
- "time": "2022-02-23T20:29:40+00:00"
+ "time": "2023-11-06T15:42:03+00:00"
},
{
"name": "graham-campbell/result-type",
- "version": "v1.1.0",
+ "version": "v1.1.2",
"source": {
"type": "git",
"url": "https://github.com/GrahamCampbell/Result-Type.git",
- "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8"
+ "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8",
- "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8",
+ "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/fbd48bce38f73f8a4ec8583362e732e4095e5862",
+ "reference": "fbd48bce38f73f8a4ec8583362e732e4095e5862",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
- "phpoption/phpoption": "^1.9"
+ "phpoption/phpoption": "^1.9.2"
},
"require-dev": {
- "phpunit/phpunit": "^8.5.28 || ^9.5.21"
+ "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
},
"type": "library",
"autoload": {
@@ -899,7 +1103,7 @@
],
"support": {
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
- "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0"
+ "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.2"
},
"funding": [
{
@@ -911,26 +1115,26 @@
"type": "tidelift"
}
],
- "time": "2022-07-30T15:56:11+00:00"
+ "time": "2023-11-12T22:16:48+00:00"
},
{
"name": "guzzlehttp/guzzle",
- "version": "7.5.0",
+ "version": "7.8.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
- "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba"
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba",
- "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104",
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104",
"shasum": ""
},
"require": {
"ext-json": "*",
- "guzzlehttp/promises": "^1.5",
- "guzzlehttp/psr7": "^1.9 || ^2.4",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0.1",
+ "guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
@@ -939,10 +1143,11 @@
"psr/http-client-implementation": "1.0"
},
"require-dev": {
- "bamarni/composer-bin-plugin": "^1.8.1",
+ "bamarni/composer-bin-plugin": "^1.8.2",
"ext-curl": "*",
- "php-http/client-integration-tests": "^3.0",
- "phpunit/phpunit": "^8.5.29 || ^9.5.23",
+ "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
@@ -955,9 +1160,6 @@
"bamarni-bin": {
"bin-links": true,
"forward-command": false
- },
- "branch-alias": {
- "dev-master": "7.5-dev"
}
},
"autoload": {
@@ -1023,7 +1225,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
- "source": "https://github.com/guzzle/guzzle/tree/7.5.0"
+ "source": "https://github.com/guzzle/guzzle/tree/7.8.1"
},
"funding": [
{
@@ -1039,38 +1241,37 @@
"type": "tidelift"
}
],
- "time": "2022-08-28T15:39:27+00:00"
+ "time": "2023-12-03T20:35:24+00:00"
},
{
"name": "guzzlehttp/promises",
- "version": "1.5.2",
+ "version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "b94b2807d85443f9719887892882d0329d1e2598"
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
- "reference": "b94b2807d85443f9719887892882d0329d1e2598",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223",
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223",
"shasum": ""
},
"require": {
- "php": ">=5.5"
+ "php": "^7.2.5 || ^8.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "1.5-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
}
},
"autoload": {
- "files": [
- "src/functions_include.php"
- ],
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
@@ -1107,7 +1308,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/1.5.2"
+ "source": "https://github.com/guzzle/promises/tree/2.0.2"
},
"funding": [
{
@@ -1123,26 +1324,26 @@
"type": "tidelift"
}
],
- "time": "2022-08-28T14:55:35+00:00"
+ "time": "2023-12-03T20:19:20+00:00"
},
{
"name": "guzzlehttp/psr7",
- "version": "2.4.3",
+ "version": "2.6.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
- "reference": "67c26b443f348a51926030c83481b85718457d3d"
+ "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d",
- "reference": "67c26b443f348a51926030c83481b85718457d3d",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221",
+ "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0",
- "psr/http-message": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0"
},
"provide": {
@@ -1150,9 +1351,9 @@
"psr/http-message-implementation": "1.0"
},
"require-dev": {
- "bamarni/composer-bin-plugin": "^1.8.1",
+ "bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "^0.9",
- "phpunit/phpunit": "^8.5.29 || ^9.5.23"
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
@@ -1162,9 +1363,6 @@
"bamarni-bin": {
"bin-links": true,
"forward-command": false
- },
- "branch-alias": {
- "dev-master": "2.4-dev"
}
},
"autoload": {
@@ -1226,7 +1424,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
- "source": "https://github.com/guzzle/psr7/tree/2.4.3"
+ "source": "https://github.com/guzzle/psr7/tree/2.6.2"
},
"funding": [
{
@@ -1242,28 +1440,28 @@
"type": "tidelift"
}
],
- "time": "2022-10-26T14:07:24+00:00"
+ "time": "2023-12-03T20:05:35+00:00"
},
{
"name": "illuminate/bus",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/bus.git",
- "reference": "c7f09872054f2b361f8ed9e9e988b3c9be06c596"
+ "reference": "8db4b00a3f6071075e9f08094c6c7b059f8deddf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/bus/zipball/c7f09872054f2b361f8ed9e9e988b3c9be06c596",
- "reference": "c7f09872054f2b361f8ed9e9e988b3c9be06c596",
+ "url": "https://api.github.com/repos/illuminate/bus/zipball/8db4b00a3f6071075e9f08094c6c7b059f8deddf",
+ "reference": "8db4b00a3f6071075e9f08094c6c7b059f8deddf",
"shasum": ""
},
"require": {
- "illuminate/collections": "^9.0",
- "illuminate/contracts": "^9.0",
- "illuminate/pipeline": "^9.0",
- "illuminate/support": "^9.0",
- "php": "^8.0.2"
+ "illuminate/collections": "^10.0",
+ "illuminate/contracts": "^10.0",
+ "illuminate/pipeline": "^10.0",
+ "illuminate/support": "^10.0",
+ "php": "^8.1"
},
"suggest": {
"illuminate/queue": "Required to use closures when chaining jobs (^7.0)."
@@ -1271,7 +1469,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1295,35 +1493,35 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-11-25T07:56:47+00:00"
+ "time": "2023-12-15T14:09:57+00:00"
},
{
"name": "illuminate/collections",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
- "reference": "7a8afa0875d7de162f30865d9fae33c8fb235fa2"
+ "reference": "63fc240a047788fbc2ebe153de85cb72fce88440"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/collections/zipball/7a8afa0875d7de162f30865d9fae33c8fb235fa2",
- "reference": "7a8afa0875d7de162f30865d9fae33c8fb235fa2",
+ "url": "https://api.github.com/repos/illuminate/collections/zipball/63fc240a047788fbc2ebe153de85cb72fce88440",
+ "reference": "63fc240a047788fbc2ebe153de85cb72fce88440",
"shasum": ""
},
"require": {
- "illuminate/conditionable": "^9.0",
- "illuminate/contracts": "^9.0",
- "illuminate/macroable": "^9.0",
- "php": "^8.0.2"
+ "illuminate/conditionable": "^10.0",
+ "illuminate/contracts": "^10.0",
+ "illuminate/macroable": "^10.0",
+ "php": "^8.1"
},
"suggest": {
- "symfony/var-dumper": "Required to use the dump method (^6.0)."
+ "symfony/var-dumper": "Required to use the dump method (^6.2)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1350,20 +1548,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-12-02T18:48:05+00:00"
+ "time": "2023-12-21T14:17:35+00:00"
},
{
"name": "illuminate/conditionable",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/conditionable.git",
- "reference": "5b40f51ccb07e0e7b1ec5559d8db9e0e2dc51883"
+ "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/conditionable/zipball/5b40f51ccb07e0e7b1ec5559d8db9e0e2dc51883",
- "reference": "5b40f51ccb07e0e7b1ec5559d8db9e0e2dc51883",
+ "url": "https://api.github.com/repos/illuminate/conditionable/zipball/d0958e4741fc9d6f516a552060fd1b829a85e009",
+ "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009",
"shasum": ""
},
"require": {
@@ -1372,7 +1570,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1396,25 +1594,25 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-07-29T19:44:19+00:00"
+ "time": "2023-02-03T08:06:17+00:00"
},
{
"name": "illuminate/container",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
- "reference": "8ca3036459e26dc7cdedaf0f882b625757cc341e"
+ "reference": "ddc26273085fad3c471b2602ad820e0097ff7939"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/container/zipball/8ca3036459e26dc7cdedaf0f882b625757cc341e",
- "reference": "8ca3036459e26dc7cdedaf0f882b625757cc341e",
+ "url": "https://api.github.com/repos/illuminate/container/zipball/ddc26273085fad3c471b2602ad820e0097ff7939",
+ "reference": "ddc26273085fad3c471b2602ad820e0097ff7939",
"shasum": ""
},
"require": {
- "illuminate/contracts": "^9.0",
- "php": "^8.0.2",
+ "illuminate/contracts": "^10.0",
+ "php": "^8.1",
"psr/container": "^1.1.1|^2.0.1"
},
"provide": {
@@ -1423,7 +1621,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1447,31 +1645,31 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-09-05T15:58:42+00:00"
+ "time": "2023-06-18T09:12:03+00:00"
},
{
"name": "illuminate/contracts",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
- "reference": "c7cc6e6198cac6dfdead111f9758de25413188b7"
+ "reference": "f6bf37a272fda164f6c451407c99f820eb1eb95b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/contracts/zipball/c7cc6e6198cac6dfdead111f9758de25413188b7",
- "reference": "c7cc6e6198cac6dfdead111f9758de25413188b7",
+ "url": "https://api.github.com/repos/illuminate/contracts/zipball/f6bf37a272fda164f6c451407c99f820eb1eb95b",
+ "reference": "f6bf37a272fda164f6c451407c99f820eb1eb95b",
"shasum": ""
},
"require": {
- "php": "^8.0.2",
+ "php": "^8.1",
"psr/container": "^1.1.1|^2.0.1",
"psr/simple-cache": "^1.0|^2.0|^3.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1495,45 +1693,50 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-10-31T22:25:40+00:00"
+ "time": "2023-10-30T00:59:22+00:00"
},
{
"name": "illuminate/database",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/database.git",
- "reference": "9d08866faf75adee93e354315ae68c86915d1541"
+ "reference": "f014850671278a8d1a0e9fd2f421aad5b487ab9e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/database/zipball/9d08866faf75adee93e354315ae68c86915d1541",
- "reference": "9d08866faf75adee93e354315ae68c86915d1541",
+ "url": "https://api.github.com/repos/illuminate/database/zipball/f014850671278a8d1a0e9fd2f421aad5b487ab9e",
+ "reference": "f014850671278a8d1a0e9fd2f421aad5b487ab9e",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "illuminate/collections": "^9.0",
- "illuminate/container": "^9.0",
- "illuminate/contracts": "^9.0",
- "illuminate/macroable": "^9.0",
- "illuminate/support": "^9.0",
- "php": "^8.0.2",
- "symfony/console": "^6.0.9"
+ "brick/math": "^0.9.3|^0.10.2|^0.11",
+ "ext-pdo": "*",
+ "illuminate/collections": "^10.0",
+ "illuminate/container": "^10.0",
+ "illuminate/contracts": "^10.0",
+ "illuminate/macroable": "^10.0",
+ "illuminate/support": "^10.0",
+ "php": "^8.1"
+ },
+ "conflict": {
+ "carbonphp/carbon-doctrine-types": ">=3.0",
+ "doctrine/dbal": ">=4.0"
},
"suggest": {
- "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).",
- "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).",
- "illuminate/console": "Required to use the database commands (^9.0).",
- "illuminate/events": "Required to use the observers with Eloquent (^9.0).",
- "illuminate/filesystem": "Required to use the migrations (^9.0).",
- "illuminate/pagination": "Required to paginate the result set (^9.0).",
- "symfony/finder": "Required to use Eloquent model factories (^6.0)."
+ "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).",
+ "ext-filter": "Required to use the Postgres database driver.",
+ "fakerphp/faker": "Required to use the eloquent factory builder (^1.21).",
+ "illuminate/console": "Required to use the database commands (^10.0).",
+ "illuminate/events": "Required to use the observers with Eloquent (^10.0).",
+ "illuminate/filesystem": "Required to use the migrations (^10.0).",
+ "illuminate/pagination": "Required to paginate the result set (^10.0).",
+ "symfony/finder": "Required to use Eloquent model factories (^6.2)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1563,35 +1766,35 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-12-02T15:12:12+00:00"
+ "time": "2023-12-21T01:49:42+00:00"
},
{
"name": "illuminate/events",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/events.git",
- "reference": "8e534676bac23bc17925f5c74c128f9c09b98f69"
+ "reference": "8d84d6220a6b3446a0bf3e4138e2eb0e10792bb1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/events/zipball/8e534676bac23bc17925f5c74c128f9c09b98f69",
- "reference": "8e534676bac23bc17925f5c74c128f9c09b98f69",
+ "url": "https://api.github.com/repos/illuminate/events/zipball/8d84d6220a6b3446a0bf3e4138e2eb0e10792bb1",
+ "reference": "8d84d6220a6b3446a0bf3e4138e2eb0e10792bb1",
"shasum": ""
},
"require": {
- "illuminate/bus": "^9.0",
- "illuminate/collections": "^9.0",
- "illuminate/container": "^9.0",
- "illuminate/contracts": "^9.0",
- "illuminate/macroable": "^9.0",
- "illuminate/support": "^9.0",
- "php": "^8.0.2"
+ "illuminate/bus": "^10.0",
+ "illuminate/collections": "^10.0",
+ "illuminate/container": "^10.0",
+ "illuminate/contracts": "^10.0",
+ "illuminate/macroable": "^10.0",
+ "illuminate/support": "^10.0",
+ "php": "^8.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1618,48 +1821,53 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-09-15T13:14:12+00:00"
+ "time": "2023-10-30T00:59:35+00:00"
},
{
"name": "illuminate/filesystem",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/filesystem.git",
- "reference": "3e29c07c25e759a99ec09377838e3926e33d9f5f"
+ "reference": "c765c61cf1308d4f5f3dc3c03ed5f920953b795c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/filesystem/zipball/3e29c07c25e759a99ec09377838e3926e33d9f5f",
- "reference": "3e29c07c25e759a99ec09377838e3926e33d9f5f",
+ "url": "https://api.github.com/repos/illuminate/filesystem/zipball/c765c61cf1308d4f5f3dc3c03ed5f920953b795c",
+ "reference": "c765c61cf1308d4f5f3dc3c03ed5f920953b795c",
"shasum": ""
},
"require": {
- "illuminate/collections": "^9.0",
- "illuminate/contracts": "^9.0",
- "illuminate/macroable": "^9.0",
- "illuminate/support": "^9.0",
- "php": "^8.0.2",
- "symfony/finder": "^6.0"
+ "illuminate/collections": "^10.0",
+ "illuminate/contracts": "^10.0",
+ "illuminate/macroable": "^10.0",
+ "illuminate/support": "^10.0",
+ "php": "^8.1",
+ "symfony/finder": "^6.2"
},
"suggest": {
+ "ext-fileinfo": "Required to use the Filesystem class.",
"ext-ftp": "Required to use the Flysystem FTP driver.",
+ "ext-hash": "Required to use the Filesystem class.",
"illuminate/http": "Required for handling uploaded files (^7.0).",
"league/flysystem": "Required to use the Flysystem local driver (^3.0.16).",
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).",
"league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).",
"league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).",
"psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
- "symfony/filesystem": "Required to enable support for relative symbolic links (^6.0).",
- "symfony/mime": "Required to enable support for guessing extensions (^6.0)."
+ "symfony/filesystem": "Required to enable support for relative symbolic links (^6.2).",
+ "symfony/mime": "Required to enable support for guessing extensions (^6.2)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
+ "files": [
+ "functions.php"
+ ],
"psr-4": {
"Illuminate\\Filesystem\\": ""
}
@@ -1680,29 +1888,29 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-11-17T14:45:11+00:00"
+ "time": "2023-12-21T15:30:21+00:00"
},
{
"name": "illuminate/macroable",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/macroable.git",
- "reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a"
+ "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/macroable/zipball/e3bfaf6401742a9c6abca61b9b10e998e5b6449a",
- "reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a",
+ "url": "https://api.github.com/repos/illuminate/macroable/zipball/dff667a46ac37b634dcf68909d9d41e94dc97c27",
+ "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27",
"shasum": ""
},
"require": {
- "php": "^8.0.2"
+ "php": "^8.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1726,31 +1934,31 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-08-09T13:29:29+00:00"
+ "time": "2023-06-05T12:46:42+00:00"
},
{
"name": "illuminate/pipeline",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/pipeline.git",
- "reference": "e0be3f3f79f8235ad7334919ca4094d5074e02f6"
+ "reference": "f802187e917a171332cc90f8c1a102939c57405d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/pipeline/zipball/e0be3f3f79f8235ad7334919ca4094d5074e02f6",
- "reference": "e0be3f3f79f8235ad7334919ca4094d5074e02f6",
+ "url": "https://api.github.com/repos/illuminate/pipeline/zipball/f802187e917a171332cc90f8c1a102939c57405d",
+ "reference": "f802187e917a171332cc90f8c1a102939c57405d",
"shasum": ""
},
"require": {
- "illuminate/contracts": "^9.0",
- "illuminate/support": "^9.0",
- "php": "^8.0.2"
+ "illuminate/contracts": "^10.0",
+ "illuminate/support": "^10.0",
+ "php": "^8.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1774,50 +1982,51 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-06-09T14:13:53+00:00"
+ "time": "2023-12-19T14:47:26+00:00"
},
{
"name": "illuminate/support",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
- "reference": "f3ec55d0f6256cb9da7e13fe758c75b443895226"
+ "reference": "a9f486d76d5403b0c95b8532cd151a0a960f9565"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/support/zipball/f3ec55d0f6256cb9da7e13fe758c75b443895226",
- "reference": "f3ec55d0f6256cb9da7e13fe758c75b443895226",
+ "url": "https://api.github.com/repos/illuminate/support/zipball/a9f486d76d5403b0c95b8532cd151a0a960f9565",
+ "reference": "a9f486d76d5403b0c95b8532cd151a0a960f9565",
"shasum": ""
},
"require": {
"doctrine/inflector": "^2.0",
- "ext-json": "*",
+ "ext-ctype": "*",
+ "ext-filter": "*",
"ext-mbstring": "*",
- "illuminate/collections": "^9.0",
- "illuminate/conditionable": "^9.0",
- "illuminate/contracts": "^9.0",
- "illuminate/macroable": "^9.0",
- "nesbot/carbon": "^2.62.1",
- "php": "^8.0.2",
+ "illuminate/collections": "^10.0",
+ "illuminate/conditionable": "^10.0",
+ "illuminate/contracts": "^10.0",
+ "illuminate/macroable": "^10.0",
+ "nesbot/carbon": "^2.67",
+ "php": "^8.1",
"voku/portable-ascii": "^2.0"
},
"conflict": {
"tightenco/collect": "<5.5.33"
},
"suggest": {
- "illuminate/filesystem": "Required to use the composer class (^9.0).",
+ "illuminate/filesystem": "Required to use the composer class (^10.0).",
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).",
- "ramsey/uuid": "Required to use Str::uuid() (^4.2.2).",
- "symfony/process": "Required to use the composer class (^6.0).",
- "symfony/uid": "Required to use Str::ulid() (^6.0).",
- "symfony/var-dumper": "Required to use the dd function (^6.0).",
+ "ramsey/uuid": "Required to use Str::uuid() (^4.7).",
+ "symfony/process": "Required to use the composer class (^6.2).",
+ "symfony/uid": "Required to use Str::ulid() (^6.2).",
+ "symfony/var-dumper": "Required to use the dd function (^6.2).",
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)."
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1844,37 +2053,37 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-12-05T15:05:31+00:00"
+ "time": "2023-12-19T15:11:55+00:00"
},
{
"name": "illuminate/view",
- "version": "v9.43.0",
+ "version": "v10.38.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/view.git",
- "reference": "951a68bbbecaa5f744bfd01e8dcdd482d0604348"
+ "reference": "9c5c0a363175becb4fcdde2d3df7e665ca537288"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/illuminate/view/zipball/951a68bbbecaa5f744bfd01e8dcdd482d0604348",
- "reference": "951a68bbbecaa5f744bfd01e8dcdd482d0604348",
+ "url": "https://api.github.com/repos/illuminate/view/zipball/9c5c0a363175becb4fcdde2d3df7e665ca537288",
+ "reference": "9c5c0a363175becb4fcdde2d3df7e665ca537288",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "illuminate/collections": "^9.0",
- "illuminate/container": "^9.0",
- "illuminate/contracts": "^9.0",
- "illuminate/events": "^9.0",
- "illuminate/filesystem": "^9.0",
- "illuminate/macroable": "^9.0",
- "illuminate/support": "^9.0",
- "php": "^8.0.2"
+ "ext-tokenizer": "*",
+ "illuminate/collections": "^10.0",
+ "illuminate/container": "^10.0",
+ "illuminate/contracts": "^10.0",
+ "illuminate/events": "^10.0",
+ "illuminate/filesystem": "^10.0",
+ "illuminate/macroable": "^10.0",
+ "illuminate/support": "^10.0",
+ "php": "^8.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.x-dev"
+ "dev-master": "10.x-dev"
}
},
"autoload": {
@@ -1892,48 +2101,354 @@
"email": "taylor@laravel.com"
}
],
- "description": "The Illuminate View package.",
- "homepage": "https://laravel.com",
+ "description": "The Illuminate View package.",
+ "homepage": "https://laravel.com",
+ "support": {
+ "issues": "https://github.com/laravel/framework/issues",
+ "source": "https://github.com/laravel/framework"
+ },
+ "time": "2023-12-17T15:34:19+00:00"
+ },
+ {
+ "name": "justinrainbow/json-schema",
+ "version": "v5.2.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/justinrainbow/json-schema.git",
+ "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/fbbe7e5d79f618997bc3332a6f49246036c45793",
+ "reference": "fbbe7e5d79f618997bc3332a6f49246036c45793",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1",
+ "json-schema/json-schema-test-suite": "1.2.0",
+ "phpunit/phpunit": "^4.8.35"
+ },
+ "bin": [
+ "bin/validate-json"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "JsonSchema\\": "src/JsonSchema/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert SchΓΆnthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "description": "A library to validate a json schema.",
+ "homepage": "https://github.com/justinrainbow/json-schema",
+ "keywords": [
+ "json",
+ "schema"
+ ],
+ "support": {
+ "issues": "https://github.com/justinrainbow/json-schema/issues",
+ "source": "https://github.com/justinrainbow/json-schema/tree/v5.2.13"
+ },
+ "time": "2023-09-26T02:20:38+00:00"
+ },
+ {
+ "name": "league/oauth2-client",
+ "version": "2.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/oauth2-client.git",
+ "reference": "160d6274b03562ebeb55ed18399281d8118b76c8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/160d6274b03562ebeb55ed18399281d8118b76c8",
+ "reference": "160d6274b03562ebeb55ed18399281d8118b76c8",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^6.0 || ^7.0",
+ "paragonie/random_compat": "^1 || ^2 || ^9.99",
+ "php": "^5.6 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.3.5",
+ "php-parallel-lint/php-parallel-lint": "^1.3.1",
+ "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5",
+ "squizlabs/php_codesniffer": "^2.3 || ^3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-2.x": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\OAuth2\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alex Bilbie",
+ "email": "hello@alexbilbie.com",
+ "homepage": "http://www.alexbilbie.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Woody Gilk",
+ "homepage": "https://github.com/shadowhand",
+ "role": "Contributor"
+ }
+ ],
+ "description": "OAuth 2.0 Client Library",
+ "keywords": [
+ "Authentication",
+ "SSO",
+ "authorization",
+ "identity",
+ "idp",
+ "oauth",
+ "oauth2",
+ "single sign on"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/oauth2-client/issues",
+ "source": "https://github.com/thephpleague/oauth2-client/tree/2.7.0"
+ },
+ "time": "2023-04-16T18:19:15+00:00"
+ },
+ {
+ "name": "league/openapi-psr7-validator",
+ "version": "0.21",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/openapi-psr7-validator.git",
+ "reference": "bccdd3f5037c796fff3ef3f11dcf8c073aaa6192"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/openapi-psr7-validator/zipball/bccdd3f5037c796fff3ef3f11dcf8c073aaa6192",
+ "reference": "bccdd3f5037c796fff3ef3f11dcf8c073aaa6192",
+ "shasum": ""
+ },
+ "require": {
+ "devizzent/cebe-php-openapi": "^1.0",
+ "ext-json": "*",
+ "league/uri": "^6.3",
+ "php": ">=7.2",
+ "psr/cache": "^1.0 || ^2.0 || ^3.0",
+ "psr/http-message": "^1.0",
+ "psr/http-server-middleware": "^1.0",
+ "respect/validation": "^1.1.3 || ^2.0",
+ "riverline/multipart-parser": "^2.0.3",
+ "symfony/polyfill-php80": "^1.27",
+ "webmozart/assert": "^1.4"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^8.0",
+ "guzzlehttp/psr7": "^1.5",
+ "hansott/psr7-cookies": "^3.0.2",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^1",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpstan/phpstan-webmozart-assert": "^1",
+ "phpunit/phpunit": "^7 || ^8 || ^9",
+ "symfony/cache": "^5.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\OpenAPIValidation\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Validate PSR-7 messages against OpenAPI (3.0.2) specifications expressed in YAML or JSON",
+ "homepage": "https://github.com/thephpleague/openapi-psr7-validator",
+ "keywords": [
+ "http",
+ "openapi",
+ "psr7",
+ "validation"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/openapi-psr7-validator/issues",
+ "source": "https://github.com/thephpleague/openapi-psr7-validator/tree/0.21"
+ },
+ "time": "2023-04-03T21:49:07+00:00"
+ },
+ {
+ "name": "league/uri",
+ "version": "6.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/uri.git",
+ "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/uri/zipball/a700b4656e4c54371b799ac61e300ab25a2d1d39",
+ "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "league/uri-interfaces": "^2.3",
+ "php": "^8.1",
+ "psr/http-message": "^1.0.1"
+ },
+ "conflict": {
+ "league/uri-schemes": "^1.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^v3.9.5",
+ "nyholm/psr7": "^1.5.1",
+ "php-http/psr7-integration-tests": "^1.1.1",
+ "phpbench/phpbench": "^1.2.6",
+ "phpstan/phpstan": "^1.8.5",
+ "phpstan/phpstan-deprecation-rules": "^1.0",
+ "phpstan/phpstan-phpunit": "^1.1.1",
+ "phpstan/phpstan-strict-rules": "^1.4.3",
+ "phpunit/phpunit": "^9.5.24",
+ "psr/http-factory": "^1.0.1"
+ },
+ "suggest": {
+ "ext-fileinfo": "Needed to create Data URI from a filepath",
+ "ext-intl": "Needed to improve host validation",
+ "league/uri-components": "Needed to easily manipulate URI objects",
+ "psr/http-factory": "Needed to use the URI factory"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Uri\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ignace Nyamagana Butera",
+ "email": "nyamsprod@gmail.com",
+ "homepage": "https://nyamsprod.com"
+ }
+ ],
+ "description": "URI manipulation library",
+ "homepage": "https://uri.thephpleague.com",
+ "keywords": [
+ "data-uri",
+ "file-uri",
+ "ftp",
+ "hostname",
+ "http",
+ "https",
+ "middleware",
+ "parse_str",
+ "parse_url",
+ "psr-7",
+ "query-string",
+ "querystring",
+ "rfc3986",
+ "rfc3987",
+ "rfc6570",
+ "uri",
+ "uri-template",
+ "url",
+ "ws"
+ ],
"support": {
- "issues": "https://github.com/laravel/framework/issues",
- "source": "https://github.com/laravel/framework"
+ "docs": "https://uri.thephpleague.com",
+ "forum": "https://thephpleague.slack.com",
+ "issues": "https://github.com/thephpleague/uri/issues",
+ "source": "https://github.com/thephpleague/uri/tree/6.8.0"
},
- "time": "2022-11-18T19:51:25+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/nyamsprod",
+ "type": "github"
+ }
+ ],
+ "time": "2022-09-13T19:58:47+00:00"
},
{
- "name": "league/oauth2-client",
- "version": "2.6.1",
+ "name": "league/uri-interfaces",
+ "version": "2.3.0",
"source": {
"type": "git",
- "url": "https://github.com/thephpleague/oauth2-client.git",
- "reference": "2334c249907190c132364f5dae0287ab8666aa19"
+ "url": "https://github.com/thephpleague/uri-interfaces.git",
+ "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/2334c249907190c132364f5dae0287ab8666aa19",
- "reference": "2334c249907190c132364f5dae0287ab8666aa19",
+ "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
+ "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
"shasum": ""
},
"require": {
- "guzzlehttp/guzzle": "^6.0 || ^7.0",
- "paragonie/random_compat": "^1 || ^2 || ^9.99",
- "php": "^5.6 || ^7.0 || ^8.0"
+ "ext-json": "*",
+ "php": "^7.2 || ^8.0"
},
"require-dev": {
- "mockery/mockery": "^1.3.5",
- "php-parallel-lint/php-parallel-lint": "^1.3.1",
- "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5",
- "squizlabs/php_codesniffer": "^2.3 || ^3.0"
+ "friendsofphp/php-cs-fixer": "^2.19",
+ "phpstan/phpstan": "^0.12.90",
+ "phpstan/phpstan-phpunit": "^0.12.19",
+ "phpstan/phpstan-strict-rules": "^0.12.9",
+ "phpunit/phpunit": "^8.5.15 || ^9.5"
+ },
+ "suggest": {
+ "ext-intl": "to use the IDNA feature",
+ "symfony/intl": "to use the IDNA feature via Symfony Polyfill"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-2.x": "2.0.x-dev"
+ "dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
- "League\\OAuth2\\Client\\": "src/"
+ "League\\Uri\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1942,58 +2457,60 @@
],
"authors": [
{
- "name": "Alex Bilbie",
- "email": "hello@alexbilbie.com",
- "homepage": "http://www.alexbilbie.com",
- "role": "Developer"
- },
- {
- "name": "Woody Gilk",
- "homepage": "https://github.com/shadowhand",
- "role": "Contributor"
+ "name": "Ignace Nyamagana Butera",
+ "email": "nyamsprod@gmail.com",
+ "homepage": "https://nyamsprod.com"
}
],
- "description": "OAuth 2.0 Client Library",
+ "description": "Common interface for URI representation",
+ "homepage": "http://github.com/thephpleague/uri-interfaces",
"keywords": [
- "Authentication",
- "SSO",
- "authorization",
- "identity",
- "idp",
- "oauth",
- "oauth2",
- "single sign on"
+ "rfc3986",
+ "rfc3987",
+ "uri",
+ "url"
],
"support": {
- "issues": "https://github.com/thephpleague/oauth2-client/issues",
- "source": "https://github.com/thephpleague/oauth2-client/tree/2.6.1"
+ "issues": "https://github.com/thephpleague/uri-interfaces/issues",
+ "source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0"
},
- "time": "2021-12-22T16:42:49+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/nyamsprod",
+ "type": "github"
+ }
+ ],
+ "time": "2021-06-28T04:27:21+00:00"
},
{
"name": "nesbot/carbon",
- "version": "2.64.0",
+ "version": "2.72.1",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "889546413c97de2d05063b8cb7b193c2531ea211"
+ "reference": "2b3b3db0a2d0556a177392ff1a3bf5608fa09f78"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/889546413c97de2d05063b8cb7b193c2531ea211",
- "reference": "889546413c97de2d05063b8cb7b193c2531ea211",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/2b3b3db0a2d0556a177392ff1a3bf5608fa09f78",
+ "reference": "2b3b3db0a2d0556a177392ff1a3bf5608fa09f78",
"shasum": ""
},
"require": {
+ "carbonphp/carbon-doctrine-types": "*",
"ext-json": "*",
"php": "^7.1.8 || ^8.0",
+ "psr/clock": "^1.0",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
"require-dev": {
- "doctrine/dbal": "^2.0 || ^3.1.4",
- "doctrine/orm": "^2.7",
+ "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0",
+ "doctrine/orm": "^2.7 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.0",
"kylekatarnls/multi-tester": "^2.0",
"ondrejmirtes/better-reflection": "*",
@@ -2070,7 +2587,7 @@
"type": "tidelift"
}
],
- "time": "2022-11-26T17:36:00+00:00"
+ "time": "2023-12-08T23:47:49+00:00"
},
{
"name": "nikic/fast-route",
@@ -2124,38 +2641,39 @@
},
{
"name": "nyholm/psr7",
- "version": "1.5.1",
+ "version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/Nyholm/psr7.git",
- "reference": "f734364e38a876a23be4d906a2a089e1315be18a"
+ "reference": "aa5fc277a4f5508013d571341ade0c3886d4d00e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Nyholm/psr7/zipball/f734364e38a876a23be4d906a2a089e1315be18a",
- "reference": "f734364e38a876a23be4d906a2a089e1315be18a",
+ "url": "https://api.github.com/repos/Nyholm/psr7/zipball/aa5fc277a4f5508013d571341ade0c3886d4d00e",
+ "reference": "aa5fc277a4f5508013d571341ade0c3886d4d00e",
"shasum": ""
},
"require": {
- "php": ">=7.1",
- "php-http/message-factory": "^1.0",
+ "php": ">=7.2",
"psr/http-factory": "^1.0",
- "psr/http-message": "^1.0"
+ "psr/http-message": "^1.1 || ^2.0"
},
"provide": {
+ "php-http/message-factory-implementation": "1.0",
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"http-interop/http-factory-tests": "^0.9",
+ "php-http/message-factory": "^1.0",
"php-http/psr7-integration-tests": "^1.0",
- "phpunit/phpunit": "^7.5 || 8.5 || 9.4",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4",
"symfony/error-handler": "^4.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "1.8-dev"
}
},
"autoload": {
@@ -2185,7 +2703,7 @@
],
"support": {
"issues": "https://github.com/Nyholm/psr7/issues",
- "source": "https://github.com/Nyholm/psr7/tree/1.5.1"
+ "source": "https://github.com/Nyholm/psr7/tree/1.8.1"
},
"funding": [
{
@@ -2197,7 +2715,7 @@
"type": "github"
}
],
- "time": "2022-06-22T07:13:36+00:00"
+ "time": "2023-11-13T09:31:12+00:00"
},
{
"name": "paragonie/random_compat",
@@ -2249,80 +2767,26 @@
},
"time": "2020-10-15T08:29:30+00:00"
},
- {
- "name": "php-http/message-factory",
- "version": "v1.0.2",
- "source": {
- "type": "git",
- "url": "https://github.com/php-http/message-factory.git",
- "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1",
- "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1",
- "shasum": ""
- },
- "require": {
- "php": ">=5.4",
- "psr/http-message": "^1.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Http\\Message\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "MΓ‘rk SΓ‘gi-KazΓ‘r",
- "email": "mark.sagikazar@gmail.com"
- }
- ],
- "description": "Factory interfaces for PSR-7 HTTP Message",
- "homepage": "http://php-http.org",
- "keywords": [
- "factory",
- "http",
- "message",
- "stream",
- "uri"
- ],
- "support": {
- "issues": "https://github.com/php-http/message-factory/issues",
- "source": "https://github.com/php-http/message-factory/tree/master"
- },
- "time": "2015-12-19T14:08:53+00:00"
- },
{
"name": "phpoption/phpoption",
- "version": "1.9.0",
+ "version": "1.9.2",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/php-option.git",
- "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab"
+ "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
- "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab",
+ "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820",
+ "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
- "bamarni/composer-bin-plugin": "^1.8",
- "phpunit/phpunit": "^8.5.28 || ^9.5.21"
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
},
"type": "library",
"extra": {
@@ -2364,7 +2828,7 @@
],
"support": {
"issues": "https://github.com/schmittjoh/php-option/issues",
- "source": "https://github.com/schmittjoh/php-option/tree/1.9.0"
+ "source": "https://github.com/schmittjoh/php-option/tree/1.9.2"
},
"funding": [
{
@@ -2376,7 +2840,7 @@
"type": "tidelift"
}
],
- "time": "2022-07-30T15:51:26+00:00"
+ "time": "2023-11-12T21:59:55+00:00"
},
{
"name": "psr/cache",
@@ -2427,6 +2891,54 @@
},
"time": "2021-02-03T23:26:27+00:00"
},
+ {
+ "name": "psr/clock",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/clock.git",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Clock\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for reading the clock.",
+ "homepage": "https://github.com/php-fig/clock",
+ "keywords": [
+ "clock",
+ "now",
+ "psr",
+ "psr-20",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/clock/issues",
+ "source": "https://github.com/php-fig/clock/tree/1.0.0"
+ },
+ "time": "2022-11-25T14:36:26+00:00"
+ },
{
"name": "psr/container",
"version": "2.0.2",
@@ -2532,21 +3044,21 @@
},
{
"name": "psr/http-client",
- "version": "1.0.1",
+ "version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
- "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
- "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
- "psr/http-message": "^1.0"
+ "psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
@@ -2566,7 +3078,7 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
@@ -2578,27 +3090,27 @@
"psr-18"
],
"support": {
- "source": "https://github.com/php-fig/http-client/tree/master"
+ "source": "https://github.com/php-fig/http-client"
},
- "time": "2020-06-29T06:28:15+00:00"
+ "time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
- "version": "1.0.1",
+ "version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
- "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
+ "reference": "e616d01114759c4c489f93b099585439f795fe35"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
- "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35",
+ "reference": "e616d01114759c4c489f93b099585439f795fe35",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
- "psr/http-message": "^1.0"
+ "psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
@@ -2618,7 +3130,7 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
@@ -2633,31 +3145,31 @@
"response"
],
"support": {
- "source": "https://github.com/php-fig/http-factory/tree/master"
+ "source": "https://github.com/php-fig/http-factory/tree/1.0.2"
},
- "time": "2019-04-30T12:38:16+00:00"
+ "time": "2023-04-10T20:10:41+00:00"
},
{
"name": "psr/http-message",
- "version": "1.0.1",
+ "version": "1.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
- "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
- "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
+ "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "1.1.x-dev"
}
},
"autoload": {
@@ -2686,27 +3198,27 @@
"response"
],
"support": {
- "source": "https://github.com/php-fig/http-message/tree/master"
+ "source": "https://github.com/php-fig/http-message/tree/1.1"
},
- "time": "2016-08-06T14:39:51+00:00"
+ "time": "2023-04-04T09:50:52+00:00"
},
{
"name": "psr/http-server-handler",
- "version": "1.0.1",
+ "version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-server-handler.git",
- "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7"
+ "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/aff2f80e33b7f026ec96bb42f63242dc50ffcae7",
- "reference": "aff2f80e33b7f026ec96bb42f63242dc50ffcae7",
+ "url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4",
+ "reference": "84c4fb66179be4caaf8e97bd239203245302e7d4",
"shasum": ""
},
"require": {
"php": ">=7.0",
- "psr/http-message": "^1.0"
+ "psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
@@ -2726,7 +3238,7 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP server-side request handler",
@@ -2742,28 +3254,27 @@
"server"
],
"support": {
- "issues": "https://github.com/php-fig/http-server-handler/issues",
- "source": "https://github.com/php-fig/http-server-handler/tree/master"
+ "source": "https://github.com/php-fig/http-server-handler/tree/1.0.2"
},
- "time": "2018-10-30T16:46:14+00:00"
+ "time": "2023-04-10T20:06:20+00:00"
},
{
"name": "psr/http-server-middleware",
- "version": "1.0.1",
+ "version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-server-middleware.git",
- "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5"
+ "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/2296f45510945530b9dceb8bcedb5cb84d40c5f5",
- "reference": "2296f45510945530b9dceb8bcedb5cb84d40c5f5",
+ "url": "https://api.github.com/repos/php-fig/http-server-middleware/zipball/c1481f747daaa6a0782775cd6a8c26a1bf4a3829",
+ "reference": "c1481f747daaa6a0782775cd6a8c26a1bf4a3829",
"shasum": ""
},
"require": {
"php": ">=7.0",
- "psr/http-message": "^1.0",
+ "psr/http-message": "^1.0 || ^2.0",
"psr/http-server-handler": "^1.0"
},
"type": "library",
@@ -2784,7 +3295,7 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP server-side middleware",
@@ -2800,9 +3311,9 @@
],
"support": {
"issues": "https://github.com/php-fig/http-server-middleware/issues",
- "source": "https://github.com/php-fig/http-server-middleware/tree/master"
+ "source": "https://github.com/php-fig/http-server-middleware/tree/1.0.2"
},
- "time": "2018-10-30T17:12:04+00:00"
+ "time": "2023-04-11T06:14:47+00:00"
},
{
"name": "psr/log",
@@ -2951,27 +3462,27 @@
},
{
"name": "rcrowe/twigbridge",
- "version": "v0.14.0",
+ "version": "v0.14.1",
"source": {
"type": "git",
"url": "https://github.com/rcrowe/TwigBridge.git",
- "reference": "f4968efb99537cc1b37c5bf20280614aadc31825"
+ "reference": "639345cb32156ff69845ed471bbf0778c52a28b2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/f4968efb99537cc1b37c5bf20280614aadc31825",
- "reference": "f4968efb99537cc1b37c5bf20280614aadc31825",
+ "url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/639345cb32156ff69845ed471bbf0778c52a28b2",
+ "reference": "639345cb32156ff69845ed471bbf0778c52a28b2",
"shasum": ""
},
"require": {
- "illuminate/support": "^6|^7|^8|^9",
- "illuminate/view": "^6|^7|^8|^9",
+ "illuminate/support": "^6|^7|^8|^9|^10",
+ "illuminate/view": "^6|^7|^8|^9|^10",
"php": "^7.2.5 || ^8.0",
"twig/twig": "~3.0"
},
"require-dev": {
"ext-json": "*",
- "laravel/framework": "^6|^7|^8|^9",
+ "laravel/framework": "^6|^7|^8|^9|^10",
"mockery/mockery": "^1.3.1",
"phpunit/phpunit": "^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.7",
"squizlabs/php_codesniffer": "^3.6"
@@ -2983,7 +3494,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "0.13-dev"
+ "dev-master": "0.14-dev"
},
"laravel": {
"providers": [
@@ -3021,9 +3532,9 @@
],
"support": {
"issues": "https://github.com/rcrowe/TwigBridge/issues",
- "source": "https://github.com/rcrowe/TwigBridge/tree/v0.14.0"
+ "source": "https://github.com/rcrowe/TwigBridge/tree/v0.14.1"
},
- "time": "2022-03-08T17:21:17+00:00"
+ "time": "2023-02-16T14:03:23+00:00"
},
{
"name": "respect/validation",
@@ -3093,59 +3604,34 @@
"time": "2019-05-28T06:10:06+00:00"
},
{
- "name": "symfony/console",
- "version": "v6.2.1",
+ "name": "riverline/multipart-parser",
+ "version": "2.1.1",
"source": {
"type": "git",
- "url": "https://github.com/symfony/console.git",
- "reference": "58f6cef5dc5f641b7bbdbf8b32b44cc926c35f3f"
+ "url": "https://github.com/Riverline/multipart-parser.git",
+ "reference": "2418bdfc2eab01e39bcffee808b1a365c166292a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/58f6cef5dc5f641b7bbdbf8b32b44cc926c35f3f",
- "reference": "58f6cef5dc5f641b7bbdbf8b32b44cc926c35f3f",
+ "url": "https://api.github.com/repos/Riverline/multipart-parser/zipball/2418bdfc2eab01e39bcffee808b1a365c166292a",
+ "reference": "2418bdfc2eab01e39bcffee808b1a365c166292a",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "symfony/deprecation-contracts": "^2.1|^3",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/service-contracts": "^1.1|^2|^3",
- "symfony/string": "^5.4|^6.0"
- },
- "conflict": {
- "symfony/dependency-injection": "<5.4",
- "symfony/dotenv": "<5.4",
- "symfony/event-dispatcher": "<5.4",
- "symfony/lock": "<5.4",
- "symfony/process": "<5.4"
- },
- "provide": {
- "psr/log-implementation": "1.0|2.0|3.0"
+ "ext-mbstring": "*",
+ "php": ">=5.6.0"
},
"require-dev": {
- "psr/log": "^1|^2|^3",
- "symfony/config": "^5.4|^6.0",
- "symfony/dependency-injection": "^5.4|^6.0",
- "symfony/event-dispatcher": "^5.4|^6.0",
- "symfony/lock": "^5.4|^6.0",
- "symfony/process": "^5.4|^6.0",
- "symfony/var-dumper": "^5.4|^6.0"
- },
- "suggest": {
- "psr/log": "For using the console logger",
- "symfony/event-dispatcher": "",
- "symfony/lock": "",
- "symfony/process": ""
+ "laminas/laminas-diactoros": "^1.8.7 || ^2.11.1",
+ "phpunit/phpunit": "^5.7 || ^9.0",
+ "psr/http-message": "^1.0",
+ "symfony/psr-http-message-bridge": "^1.1 || ^2.0"
},
"type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Console\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Riverline\\MultiPartParser\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -3153,53 +3639,38 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Romain Cambien",
+ "email": "romain@cambien.net"
},
{
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "Riverline",
+ "homepage": "http://www.riverline.fr"
}
],
- "description": "Eases the creation of beautiful and testable command line interfaces",
- "homepage": "https://symfony.com",
+ "description": "One class library to parse multipart content with encoding and charset support.",
"keywords": [
- "cli",
- "command line",
- "console",
- "terminal"
+ "http",
+ "multipart",
+ "parser"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v6.2.1"
+ "issues": "https://github.com/Riverline/multipart-parser/issues",
+ "source": "https://github.com/Riverline/multipart-parser/tree/2.1.1"
},
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
- }
- ],
- "time": "2022-12-01T13:44:20+00:00"
+ "time": "2023-04-28T18:53:59+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.2.0",
+ "version": "v3.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3"
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3",
- "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
"shasum": ""
},
"require": {
@@ -3208,7 +3679,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.3-dev"
+ "dev-main": "3.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -3237,7 +3708,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
},
"funding": [
{
@@ -3253,28 +3724,29 @@
"type": "tidelift"
}
],
- "time": "2022-11-25T10:21:52+00:00"
+ "time": "2023-05-23T14:45:45+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v6.2.0",
+ "version": "v7.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "9efb1618fabee89515fe031314e8ed5625f85a53"
+ "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9efb1618fabee89515fe031314e8ed5625f85a53",
- "reference": "9efb1618fabee89515fe031314e8ed5625f85a53",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e",
+ "reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "symfony/event-dispatcher-contracts": "^2|^3"
+ "php": ">=8.2",
+ "symfony/event-dispatcher-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/dependency-injection": "<5.4"
+ "symfony/dependency-injection": "<6.4",
+ "symfony/service-contracts": "<2.5"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
@@ -3282,17 +3754,13 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^5.4|^6.0",
- "symfony/dependency-injection": "^5.4|^6.0",
- "symfony/error-handler": "^5.4|^6.0",
- "symfony/expression-language": "^5.4|^6.0",
- "symfony/http-foundation": "^5.4|^6.0",
- "symfony/service-contracts": "^1.1|^2|^3",
- "symfony/stopwatch": "^5.4|^6.0"
- },
- "suggest": {
- "symfony/dependency-injection": "",
- "symfony/http-kernel": ""
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/stopwatch": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -3320,7 +3788,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.0"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.0"
},
"funding": [
{
@@ -3336,33 +3804,30 @@
"type": "tidelift"
}
],
- "time": "2022-11-02T09:08:04+00:00"
+ "time": "2023-07-27T16:29:09+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
- "version": "v3.2.0",
+ "version": "v3.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
- "reference": "0782b0b52a737a05b4383d0df35a474303cabdae"
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0782b0b52a737a05b4383d0df35a474303cabdae",
- "reference": "0782b0b52a737a05b4383d0df35a474303cabdae",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df",
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df",
"shasum": ""
},
"require": {
"php": ">=8.1",
"psr/event-dispatcher": "^1"
},
- "suggest": {
- "symfony/event-dispatcher-implementation": ""
- },
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.3-dev"
+ "dev-main": "3.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -3399,7 +3864,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.0"
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0"
},
"funding": [
{
@@ -3415,27 +3880,27 @@
"type": "tidelift"
}
],
- "time": "2022-11-25T10:21:52+00:00"
+ "time": "2023-05-23T14:45:45+00:00"
},
{
"name": "symfony/finder",
- "version": "v6.2.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "eb2355f69519e4ef33f1835bca4c935f5d42e570"
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/eb2355f69519e4ef33f1835bca4c935f5d42e570",
- "reference": "eb2355f69519e4ef33f1835bca4c935f5d42e570",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce",
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"require-dev": {
- "symfony/filesystem": "^6.0"
+ "symfony/filesystem": "^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3463,7 +3928,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v6.2.0"
+ "source": "https://github.com/symfony/finder/tree/v6.4.0"
},
"funding": [
{
@@ -3479,41 +3944,40 @@
"type": "tidelift"
}
],
- "time": "2022-10-09T08:55:40+00:00"
+ "time": "2023-10-31T17:30:12+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v6.2.1",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "d0bbd5a7e81b38f32504399b9199f265505b7bac"
+ "reference": "44a6d39a9cc11e154547d882d5aac1e014440771"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d0bbd5a7e81b38f32504399b9199f265505b7bac",
- "reference": "d0bbd5a7e81b38f32504399b9199f265505b7bac",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771",
+ "reference": "44a6d39a9cc11e154547d882d5aac1e014440771",
"shasum": ""
},
"require": {
"php": ">=8.1",
- "symfony/deprecation-contracts": "^2.1|^3",
- "symfony/polyfill-mbstring": "~1.1"
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "~1.1",
+ "symfony/polyfill-php83": "^1.27"
},
"conflict": {
- "symfony/cache": "<6.2"
+ "symfony/cache": "<6.3"
},
"require-dev": {
- "predis/predis": "~1.0",
- "symfony/cache": "^5.4|^6.0",
- "symfony/dependency-injection": "^5.4|^6.0",
- "symfony/expression-language": "^5.4|^6.0",
- "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
- "symfony/mime": "^5.4|^6.0",
- "symfony/rate-limiter": "^5.2|^6.0"
- },
- "suggest": {
- "symfony/mime": "To use the file extension guesser"
+ "doctrine/dbal": "^2.13.1|^3|^4",
+ "predis/predis": "^1.1|^2.0",
+ "symfony/cache": "^6.3|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0",
+ "symfony/mime": "^5.4|^6.0|^7.0",
+ "symfony/rate-limiter": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3541,7 +4005,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v6.2.1"
+ "source": "https://github.com/symfony/http-foundation/tree/v6.4.0"
},
"funding": [
{
@@ -3557,42 +4021,43 @@
"type": "tidelift"
}
],
- "time": "2022-12-04T18:26:13+00:00"
+ "time": "2023-11-20T16:41:16+00:00"
},
{
"name": "symfony/mailer",
- "version": "v6.2.1",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "a18c3dd41cfcf011e3866802e39b9ae9e541deaf"
+ "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/a18c3dd41cfcf011e3866802e39b9ae9e541deaf",
- "reference": "a18c3dd41cfcf011e3866802e39b9ae9e541deaf",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba",
+ "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba",
"shasum": ""
},
"require": {
- "egulias/email-validator": "^2.1.10|^3",
+ "egulias/email-validator": "^2.1.10|^3|^4",
"php": ">=8.1",
"psr/event-dispatcher": "^1",
"psr/log": "^1|^2|^3",
- "symfony/event-dispatcher": "^5.4|^6.0",
- "symfony/mime": "^6.2",
- "symfony/service-contracts": "^1.1|^2|^3"
+ "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
+ "symfony/mime": "^6.2|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
},
"conflict": {
+ "symfony/http-client-contracts": "<2.5",
"symfony/http-kernel": "<5.4",
"symfony/messenger": "<6.2",
"symfony/mime": "<6.2",
"symfony/twig-bridge": "<6.2.1"
},
"require-dev": {
- "symfony/console": "^5.4|^6.0",
- "symfony/http-client-contracts": "^1.1|^2|^3",
- "symfony/messenger": "^6.2",
- "symfony/twig-bridge": "^6.2"
+ "symfony/console": "^5.4|^6.0|^7.0",
+ "symfony/http-client": "^5.4|^6.0|^7.0",
+ "symfony/messenger": "^6.2|^7.0",
+ "symfony/twig-bridge": "^6.2|^7.0"
},
"type": "library",
"autoload": {
@@ -3620,7 +4085,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v6.2.1"
+ "source": "https://github.com/symfony/mailer/tree/v6.4.0"
},
"funding": [
{
@@ -3636,24 +4101,24 @@
"type": "tidelift"
}
],
- "time": "2022-12-06T16:54:23+00:00"
+ "time": "2023-11-12T18:02:22+00:00"
},
{
"name": "symfony/mime",
- "version": "v6.2.0",
+ "version": "v7.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "1e8005a7cbd79fb824ad81308ef2a76592a08bc0"
+ "reference": "0a2fff95c1a10df97f571d67e76c7ae0f0d4f535"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/1e8005a7cbd79fb824ad81308ef2a76592a08bc0",
- "reference": "1e8005a7cbd79fb824ad81308ef2a76592a08bc0",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/0a2fff95c1a10df97f571d67e76c7ae0f0d4f535",
+ "reference": "0a2fff95c1a10df97f571d67e76c7ae0f0d4f535",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
@@ -3661,17 +4126,17 @@
"egulias/email-validator": "~3.0.0",
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
- "symfony/mailer": "<5.4",
- "symfony/serializer": "<6.2"
+ "symfony/mailer": "<6.4",
+ "symfony/serializer": "<6.4"
},
"require-dev": {
- "egulias/email-validator": "^2.1.10|^3.1",
+ "egulias/email-validator": "^2.1.10|^3.1|^4",
"league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
- "symfony/dependency-injection": "^5.4|^6.0",
- "symfony/property-access": "^5.4|^6.0",
- "symfony/property-info": "^5.4|^6.0",
- "symfony/serializer": "^6.2"
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0"
},
"type": "library",
"autoload": {
@@ -3703,7 +4168,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v6.2.0"
+ "source": "https://github.com/symfony/mime/tree/v7.0.0"
},
"funding": [
{
@@ -3719,20 +4184,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-28T12:28:19+00:00"
+ "time": "2023-10-19T14:20:43+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
+ "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
- "reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
+ "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@@ -3747,7 +4212,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -3785,7 +4250,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@@ -3801,24 +4266,26 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
- "name": "symfony/polyfill-intl-grapheme",
- "version": "v1.27.0",
+ "name": "symfony/polyfill-intl-idn",
+ "version": "v1.28.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "511a08c03c1960e08a883f4cffcacd219b758354"
+ "url": "https://github.com/symfony/polyfill-intl-idn.git",
+ "reference": "ecaafce9f77234a6a449d29e49267ba10499116d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
- "reference": "511a08c03c1960e08a883f4cffcacd219b758354",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d",
+ "reference": "ecaafce9f77234a6a449d29e49267ba10499116d",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.1",
+ "symfony/polyfill-intl-normalizer": "^1.10",
+ "symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
@@ -3826,7 +4293,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -3838,7 +4305,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ "Symfony\\Polyfill\\Intl\\Idn\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -3847,26 +4314,30 @@
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
+ "name": "Laurent Bassin",
+ "email": "laurent@bassin.info"
+ },
+ {
+ "name": "Trevor Rowbotham",
+ "email": "trevor.rowbotham@pm.me"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill for intl's grapheme_* functions",
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
- "grapheme",
+ "idn",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0"
},
"funding": [
{
@@ -3882,26 +4353,24 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:30:37+00:00"
},
{
- "name": "symfony/polyfill-intl-idn",
- "version": "v1.27.0",
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.28.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-intl-idn.git",
- "reference": "639084e360537a19f9ee352433b84ce831f3d2da"
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
- "reference": "639084e360537a19f9ee352433b84ce831f3d2da",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
+ "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": ""
},
"require": {
- "php": ">=7.1",
- "symfony/polyfill-intl-normalizer": "^1.10",
- "symfony/polyfill-php72": "^1.10"
+ "php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
@@ -3909,7 +4378,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -3921,8 +4390,11 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Intl\\Idn\\": ""
- }
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -3930,30 +4402,26 @@
],
"authors": [
{
- "name": "Laurent Bassin",
- "email": "laurent@bassin.info"
- },
- {
- "name": "Trevor Rowbotham",
- "email": "trevor.rowbotham@pm.me"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
- "idn",
"intl",
+ "normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
},
"funding": [
{
@@ -3969,32 +4437,35 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
- "name": "symfony/polyfill-intl-normalizer",
- "version": "v1.27.0",
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.28.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
- "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
+ "reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
+ "provide": {
+ "ext-mbstring": "*"
+ },
"suggest": {
- "ext-intl": "For best performance"
+ "ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4005,12 +4476,9 @@
"files": [
"bootstrap.php"
],
- "psr-4": {
- "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
- },
- "classmap": [
- "Resources/stubs"
- ]
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -4026,18 +4494,17 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill for intl's Normalizer class and related functions",
+ "description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
- "intl",
- "normalizer",
+ "mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@@ -4053,35 +4520,29 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-07-28T09:04:16+00:00"
},
{
- "name": "symfony/polyfill-mbstring",
- "version": "v1.27.0",
+ "name": "symfony/polyfill-php72",
+ "version": "v1.28.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
+ "url": "https://github.com/symfony/polyfill-php72.git",
+ "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
- "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
+ "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
+ "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
- "provide": {
- "ext-mbstring": "*"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4093,7 +4554,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
+ "Symfony\\Polyfill\\Php72\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -4110,17 +4571,16 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill for the Mbstring extension",
+ "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
- "mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
},
"funding": [
{
@@ -4136,20 +4596,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
- "name": "symfony/polyfill-php72",
- "version": "v1.27.0",
+ "name": "symfony/polyfill-php80",
+ "version": "v1.28.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-php72.git",
- "reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
- "reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
+ "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"shasum": ""
},
"require": {
@@ -4158,7 +4618,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4170,14 +4630,21 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Php72\\": ""
- }
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -4187,7 +4654,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@@ -4196,7 +4663,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
},
"funding": [
{
@@ -4212,29 +4679,30 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
- "name": "symfony/polyfill-php80",
- "version": "v1.27.0",
+ "name": "symfony/polyfill-php83",
+ "version": "v1.28.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
+ "url": "https://github.com/symfony/polyfill-php83.git",
+ "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
- "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11",
+ "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.1",
+ "symfony/polyfill-php80": "^1.14"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -4246,7 +4714,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Php80\\": ""
+ "Symfony\\Polyfill\\Php83\\": ""
},
"classmap": [
"Resources/stubs"
@@ -4257,10 +4725,6 @@
"MIT"
],
"authors": [
- {
- "name": "Ion Bazan",
- "email": "ion.bazan@gmail.com"
- },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -4270,7 +4734,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@@ -4279,7 +4743,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0"
},
"funding": [
{
@@ -4295,36 +4759,37 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-08-16T06:22:46+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
- "version": "v2.1.4",
+ "version": "v2.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/psr-http-message-bridge.git",
- "reference": "a125b93ef378c492e274f217874906fb9babdebb"
+ "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/a125b93ef378c492e274f217874906fb9babdebb",
- "reference": "a125b93ef378c492e274f217874906fb9babdebb",
+ "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/581ca6067eb62640de5ff08ee1ba6850a0ee472e",
+ "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e",
"shasum": ""
},
"require": {
- "php": ">=7.1",
- "psr/http-message": "^1.0",
- "symfony/http-foundation": "^4.4 || ^5.0 || ^6.0"
+ "php": ">=7.2.5",
+ "psr/http-message": "^1.0 || ^2.0",
+ "symfony/deprecation-contracts": "^2.5 || ^3.0",
+ "symfony/http-foundation": "^5.4 || ^6.0"
},
"require-dev": {
"nyholm/psr7": "^1.1",
"psr/log": "^1.1 || ^2 || ^3",
- "symfony/browser-kit": "^4.4 || ^5.0 || ^6.0",
- "symfony/config": "^4.4 || ^5.0 || ^6.0",
- "symfony/event-dispatcher": "^4.4 || ^5.0 || ^6.0",
- "symfony/framework-bundle": "^4.4 || ^5.0 || ^6.0",
- "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0",
- "symfony/phpunit-bridge": "^5.4@dev || ^6.0"
+ "symfony/browser-kit": "^5.4 || ^6.0",
+ "symfony/config": "^5.4 || ^6.0",
+ "symfony/event-dispatcher": "^5.4 || ^6.0",
+ "symfony/framework-bundle": "^5.4 || ^6.0",
+ "symfony/http-kernel": "^5.4 || ^6.0",
+ "symfony/phpunit-bridge": "^6.2"
},
"suggest": {
"nyholm/psr7": "For a super lightweight PSR-7/17 implementation"
@@ -4332,7 +4797,7 @@
"type": "symfony-bridge",
"extra": {
"branch-alias": {
- "dev-main": "2.1-dev"
+ "dev-main": "2.3-dev"
}
},
"autoload": {
@@ -4367,7 +4832,7 @@
],
"support": {
"issues": "https://github.com/symfony/psr-http-message-bridge/issues",
- "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.1.4"
+ "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.3.1"
},
"funding": [
{
@@ -4383,20 +4848,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-28T22:46:34+00:00"
+ "time": "2023-07-26T11:53:26+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.1.1",
+ "version": "v3.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239"
+ "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239",
- "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838",
+ "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838",
"shasum": ""
},
"require": {
@@ -4406,13 +4871,10 @@
"conflict": {
"ext-psr": "<1.1|>=2"
},
- "suggest": {
- "symfony/service-implementation": ""
- },
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.1-dev"
+ "dev-main": "3.4-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -4452,7 +4914,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.1.1"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.4.0"
},
"funding": [
{
@@ -4468,38 +4930,55 @@
"type": "tidelift"
}
],
- "time": "2022-05-30T19:18:58+00:00"
+ "time": "2023-07-30T20:28:31+00:00"
},
{
- "name": "symfony/string",
- "version": "v6.2.0",
+ "name": "symfony/translation",
+ "version": "v6.4.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/string.git",
- "reference": "145702685e0d12f81d755c71127bfff7582fdd36"
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/145702685e0d12f81d755c71127bfff7582fdd36",
- "reference": "145702685e0d12f81d755c71127bfff7582fdd36",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37",
+ "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37",
"shasum": ""
},
"require": {
"php": ">=8.1",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-intl-grapheme": "~1.0",
- "symfony/polyfill-intl-normalizer": "~1.0",
- "symfony/polyfill-mbstring": "~1.0"
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/translation-contracts": "^2.5|^3.0"
},
"conflict": {
- "symfony/translation-contracts": "<2.0"
+ "symfony/config": "<5.4",
+ "symfony/console": "<5.4",
+ "symfony/dependency-injection": "<5.4",
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/http-kernel": "<5.4",
+ "symfony/service-contracts": "<2.5",
+ "symfony/twig-bundle": "<5.4",
+ "symfony/yaml": "<5.4"
+ },
+ "provide": {
+ "symfony/translation-implementation": "2.3|3.0"
},
"require-dev": {
- "symfony/error-handler": "^5.4|^6.0",
- "symfony/http-client": "^5.4|^6.0",
- "symfony/intl": "^6.2",
- "symfony/translation-contracts": "^2.0|^3.0",
- "symfony/var-exporter": "^5.4|^6.0"
+ "nikic/php-parser": "^4.13",
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/console": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/finder": "^5.4|^6.0|^7.0",
+ "symfony/http-client-contracts": "^2.5|^3.0",
+ "symfony/http-kernel": "^5.4|^6.0|^7.0",
+ "symfony/intl": "^5.4|^6.0|^7.0",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/routing": "^5.4|^6.0|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/yaml": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -4507,7 +4986,7 @@
"Resources/functions.php"
],
"psr-4": {
- "Symfony\\Component\\String\\": ""
+ "Symfony\\Component\\Translation\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -4519,26 +4998,18 @@
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
- "keywords": [
- "grapheme",
- "i18n",
- "string",
- "unicode",
- "utf-8",
- "utf8"
- ],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.2.0"
+ "source": "https://github.com/symfony/translation/tree/v6.4.0"
},
"funding": [
{
@@ -4554,69 +5025,41 @@
"type": "tidelift"
}
],
- "time": "2022-11-30T17:13:47+00:00"
+ "time": "2023-11-29T08:14:36+00:00"
},
{
- "name": "symfony/translation",
- "version": "v6.2.0",
+ "name": "symfony/translation-contracts",
+ "version": "v3.4.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/translation.git",
- "reference": "c08de62caead8357244efcb809d0b1a2584f2198"
+ "url": "https://github.com/symfony/translation-contracts.git",
+ "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/c08de62caead8357244efcb809d0b1a2584f2198",
- "reference": "c08de62caead8357244efcb809d0b1a2584f2198",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5",
+ "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/translation-contracts": "^2.3|^3.0"
- },
- "conflict": {
- "symfony/config": "<5.4",
- "symfony/console": "<5.4",
- "symfony/dependency-injection": "<5.4",
- "symfony/http-kernel": "<5.4",
- "symfony/twig-bundle": "<5.4",
- "symfony/yaml": "<5.4"
- },
- "provide": {
- "symfony/translation-implementation": "2.3|3.0"
- },
- "require-dev": {
- "nikic/php-parser": "^4.13",
- "psr/log": "^1|^2|^3",
- "symfony/config": "^5.4|^6.0",
- "symfony/console": "^5.4|^6.0",
- "symfony/dependency-injection": "^5.4|^6.0",
- "symfony/finder": "^5.4|^6.0",
- "symfony/http-client-contracts": "^1.1|^2.0|^3.0",
- "symfony/http-kernel": "^5.4|^6.0",
- "symfony/intl": "^5.4|^6.0",
- "symfony/polyfill-intl-icu": "^1.21",
- "symfony/routing": "^5.4|^6.0",
- "symfony/service-contracts": "^1.1.2|^2|^3",
- "symfony/yaml": "^5.4|^6.0"
- },
- "suggest": {
- "nikic/php-parser": "To use PhpAstExtractor",
- "psr/log-implementation": "To use logging capability in translator",
- "symfony/config": "",
- "symfony/yaml": ""
+ "php": ">=8.1"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
"autoload": {
- "files": [
- "Resources/functions.php"
- ],
"psr-4": {
- "Symfony\\Component\\Translation\\": ""
+ "Symfony\\Contracts\\Translation\\": ""
},
"exclude-from-classmap": [
- "/Tests/"
+ "/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -4625,18 +5068,26 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides tools to internationalize your application",
+ "description": "Generic abstractions related to translation",
"homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
"support": {
- "source": "https://github.com/symfony/translation/tree/v6.2.0"
+ "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0"
},
"funding": [
{
@@ -4652,44 +5103,43 @@
"type": "tidelift"
}
],
- "time": "2022-11-02T09:08:04+00:00"
+ "time": "2023-07-25T15:08:44+00:00"
},
{
- "name": "symfony/translation-contracts",
- "version": "v3.2.0",
+ "name": "symfony/yaml",
+ "version": "v6.4.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/translation-contracts.git",
- "reference": "68cce71402305a015f8c1589bfada1280dc64fe7"
+ "url": "https://github.com/symfony/yaml.git",
+ "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/68cce71402305a015f8c1589bfada1280dc64fe7",
- "reference": "68cce71402305a015f8c1589bfada1280dc64fe7",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/4f9237a1bb42455d609e6687d2613dde5b41a587",
+ "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-ctype": "^1.8"
},
- "suggest": {
- "symfony/translation-implementation": ""
+ "conflict": {
+ "symfony/console": "<5.4"
},
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "3.3-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
- }
+ "require-dev": {
+ "symfony/console": "^5.4|^6.0|^7.0"
},
+ "bin": [
+ "Resources/bin/yaml-lint"
+ ],
+ "type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Contracts\\Translation\\": ""
+ "Symfony\\Component\\Yaml\\": ""
},
"exclude-from-classmap": [
- "/Test/"
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -4698,26 +5148,18 @@
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Generic abstractions related to translation",
+ "description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
- "keywords": [
- "abstractions",
- "contracts",
- "decoupling",
- "interfaces",
- "interoperability",
- "standards"
- ],
"support": {
- "source": "https://github.com/symfony/translation-contracts/tree/v3.2.0"
+ "source": "https://github.com/symfony/yaml/tree/v6.4.0"
},
"funding": [
{
@@ -4733,37 +5175,33 @@
"type": "tidelift"
}
],
- "time": "2022-11-25T10:21:52+00:00"
+ "time": "2023-11-06T11:00:25+00:00"
},
{
"name": "twig/twig",
- "version": "v3.4.3",
+ "version": "v3.8.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
- "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-mbstring": "^1.3"
+ "symfony/polyfill-mbstring": "^1.3",
+ "symfony/polyfill-php80": "^1.22"
},
"require-dev": {
- "psr/container": "^1.0",
- "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
+ "psr/container": "^1.0|^2.0",
+ "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.4-dev"
- }
- },
"autoload": {
"psr-4": {
"Twig\\": "src/"
@@ -4797,7 +5235,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
- "source": "https://github.com/twigphp/Twig/tree/v3.4.3"
+ "source": "https://github.com/twigphp/Twig/tree/v3.8.0"
},
"funding": [
{
@@ -4809,35 +5247,35 @@
"type": "tidelift"
}
],
- "time": "2022-09-28T08:42:51+00:00"
+ "time": "2023-11-21T18:54:41+00:00"
},
{
"name": "vlucas/phpdotenv",
- "version": "v5.5.0",
+ "version": "v5.6.0",
"source": {
"type": "git",
"url": "https://github.com/vlucas/phpdotenv.git",
- "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7"
+ "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7",
- "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7",
+ "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4",
+ "reference": "2cf9fb6054c2bb1d59d1f3817706ecdb9d2934c4",
"shasum": ""
},
"require": {
"ext-pcre": "*",
- "graham-campbell/result-type": "^1.0.2",
- "php": "^7.1.3 || ^8.0",
- "phpoption/phpoption": "^1.8",
- "symfony/polyfill-ctype": "^1.23",
- "symfony/polyfill-mbstring": "^1.23.1",
- "symfony/polyfill-php80": "^1.23.1"
+ "graham-campbell/result-type": "^1.1.2",
+ "php": "^7.2.5 || ^8.0",
+ "phpoption/phpoption": "^1.9.2",
+ "symfony/polyfill-ctype": "^1.24",
+ "symfony/polyfill-mbstring": "^1.24",
+ "symfony/polyfill-php80": "^1.24"
},
"require-dev": {
- "bamarni/composer-bin-plugin": "^1.4.1",
+ "bamarni/composer-bin-plugin": "^1.8.2",
"ext-filter": "*",
- "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25"
+ "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
},
"suggest": {
"ext-filter": "Required to use the boolean validator."
@@ -4849,7 +5287,7 @@
"forward-command": true
},
"branch-alias": {
- "dev-master": "5.5-dev"
+ "dev-master": "5.6-dev"
}
},
"autoload": {
@@ -4881,7 +5319,7 @@
],
"support": {
"issues": "https://github.com/vlucas/phpdotenv/issues",
- "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0"
+ "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.0"
},
"funding": [
{
@@ -4893,7 +5331,7 @@
"type": "tidelift"
}
],
- "time": "2022-10-16T01:01:54+00:00"
+ "time": "2023-11-12T22:43:29+00:00"
},
{
"name": "voku/portable-ascii",
@@ -4968,40 +5406,101 @@
}
],
"time": "2022-03-08T17:03:00+00:00"
+ },
+ {
+ "name": "webmozart/assert",
+ "version": "1.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozarts/assert.git",
+ "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
+ "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<0.12.20",
+ "vimeo/psalm": "<4.6.1 || 4.6.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.5.13"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.10-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Assert\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Assertions to validate method input/output with nice error messages.",
+ "keywords": [
+ "assert",
+ "check",
+ "validate"
+ ],
+ "support": {
+ "issues": "https://github.com/webmozarts/assert/issues",
+ "source": "https://github.com/webmozarts/assert/tree/1.11.0"
+ },
+ "time": "2022-06-03T18:03:27+00:00"
}
],
"packages-dev": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
- "version": "v0.7.2",
+ "version": "v1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
- "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
+ "url": "https://github.com/PHPCSStandards/composer-installer.git",
+ "reference": "4be43904336affa5c2f70744a348312336afd0da"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
- "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
+ "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da",
+ "reference": "4be43904336affa5c2f70744a348312336afd0da",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
- "php": ">=5.3",
+ "php": ">=5.4",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
+ "ext-json": "*",
+ "ext-zip": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
- "phpcompatibility/php-compatibility": "^9.0"
+ "phpcompatibility/php-compatibility": "^9.0",
+ "yoast/phpunit-polyfills": "^1.0"
},
"type": "composer-plugin",
"extra": {
- "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
+ "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
- "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
+ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -5017,7 +5516,7 @@
},
{
"name": "Contributors",
- "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
+ "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
@@ -5041,32 +5540,31 @@
"tests"
],
"support": {
- "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
- "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
+ "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
+ "source": "https://github.com/PHPCSStandards/composer-installer"
},
- "time": "2022-02-04T12:51:07+00:00"
+ "time": "2023-01-05T11:28:13+00:00"
},
{
"name": "dms/phpunit-arraysubset-asserts",
- "version": "v0.4.0",
+ "version": "v0.5.0",
"source": {
"type": "git",
"url": "https://github.com/rdohms/phpunit-arraysubset-asserts.git",
- "reference": "428293c2a00eceefbad71a2dbdfb913febb35de2"
+ "reference": "aa6b9e858414e91cca361cac3b2035ee57d212e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/rdohms/phpunit-arraysubset-asserts/zipball/428293c2a00eceefbad71a2dbdfb913febb35de2",
- "reference": "428293c2a00eceefbad71a2dbdfb913febb35de2",
+ "url": "https://api.github.com/repos/rdohms/phpunit-arraysubset-asserts/zipball/aa6b9e858414e91cca361cac3b2035ee57d212e0",
+ "reference": "aa6b9e858414e91cca361cac3b2035ee57d212e0",
"shasum": ""
},
"require": {
"php": "^5.4 || ^7.0 || ^8.0",
- "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
+ "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0"
},
"require-dev": {
- "dms/coding-standard": "^9",
- "squizlabs/php_codesniffer": "^3.4"
+ "dms/coding-standard": "^9"
},
"type": "library",
"autoload": {
@@ -5087,36 +5585,36 @@
"description": "This package provides ArraySubset and related asserts once deprecated in PHPUnit 8",
"support": {
"issues": "https://github.com/rdohms/phpunit-arraysubset-asserts/issues",
- "source": "https://github.com/rdohms/phpunit-arraysubset-asserts/tree/v0.4.0"
+ "source": "https://github.com/rdohms/phpunit-arraysubset-asserts/tree/v0.5.0"
},
- "time": "2022-02-13T15:00:28+00:00"
+ "time": "2023-06-02T17:33:53+00:00"
},
{
"name": "doctrine/instantiator",
- "version": "1.4.1",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
- "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
+ "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
- "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
+ "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0"
+ "php": "^8.1"
},
"require-dev": {
- "doctrine/coding-standard": "^9",
+ "doctrine/coding-standard": "^11",
"ext-pdo": "*",
"ext-phar": "*",
- "phpbench/phpbench": "^0.16 || ^1",
- "phpstan/phpstan": "^1.4",
- "phpstan/phpstan-phpunit": "^1",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
- "vimeo/psalm": "^4.22"
+ "phpbench/phpbench": "^1.2",
+ "phpstan/phpstan": "^1.9.4",
+ "phpstan/phpstan-phpunit": "^1.3",
+ "phpunit/phpunit": "^9.5.27",
+ "vimeo/psalm": "^5.4"
},
"type": "library",
"autoload": {
@@ -5143,7 +5641,7 @@
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
- "source": "https://github.com/doctrine/instantiator/tree/1.4.1"
+ "source": "https://github.com/doctrine/instantiator/tree/2.0.0"
},
"funding": [
{
@@ -5159,20 +5657,20 @@
"type": "tidelift"
}
],
- "time": "2022-03-03T08:28:38+00:00"
+ "time": "2022-12-30T00:23:10+00:00"
},
{
"name": "fakerphp/faker",
- "version": "v1.21.0",
+ "version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/FakerPHP/Faker.git",
- "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d"
+ "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/92efad6a967f0b79c499705c69b662f738cc9e4d",
- "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d",
+ "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01",
+ "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01",
"shasum": ""
},
"require": {
@@ -5225,9 +5723,9 @@
],
"support": {
"issues": "https://github.com/FakerPHP/Faker/issues",
- "source": "https://github.com/FakerPHP/Faker/tree/v1.21.0"
+ "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0"
},
- "time": "2022-12-13T13:54:32+00:00"
+ "time": "2023-06-12T08:44:38+00:00"
},
{
"name": "fig/log-test",
@@ -5277,16 +5775,16 @@
},
{
"name": "filp/whoops",
- "version": "2.14.6",
+ "version": "2.15.4",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
- "reference": "f7948baaa0330277c729714910336383286305da"
+ "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/filp/whoops/zipball/f7948baaa0330277c729714910336383286305da",
- "reference": "f7948baaa0330277c729714910336383286305da",
+ "url": "https://api.github.com/repos/filp/whoops/zipball/a139776fa3f5985a50b509f2a02ff0f709d2a546",
+ "reference": "a139776fa3f5985a50b509f2a02ff0f709d2a546",
"shasum": ""
},
"require": {
@@ -5336,7 +5834,7 @@
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
- "source": "https://github.com/filp/whoops/tree/2.14.6"
+ "source": "https://github.com/filp/whoops/tree/2.15.4"
},
"funding": [
{
@@ -5344,20 +5842,20 @@
"type": "github"
}
],
- "time": "2022-11-02T16:23:29+00:00"
+ "time": "2023-11-03T12:00:00+00:00"
},
{
"name": "myclabs/deep-copy",
- "version": "1.11.0",
+ "version": "1.11.1",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
+ "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
- "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
+ "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
"shasum": ""
},
"require": {
@@ -5395,7 +5893,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
},
"funding": [
{
@@ -5403,20 +5901,20 @@
"type": "tidelift"
}
],
- "time": "2022-03-03T13:19:32+00:00"
+ "time": "2023-03-08T13:26:56+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v4.15.2",
+ "version": "v4.18.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
+ "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
- "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999",
+ "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999",
"shasum": ""
},
"require": {
@@ -5457,9 +5955,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0"
},
- "time": "2022-11-12T15:38:23+00:00"
+ "time": "2023-12-10T21:03:43+00:00"
},
{
"name": "phar-io/manifest",
@@ -5574,22 +6072,24 @@
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.13.1",
+ "version": "1.24.5",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "aac44118344d197e6d5f7c6cee91885f0a89acdd"
+ "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/aac44118344d197e6d5f7c6cee91885f0a89acdd",
- "reference": "aac44118344d197e6d5f7c6cee91885f0a89acdd",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fedf211ff14ec8381c9bf5714e33a7a552dd1acc",
+ "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
+ "doctrine/annotations": "^2.0",
+ "nikic/php-parser": "^4.15",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.5",
@@ -5613,22 +6113,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.13.1"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.5"
},
- "time": "2022-11-20T08:52:26+00:00"
+ "time": "2023-12-16T09:33:33+00:00"
},
{
"name": "phpstan/phpstan",
- "version": "1.9.3",
+ "version": "1.10.50",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "709999b91448d4f2bb07daffffedc889b33e461c"
+ "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/709999b91448d4f2bb07daffffedc889b33e461c",
- "reference": "709999b91448d4f2bb07daffffedc889b33e461c",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/06a98513ac72c03e8366b5a0cb00750b487032e4",
+ "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4",
"shasum": ""
},
"require": {
@@ -5657,8 +6157,11 @@
"static analysis"
],
"support": {
+ "docs": "https://phpstan.org/user-guide/getting-started",
+ "forum": "https://github.com/phpstan/phpstan/discussions",
"issues": "https://github.com/phpstan/phpstan/issues",
- "source": "https://github.com/phpstan/phpstan/tree/1.9.3"
+ "security": "https://github.com/phpstan/phpstan/security/policy",
+ "source": "https://github.com/phpstan/phpstan-src"
},
"funding": [
{
@@ -5674,27 +6177,27 @@
"type": "tidelift"
}
],
- "time": "2022-12-13T10:28:10+00:00"
+ "time": "2023-12-13T10:59:42+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.20",
+ "version": "9.2.30",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "af7463c955007de36db0c5e26d03e2f933c2e980"
+ "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/af7463c955007de36db0c5e26d03e2f933c2e980",
- "reference": "af7463c955007de36db0c5e26d03e2f933c2e980",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089",
+ "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-libxml": "*",
"ext-xmlwriter": "*",
- "nikic/php-parser": "^4.14",
+ "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=7.3",
"phpunit/php-file-iterator": "^3.0.3",
"phpunit/php-text-template": "^2.0.2",
@@ -5709,8 +6212,8 @@
"phpunit/phpunit": "^9.3"
},
"suggest": {
- "ext-pcov": "*",
- "ext-xdebug": "*"
+ "ext-pcov": "PHP extension that provides line coverage",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
},
"type": "library",
"extra": {
@@ -5743,7 +6246,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.20"
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30"
},
"funding": [
{
@@ -5751,7 +6255,7 @@
"type": "github"
}
],
- "time": "2022-12-13T07:49:28+00:00"
+ "time": "2023-12-22T06:47:57+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -5996,20 +6500,20 @@
},
{
"name": "phpunit/phpunit",
- "version": "9.5.27",
+ "version": "9.6.15",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38"
+ "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38",
- "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/05017b80304e0eb3f31d90194a563fd53a6021f1",
+ "reference": "05017b80304e0eb3f31d90194a563fd53a6021f1",
"shasum": ""
},
"require": {
- "doctrine/instantiator": "^1.3.1",
+ "doctrine/instantiator": "^1.3.1 || ^2",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
@@ -6020,7 +6524,7 @@
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=7.3",
- "phpunit/php-code-coverage": "^9.2.13",
+ "phpunit/php-code-coverage": "^9.2.28",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
@@ -6038,8 +6542,8 @@
"sebastian/version": "^3.0.2"
},
"suggest": {
- "ext-soap": "*",
- "ext-xdebug": "*"
+ "ext-soap": "To be able to generate mocks based on WSDL files",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
},
"bin": [
"phpunit"
@@ -6047,7 +6551,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.5-dev"
+ "dev-master": "9.6-dev"
}
},
"autoload": {
@@ -6078,7 +6582,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27"
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.15"
},
"funding": [
{
@@ -6094,7 +6599,7 @@
"type": "tidelift"
}
],
- "time": "2022-12-09T07:31:23+00:00"
+ "time": "2023-12-01T16:55:19+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -6339,20 +6844,20 @@
},
{
"name": "sebastian/complexity",
- "version": "2.0.2",
+ "version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
- "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
+ "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
- "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a",
+ "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.7",
+ "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=7.3"
},
"require-dev": {
@@ -6384,7 +6889,7 @@
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
- "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
+ "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3"
},
"funding": [
{
@@ -6392,20 +6897,20 @@
"type": "github"
}
],
- "time": "2020-10-26T15:52:27+00:00"
+ "time": "2023-12-22T06:19:30+00:00"
},
{
"name": "sebastian/diff",
- "version": "4.0.4",
+ "version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
+ "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
- "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
+ "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
"shasum": ""
},
"require": {
@@ -6450,7 +6955,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
- "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
+ "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5"
},
"funding": [
{
@@ -6458,20 +6963,20 @@
"type": "github"
}
],
- "time": "2020-10-26T13:10:38+00:00"
+ "time": "2023-05-07T05:35:17+00:00"
},
{
"name": "sebastian/environment",
- "version": "5.1.4",
+ "version": "5.1.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
+ "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
- "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
+ "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
"shasum": ""
},
"require": {
@@ -6513,7 +7018,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
- "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
+ "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5"
},
"funding": [
{
@@ -6521,7 +7026,7 @@
"type": "github"
}
],
- "time": "2022-04-03T09:37:03+00:00"
+ "time": "2023-02-03T06:03:51+00:00"
},
{
"name": "sebastian/exporter",
@@ -6602,16 +7107,16 @@
},
{
"name": "sebastian/global-state",
- "version": "5.0.5",
+ "version": "5.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
+ "reference": "bde739e7565280bda77be70044ac1047bc007e34"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
- "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
+ "reference": "bde739e7565280bda77be70044ac1047bc007e34",
"shasum": ""
},
"require": {
@@ -6654,7 +7159,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
- "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
+ "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
},
"funding": [
{
@@ -6662,24 +7167,24 @@
"type": "github"
}
],
- "time": "2022-02-14T08:28:10+00:00"
+ "time": "2023-08-02T09:26:13+00:00"
},
{
"name": "sebastian/lines-of-code",
- "version": "1.0.3",
+ "version": "1.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
- "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
+ "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
- "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5",
+ "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.6",
+ "nikic/php-parser": "^4.18 || ^5.0",
"php": ">=7.3"
},
"require-dev": {
@@ -6711,7 +7216,7 @@
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
- "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4"
},
"funding": [
{
@@ -6719,7 +7224,7 @@
"type": "github"
}
],
- "time": "2020-11-28T06:42:11+00:00"
+ "time": "2023-12-22T06:20:34+00:00"
},
{
"name": "sebastian/object-enumerator",
@@ -6835,16 +7340,16 @@
},
{
"name": "sebastian/recursion-context",
- "version": "4.0.4",
+ "version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
+ "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
- "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
+ "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
"shasum": ""
},
"require": {
@@ -6883,10 +7388,10 @@
}
],
"description": "Provides functionality to recursively process PHP variables",
- "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5"
},
"funding": [
{
@@ -6894,7 +7399,7 @@
"type": "github"
}
],
- "time": "2020-10-26T13:17:30+00:00"
+ "time": "2023-02-03T06:07:39+00:00"
},
{
"name": "sebastian/resource-operations",
@@ -6953,16 +7458,16 @@
},
{
"name": "sebastian/type",
- "version": "3.2.0",
+ "version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
- "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
+ "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
- "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
+ "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
"shasum": ""
},
"require": {
@@ -6997,7 +7502,7 @@
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
- "source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
+ "source": "https://github.com/sebastianbergmann/type/tree/3.2.1"
},
"funding": [
{
@@ -7005,7 +7510,7 @@
"type": "github"
}
],
- "time": "2022-09-12T14:47:03+00:00"
+ "time": "2023-02-03T06:13:03+00:00"
},
{
"name": "sebastian/version",
@@ -7062,32 +7567,32 @@
},
{
"name": "slevomat/coding-standard",
- "version": "8.6.4",
+ "version": "8.14.1",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
- "reference": "8a02c83e59c3230a2a4367b29956a2f2b56e3a24"
+ "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/8a02c83e59c3230a2a4367b29956a2f2b56e3a24",
- "reference": "8a02c83e59c3230a2a4367b29956a2f2b56e3a24",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/fea1fd6f137cc84f9cba0ae30d549615dbc6a926",
+ "reference": "fea1fd6f137cc84f9cba0ae30d549615dbc6a926",
"shasum": ""
},
"require": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0",
"php": "^7.2 || ^8.0",
- "phpstan/phpdoc-parser": ">=1.11.0 <1.14.0",
+ "phpstan/phpdoc-parser": "^1.23.1",
"squizlabs/php_codesniffer": "^3.7.1"
},
"require-dev": {
"phing/phing": "2.17.4",
"php-parallel-lint/php-parallel-lint": "1.3.2",
- "phpstan/phpstan": "1.4.10|1.9.2",
- "phpstan/phpstan-deprecation-rules": "1.0.0",
- "phpstan/phpstan-phpunit": "1.0.0|1.2.2",
- "phpstan/phpstan-strict-rules": "1.4.4",
- "phpunit/phpunit": "7.5.20|8.5.21|9.5.26"
+ "phpstan/phpstan": "1.10.37",
+ "phpstan/phpstan-deprecation-rules": "1.1.4",
+ "phpstan/phpstan-phpunit": "1.3.14",
+ "phpstan/phpstan-strict-rules": "1.5.1",
+ "phpunit/phpunit": "8.5.21|9.6.8|10.3.5"
},
"type": "phpcodesniffer-standard",
"extra": {
@@ -7097,7 +7602,7 @@
},
"autoload": {
"psr-4": {
- "SlevomatCodingStandard\\": "SlevomatCodingStandard"
+ "SlevomatCodingStandard\\": "SlevomatCodingStandard/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -7111,7 +7616,7 @@
],
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
- "source": "https://github.com/slevomat/coding-standard/tree/8.6.4"
+ "source": "https://github.com/slevomat/coding-standard/tree/8.14.1"
},
"funding": [
{
@@ -7123,20 +7628,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-14T09:26:24+00:00"
+ "time": "2023-10-08T07:28:08+00:00"
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.7.1",
+ "version": "3.8.0",
"source": {
"type": "git",
- "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619"
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619",
- "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5805f7a4e4958dbb5e944ef1e6edae0a303765e7",
+ "reference": "5805f7a4e4958dbb5e944ef1e6edae0a303765e7",
"shasum": ""
},
"require": {
@@ -7146,7 +7651,7 @@
"php": ">=5.4.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/phpcs",
@@ -7165,56 +7670,77 @@
"authors": [
{
"name": "Greg Sherwood",
- "role": "lead"
+ "role": "Former lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "Current lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
- "homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
"keywords": [
"phpcs",
- "standards"
+ "standards",
+ "static analysis"
],
"support": {
- "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
- "source": "https://github.com/squizlabs/PHP_CodeSniffer",
- "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
+ "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
+ "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
},
- "time": "2022-06-18T07:21:10+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2023-12-08T12:32:31+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v6.2.1",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "1e7544c8698627b908657e5276854d52ab70087a"
+ "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1e7544c8698627b908657e5276854d52ab70087a",
- "reference": "1e7544c8698627b908657e5276854d52ab70087a",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6",
+ "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6",
"shasum": ""
},
"require": {
"php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "phpunit/phpunit": "<5.4.3",
"symfony/console": "<5.4"
},
"require-dev": {
"ext-iconv": "*",
- "symfony/console": "^5.4|^6.0",
- "symfony/process": "^5.4|^6.0",
- "symfony/uid": "^5.4|^6.0",
+ "symfony/console": "^5.4|^6.0|^7.0",
+ "symfony/error-handler": "^6.3|^7.0",
+ "symfony/http-kernel": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
+ "symfony/uid": "^5.4|^6.0|^7.0",
"twig/twig": "^2.13|^3.0.4"
},
- "suggest": {
- "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
- "ext-intl": "To show region name in time zone dump",
- "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
- },
"bin": [
"Resources/bin/var-dump-server"
],
@@ -7251,7 +7777,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v6.2.1"
+ "source": "https://github.com/symfony/var-dumper/tree/v6.4.0"
},
"funding": [
{
@@ -7267,20 +7793,20 @@
"type": "tidelift"
}
],
- "time": "2022-12-03T22:32:58+00:00"
+ "time": "2023-11-09T08:28:32+00:00"
},
{
"name": "theseer/tokenizer",
- "version": "1.2.1",
+ "version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
- "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
+ "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
- "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
+ "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
"shasum": ""
},
"require": {
@@ -7309,7 +7835,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
- "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.2"
},
"funding": [
{
@@ -7317,7 +7843,7 @@
"type": "github"
}
],
- "time": "2021-07-28T10:34:58+00:00"
+ "time": "2023-11-20T00:12:19+00:00"
}
],
"aliases": [],
@@ -7335,5 +7861,5 @@
"ext-xml": "*"
},
"platform-dev": [],
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.6.0"
}
diff --git a/config/app.php b/config/app.php
index 2386dbbc8..651790969 100644
--- a/config/app.php
+++ b/config/app.php
@@ -28,7 +28,6 @@
\Engelsystem\Renderer\TwigServiceProvider::class,
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
- \Engelsystem\Middleware\SessionHandlerServiceProvider::class,
\Engelsystem\Http\Validation\ValidationServiceProvider::class,
\Engelsystem\Http\RedirectServiceProvider::class,
@@ -38,6 +37,7 @@
\Engelsystem\Http\HttpClientServiceProvider::class,
\Engelsystem\Helpers\DumpServerServiceProvider::class,
\Engelsystem\Helpers\UuidServiceProvider::class,
+ \Engelsystem\Controllers\Api\UsesAuthServiceProvider::class,
],
// Application middleware
@@ -48,10 +48,13 @@
// Changes of request/response parameters
\Engelsystem\Middleware\SetLocale::class,
+ \Engelsystem\Middleware\ETagHandler::class,
\Engelsystem\Middleware\AddHeaders::class,
+ \Engelsystem\Middleware\TrimInput::class,
// The application code
\Engelsystem\Middleware\ErrorHandler::class,
+ \Engelsystem\Middleware\ApiRouteHandler::class,
\Engelsystem\Middleware\VerifyCsrfToken::class,
\Engelsystem\Middleware\RouteDispatcher::class,
\Engelsystem\Middleware\SessionHandler::class,
@@ -73,6 +76,7 @@
'message.created' => \Engelsystem\Events\Listener\Messages::class . '@created',
'news.created' => \Engelsystem\Events\Listener\News::class . '@created',
+ 'news.updated' => \Engelsystem\Events\Listener\News::class . '@updated',
'oauth2.login' => \Engelsystem\Events\Listener\OAuth2::class . '@login',
@@ -80,5 +84,7 @@
\Engelsystem\Events\Listener\Shift::class . '@deletedEntryCreateWorklog',
\Engelsystem\Events\Listener\Shift::class . '@deletedEntrySendEmail',
],
+
+ 'shift.updating' => \Engelsystem\Events\Listener\Shift::class . '@updatedShiftSendEmail',
],
];
diff --git a/config/config.default.php b/config/config.default.php
index b39113114..352ab4e2f 100644
--- a/config/config.default.php
+++ b/config/config.default.php
@@ -13,7 +13,7 @@
'password' => env('MYSQL_PASSWORD', ''),
],
- // For accessing stats
+ // For accessing /metrics, /stats and custom FSR endpoints (e.g., pretix integration)
'api_key' => env('API_KEY', ''),
// Enable maintenance mode (show a static page)
@@ -25,19 +25,29 @@
// 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
// Available link placeholders: %lang%
+ // To disable a header_item in the config.php, you can set its value to null
'header_items' => [
- //'Foo' => 'https://foo.bar/batz-%lang%.html',
+ // Name can be a translation string, permission is a engelsystem privilege
+ // 'Name' => 'URL',
+ // 'Name' => ['URL', 'permission'],
+
+ //'Foo' => ['https://foo.bar/batz-%lang%.html', 'logout'], // Permission: for logged-in users
],
// Footer links
+ // To disable a footer item in the config.php, you can set its value to null
'footer_items' => [
+ // Name can be a translation string, permission is a engelsystem privilege
+ // 'Name' => 'URL',
+ // 'Name' => ['URL', 'permission'],
+
// URL to the angel faq and job description
- 'FAQ' => env('FAQ_URL', '/faq'),
+ 'faq.faq' => [env('FAQ_URL', '/faq'), 'faq.view'],
// Contact email address, linked on every page
'Contact' => env('CONTACT_EMAIL', 'mailto:mail@example.com'),
@@ -47,7 +57,7 @@
'faq_text' => env('FAQ_TEXT', null),
// Link to documentation/help
- 'documentation_url' => 'https://engelsystem.de/doc/',
+ 'documentation_url' => env('DOCUMENTATION_URL', 'https://engelsystem.de/doc/'),
// Email config
'email' => [
@@ -69,7 +79,7 @@
],
# Your privacy@ contact address
- 'privacy_email' => '',
+ 'privacy_email' => env('PRIVACY_EMAIL', null),
// Initial admin password
'setup_admin_password' => env('SETUP_ADMIN_PASSWORD', null),
@@ -91,7 +101,7 @@
// User info URL which provides userdata
'url_info' => env('OIDC_USERINFO_URL', ''),
// OAuth Scopes
- // 'scope' => ['openid'],
+ 'scope' => ['openid', 'email', 'profile'],
// Info unique user id field
'id' => env('OIDC_ID_CLAIM', 'uuid'),
// The following fields are used for registration
@@ -128,7 +138,19 @@
// Default theme, 1=style1.css
'theme' => env('THEME', 1),
+ // Supported themes
+ // To disable a theme in the config.php, you can set its value to null
'themes' => [
+ 17 => [
+ 'name' => 'Engelsystem 37c3 (2023)',
+ 'type' => 'dark',
+ 'navbar_classes' => 'navbar-dark',
+ ],
+ 16 => [
+ 'name' => 'Engelsystem cccamp23 (2023)',
+ 'type' => 'dark',
+ 'navbar_classes' => 'navbar-dark',
+ ],
15 => [
'name' => 'Engelsystem rC3 (2021)',
'type' => 'dark',
@@ -221,6 +243,16 @@
// Users are able to sign up
'registration_enabled' => (bool) env('REGISTRATION_ENABLED', true),
+ // Required user fields
+ 'required_user_fields' => [
+ 'pronoun' => (bool) env('PRONOUN_REQUIRED', false),
+ 'firstname' => (bool) env('FIRSTNAME_REQUIRED', false),
+ 'lastname' => (bool) env('LASTNAME_REQUIRED', false),
+ 'tshirt_size' => (bool) env('TSHIRT_SIZE_REQUIRED', true),
+ 'mobile' => (bool) env('MOBILE_REQUIRED', false),
+ 'dect' => (bool) env('DECT_REQUIRED', false),
+ ],
+
// Only arrived angels can sign up for shifts
'signup_requires_arrival' => (bool) env('SIGNUP_REQUIRES_ARRIVAL', false),
@@ -247,7 +279,7 @@
// 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' => PASSWORD_DEFAULT,
+ 'password_algorithm' => env('PASSWORD_ALGORITHM', PASSWORD_DEFAULT),
// The minimum length for passwords
'min_password_length' => env('PASSWORD_MINIMUM_LENGTH', 8),
@@ -263,6 +295,10 @@
// 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
'enable_user_name' => (bool) env('ENABLE_USER_NAME', false),
@@ -311,7 +347,15 @@
'voucher_start' => env('VOUCHER_START', null) ?: null,
],
+ # Instruction in accordance with Β§ 43 Para. 1 of the German Infection Protection Act (IfSG)
+ 'ifsg_enabled' => (bool) env('IFSG_ENABLED', false),
+
+ # Instruction only onsite in accordance with Β§ 43 Para. 1 of the German Infection Protection Act (IfSG)
+ 'ifsg_light_enabled' => (bool) env('IFSG_LIGHT_ENABLED', false)
+ && env('IFSG_ENABLED', false),
+
// Available locales in /resources/lang/
+ // To disable a locale in the config.php, you can set its value to null
'locales' => [
'de_DE' => 'Deutsch',
'en_US' => 'English',
@@ -320,21 +364,28 @@
// The default locale to use
'default_locale' => env('DEFAULT_LOCALE', 'en_US'),
- // Available T-Shirt sizes, set value to null if not available
+ // Available T-Shirt sizes
+ // To disable a t-shirt size in the config.php, you can set its value to null
'tshirt_sizes' => [
'S' => 'Small Straight-Cut',
- 'S-G' => 'Small Fitted-Cut',
+ 'S-F' => 'Small Fitted-Cut',
'M' => 'Medium Straight-Cut',
- 'M-G' => 'Medium Fitted-Cut',
+ 'M-F' => 'Medium Fitted-Cut',
'L' => 'Large Straight-Cut',
- 'L-G' => 'Large Fitted-Cut',
+ 'L-F' => 'Large Fitted-Cut',
'XL' => 'XLarge Straight-Cut',
- 'XL-G' => 'XLarge Fitted-Cut',
+ 'XL-F' => 'XLarge Fitted-Cut',
'2XL' => '2XLarge Straight-Cut',
'3XL' => '3XLarge Straight-Cut',
'4XL' => '4XLarge Straight-Cut',
],
+ // Whether to show the current day of the event (-2, -1, 0, 1, 2β¦) in footer and on the dashboard.
+ // The event start date has to be set for it to appear.
+ 'enable_show_day_of_event' => false,
+ // If true there will be a day 0 (-1, 0, 1β¦). If false there won't (-1, 1β¦)
+ 'event_has_day0' => true,
+
'metrics' => [
// User work buckets in seconds
'work' => [1 * 60 * 60, 1.5 * 60 * 60, 2 * 60 * 60, 3 * 60 * 60, 5 * 60 * 60, 10 * 60 * 60, 20 * 60 * 60],
@@ -363,11 +414,16 @@
// Add additional headers
'add_headers' => (bool) env('ADD_HEADERS', true),
+ // Predefined headers
+ // To disable a header in the config.php, you can set its value to null
'headers' => [
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'sameorigin',
'Referrer-Policy' => 'strict-origin-when-cross-origin',
- 'Content-Security-Policy' => 'default-src \'self\' \'unsafe-inline\' \'unsafe-eval\'; img-src \'self\' data:;',
+ 'Content-Security-Policy' =>
+ 'default-src \'self\'; '
+ . ' style-src \'self\' \'unsafe-inline\'; '
+ . 'img-src \'self\' data:;',
'X-XSS-Protection' => '1; mode=block',
'Feature-Policy' => 'autoplay \'none\'',
//'Strict-Transport-Security' => 'max-age=7776000',
diff --git a/config/routes.php b/config/routes.php
index 1aaf52091..767a44c48 100644
--- a/config/routes.php
+++ b/config/routes.php
@@ -8,6 +8,8 @@
// Pages
$route->get('/', 'HomeController@index');
+$route->get('/register', 'RegistrationController@view');
+$route->post('/register', 'RegistrationController@save');
$route->get('/credits', 'CreditsController@index');
$route->get('/health', 'HealthController@index');
@@ -38,7 +40,14 @@ function (RouteCollector $route): void {
$route->post('/theme', 'SettingsController@saveTheme');
$route->get('/language', 'SettingsController@language');
$route->post('/language', 'SettingsController@saveLanguage');
+ $route->get('/certificates', 'SettingsController@certificate');
+ $route->post('/certificates/ifsg', 'SettingsController@saveIfsgCertificate');
+ $route->post('/certificates/driving', 'SettingsController@saveDrivingLicense');
+ $route->get('/api', 'SettingsController@api');
+ $route->post('/api', 'SettingsController@apiKeyReset');
$route->get('/oauth', 'SettingsController@oauth');
+ $route->get('/sessions', 'SettingsController@sessions');
+ $route->post('/sessions', 'SettingsController@sessionsDelete');
}
);
@@ -62,6 +71,11 @@ function (RouteCollector $route): void {
$route->get('/about', 'AngelTypesController@about');
});
+// Shifts
+$route->addGroup('/shifts', function (RouteCollector $route): void {
+ $route->get('/random', 'ShiftsController@random');
+});
+
// News
$route->get('/meetings', 'NewsController@meetings');
$route->addGroup(
@@ -101,8 +115,46 @@ function (RouteCollector $route): void {
);
// API
-$route->get('/api/usershifts[/{email:.+}]', 'ApiController@usershifts');
-$route->get('/api[/{resource:.+}]', 'ApiController@index');
+$route->addGroup(
+ '/api',
+ function (RouteCollector $route): void {
+ $route->get('', 'Api\IndexController@index');
+
+ $route->addGroup(
+ '/v0-beta',
+ function (RouteCollector $route): void {
+ $route->addRoute(['OPTIONS'], '[/{resource:.+}]', 'Api\IndexController@options');
+ $route->get('', 'Api\IndexController@indexV0');
+ $route->get('/openapi', 'Api\IndexController@openApiV0');
+ $route->get('/info', 'Api\IndexController@info');
+
+ $route->get('/angeltypes', 'Api\AngelTypeController@index');
+ $route->get('/angeltypes/{angeltype_id:\d+}/shifts', 'Api\ShiftsController@entriesByAngeltype');
+
+ $route->get('/locations', 'Api\LocationsController@index');
+ $route->get('/locations/{location_id:\d+}/shifts', 'Api\ShiftsController@entriesByLocation');
+
+ $route->get('/news', 'Api\NewsController@index');
+
+ $route->get('/users/{user_id:(?:\d+|self)}', 'Api\UsersController@user');
+ $route->get('/users/{user_id:(?:\d+|self)}/angeltypes', 'Api\AngelTypeController@ofUser');
+ $route->get('/users/{user_id:(?:\d+|self)}/shifts', 'Api\ShiftsController@entriesByUser');
+
+ $route->addRoute(
+ ['POST', 'PUT', 'DELETE', 'PATCH'],
+ '/[{resource:.+}]',
+ 'Api\IndexController@notImplemented'
+ );
+ $route->get('/[{resource:.+}]', 'Api\IndexController@notFound');
+ }
+ );
+
+ // Routes for custom FSR requests (e.g., pretix integration)
+ $route->get('/usershifts[/{email:.+}]', 'Api\FsrController@usershifts');
+
+ $route->get('/[{resource:.+}]', 'Api\IndexController@notFound');
+ }
+);
// Feeds
$route->get('/atom', 'FeedController@atom');
@@ -147,6 +199,27 @@ function (RouteCollector $route): void {
}
);
+ // Shifts
+ $route->addGroup(
+ '/shifts',
+ function (RouteCollector $route): void {
+ $route->get('/history', 'Admin\\ShiftsController@history');
+ $route->post('/history', 'Admin\\ShiftsController@deleteTransaction');
+ }
+ );
+
+ // Shift types
+ $route->addGroup(
+ '/shifttypes',
+ function (RouteCollector $route): void {
+ $route->get('', 'Admin\\ShiftTypesController@index');
+ $route->post('', 'Admin\\ShiftTypesController@delete');
+ $route->get('/{shift_type_id:\d+}', 'Admin\\ShiftTypesController@view');
+ $route->get('/edit[/{shift_type_id:\d+}]', 'Admin\\ShiftTypesController@edit');
+ $route->post('/edit[/{shift_type_id:\d+}]', 'Admin\\ShiftTypesController@save');
+ }
+ );
+
// Questions
$route->addGroup(
'/questions',
@@ -158,14 +231,14 @@ function (RouteCollector $route): void {
}
);
- // Rooms
+ // Locations
$route->addGroup(
- '/rooms',
+ '/locations',
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('', 'Admin\\LocationsController@index');
+ $route->post('', 'Admin\\LocationsController@delete');
+ $route->get('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@edit');
+ $route->post('/edit[/{location_id:\d+}]', 'Admin\\LocationsController@save');
}
);
diff --git a/db/factories/AngelTypeFactory.php b/db/factories/AngelTypeFactory.php
index 139441574..9a8e6f42b 100644
--- a/db/factories/AngelTypeFactory.php
+++ b/db/factories/AngelTypeFactory.php
@@ -24,9 +24,11 @@ public function definition(): array
'restricted' => $this->faker->boolean(),
'requires_driver_license' => $this->faker->boolean(),
- 'no_self_signup' => $this->faker->boolean(),
+ 'requires_ifsg_certificate' => $this->faker->boolean(),
+ 'shift_self_signup' => $this->faker->boolean(),
'show_on_dashboard' => $this->faker->boolean(),
'hide_register' => $this->faker->boolean(),
+ 'hide_on_shift_view' => $this->faker->boolean(),
];
}
}
diff --git a/db/factories/RoomFactory.php b/db/factories/LocationFactory.php
similarity index 66%
rename from db/factories/RoomFactory.php
rename to db/factories/LocationFactory.php
index 0a06959b4..5dd37e92b 100644
--- a/db/factories/RoomFactory.php
+++ b/db/factories/LocationFactory.php
@@ -4,13 +4,13 @@
namespace Database\Factories\Engelsystem\Models;
-use Engelsystem\Models\Room;
+use Engelsystem\Models\Location;
use Illuminate\Database\Eloquent\Factories\Factory;
-class RoomFactory extends Factory
+class LocationFactory extends Factory
{
/** @var string */
- protected $model = Room::class; // phpcs:ignore
+ protected $model = Location::class; // phpcs:ignore
public function definition(): array
{
@@ -18,6 +18,7 @@ public function definition(): array
'name' => $this->faker->unique()->firstName(),
'map_url' => $this->faker->url(),
'description' => $this->faker->text(),
+ 'dect' => $this->faker->optional()->numberBetween(1000, 9999),
];
}
}
diff --git a/db/factories/NewsFactory.php b/db/factories/NewsFactory.php
index 54b39d36a..f2af8ccfd 100644
--- a/db/factories/NewsFactory.php
+++ b/db/factories/NewsFactory.php
@@ -16,12 +16,12 @@ class NewsFactory extends Factory
public function definition(): array
{
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(),
+ 'title' => $this->faker->text(50),
+ 'text' => $this->faker->realText(),
+ 'is_meeting' => $this->faker->boolean(),
+ 'is_pinned' => $this->faker->boolean(.1),
+ 'is_highlighted' => $this->faker->boolean(.1),
+ 'user_id' => User::factory(),
];
}
}
diff --git a/db/factories/OAuthFactory.php b/db/factories/OAuthFactory.php
new file mode 100644
index 000000000..0e377aa47
--- /dev/null
+++ b/db/factories/OAuthFactory.php
@@ -0,0 +1,30 @@
+
+ */
+ public function definition(): array
+ {
+ return [
+ 'user_id' => User::factory(),
+ 'provider' => $this->faker->unique()->word(),
+ 'identifier' => $this->faker->unique()->word(),
+ 'access_token' => $this->faker->unique()->word(),
+ 'refresh_token' => $this->faker->unique()->word(),
+ 'expires_at' => $this->faker->dateTimeInInterval('+5 days', '+3 months')->format('Y-m-d'),
+ ];
+ }
+}
diff --git a/db/factories/SessionFactory.php b/db/factories/SessionFactory.php
new file mode 100644
index 000000000..1f455140f
--- /dev/null
+++ b/db/factories/SessionFactory.php
@@ -0,0 +1,24 @@
+ $this->faker->lexify('????????????????????????????????'),
+ 'payload' => $this->faker->text(100),
+ 'user_id' => $this->faker->optional()->passthrough(User::factory()),
+ ];
+ }
+}
diff --git a/db/factories/Shifts/NeededAngelTypeFactory.php b/db/factories/Shifts/NeededAngelTypeFactory.php
index ee07e534e..7698068e4 100644
--- a/db/factories/Shifts/NeededAngelTypeFactory.php
+++ b/db/factories/Shifts/NeededAngelTypeFactory.php
@@ -5,7 +5,7 @@
namespace Database\Factories\Engelsystem\Models\Shifts;
use Engelsystem\Models\AngelType;
-use Engelsystem\Models\Room;
+use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\NeededAngelType;
use Engelsystem\Models\Shifts\Shift;
use Illuminate\Database\Eloquent\Factories\Factory;
@@ -17,11 +17,12 @@ class NeededAngelTypeFactory extends Factory
public function definition(): array
{
- $forRoom = $this->faker->boolean();
+ $type = $this->faker->numberBetween(0, 2);
return [
- 'room_id' => $forRoom ? Room::factory() : null,
- 'shift_id' => $forRoom ? null : Shift::factory(),
+ 'location_id' => $type == 0 ? Location::factory() : null,
+ 'shift_id' => $type == 1 ? null : Shift::factory(),
+ 'shift_type_id' => $type == 2 ? null : Shift::factory(),
'angel_type_id' => AngelType::factory(),
'count' => $this->faker->numberBetween(1, 5),
];
diff --git a/db/factories/Shifts/ScheduleFactory.php b/db/factories/Shifts/ScheduleFactory.php
index 42a323af1..350d0be36 100644
--- a/db/factories/Shifts/ScheduleFactory.php
+++ b/db/factories/Shifts/ScheduleFactory.php
@@ -18,6 +18,7 @@ public function definition(): array
'name' => $this->faker->unique()->words(4, true),
'url' => $this->faker->parse('https://{{safeEmailDomain}}/{{slug}}.xml'),
'shift_type' => $this->faker->numberBetween(1, 5),
+ 'needed_from_shift_type' => $this->faker->boolean(.2),
'minutes_before' => 15,
'minutes_after' => 15,
];
diff --git a/db/factories/Shifts/ShiftFactory.php b/db/factories/Shifts/ShiftFactory.php
index 6bf2f7966..8364ce731 100644
--- a/db/factories/Shifts/ShiftFactory.php
+++ b/db/factories/Shifts/ShiftFactory.php
@@ -4,7 +4,7 @@
namespace Database\Factories\Engelsystem\Models\Shifts;
-use Engelsystem\Models\Room;
+use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftType;
use Engelsystem\Models\User\User;
@@ -25,7 +25,7 @@ public function definition(): array
'start' => $start,
'end' => $this->faker->dateTimeInInterval($start, '+3 hours'),
'shift_type_id' => ShiftType::factory(),
- 'room_id' => Room::factory(),
+ 'location_id' => Location::factory(),
'transaction_id' => $this->faker->optional()->uuid(),
'created_by' => User::factory(),
'updated_by' => $this->faker->optional(.3)->boolean() ? User::factory() : null,
diff --git a/db/factories/User/ContactFactory.php b/db/factories/User/ContactFactory.php
index dc26e60d8..360a9279e 100644
--- a/db/factories/User/ContactFactory.php
+++ b/db/factories/User/ContactFactory.php
@@ -5,6 +5,7 @@
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Contact;
+use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ContactFactory extends Factory
@@ -15,6 +16,7 @@ class ContactFactory extends Factory
public function definition(): array
{
return [
+ 'user_id' => User::factory(),
'dect' => $this->faker->optional()->numberBetween(1000, 9999),
'email' => $this->faker->unique()->optional()->safeEmail(),
'mobile' => $this->faker->optional(.2)->phoneNumber(),
diff --git a/db/factories/User/LicenseFactory.php b/db/factories/User/LicenseFactory.php
index 4c9ccecf4..5240c9712 100644
--- a/db/factories/User/LicenseFactory.php
+++ b/db/factories/User/LicenseFactory.php
@@ -5,6 +5,7 @@
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\License;
+use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class LicenseFactory extends Factory
@@ -21,13 +22,19 @@ public function definition(): array
$drive_forklift = ($drive_car && $this->faker->boolean(.1))
|| ($drive_12t && $this->faker->boolean(.7));
+ $ifsg_certificate = $this->faker->boolean(0.1);
+ $ifsg_certificate_light = $this->faker->boolean(0.5) && !$ifsg_certificate;
+
return [
- 'has_car' => $drive_car && $this->faker->boolean(.7),
- 'drive_forklift' => $drive_forklift,
- 'drive_car' => $drive_car,
- 'drive_3_5t' => $drive_3_5t,
- 'drive_7_5t' => $drive_7_5t,
- 'drive_12t' => $drive_12t,
+ 'user_id' => User::factory(),
+ 'has_car' => $drive_car && $this->faker->boolean(.7),
+ 'drive_forklift' => $drive_forklift,
+ 'drive_car' => $drive_car,
+ 'drive_3_5t' => $drive_3_5t,
+ 'drive_7_5t' => $drive_7_5t,
+ 'drive_12t' => $drive_12t,
+ 'ifsg_certificate' => $ifsg_certificate,
+ 'ifsg_certificate_light' => $ifsg_certificate_light,
];
}
}
diff --git a/db/factories/User/PasswordResetFactory.php b/db/factories/User/PasswordResetFactory.php
index 69209a270..c0169568e 100644
--- a/db/factories/User/PasswordResetFactory.php
+++ b/db/factories/User/PasswordResetFactory.php
@@ -5,6 +5,7 @@
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\PasswordReset;
+use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PasswordResetFactory extends Factory
@@ -15,6 +16,7 @@ class PasswordResetFactory extends Factory
public function definition(): array
{
return [
+ 'user_id' => User::factory(),
'token' => bin2hex(random_bytes(16)),
];
}
diff --git a/db/factories/User/PersonalDataFactory.php b/db/factories/User/PersonalDataFactory.php
index e69c7e44a..e47ee9fd2 100644
--- a/db/factories/User/PersonalDataFactory.php
+++ b/db/factories/User/PersonalDataFactory.php
@@ -6,6 +6,7 @@
use Carbon\Carbon;
use Engelsystem\Models\User\PersonalData;
+use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PersonalDataFactory extends Factory
@@ -19,6 +20,7 @@ public function definition(): array
$departure = $this->faker->optional()->dateTimeThisMonth('2 weeks');
return [
+ 'user_id' => User::factory(),
'first_name' => $this->faker->optional(.7)->firstName(),
'last_name' => $this->faker->optional()->lastName(),
'pronoun' => $this->faker->optional(.3)->pronoun(),
diff --git a/db/factories/User/SettingsFactory.php b/db/factories/User/SettingsFactory.php
index f399ed319..b5fb7f4f0 100644
--- a/db/factories/User/SettingsFactory.php
+++ b/db/factories/User/SettingsFactory.php
@@ -5,6 +5,7 @@
namespace Database\Factories\Engelsystem\Models\User;
use Engelsystem\Models\User\Settings;
+use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class SettingsFactory extends Factory
@@ -15,6 +16,7 @@ class SettingsFactory extends Factory
public function definition(): array
{
return [
+ 'user_id' => User::factory(),
'language' => $this->faker->locale(),
'theme' => $this->faker->numberBetween(1, 20),
'email_human' => $this->faker->boolean(),
diff --git a/db/factories/User/StateFactory.php b/db/factories/User/StateFactory.php
index 4f9a04e6d..277807779 100644
--- a/db/factories/User/StateFactory.php
+++ b/db/factories/User/StateFactory.php
@@ -6,6 +6,7 @@
use Carbon\Carbon;
use Engelsystem\Models\User\State;
+use Engelsystem\Models\User\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class StateFactory extends Factory
@@ -18,8 +19,10 @@ public function definition(): array
$arrival = $this->faker->optional()->dateTimeThisMonth();
return [
+ 'user_id' => User::factory(),
'arrived' => (bool) $arrival,
'arrival_date' => $arrival ? Carbon::instance($arrival) : null,
+ 'user_info' => $this->faker->optional(.1)->text(),
'active' => $this->faker->boolean(.3),
'force_active' => $this->faker->boolean(.1),
'got_shirt' => $this->faker->boolean(),
diff --git a/db/factories/User/UserFactory.php b/db/factories/User/UserFactory.php
index ce37e7023..545931fca 100644
--- a/db/factories/User/UserFactory.php
+++ b/db/factories/User/UserFactory.php
@@ -19,6 +19,7 @@ public function definition(): array
'password' => crypt(random_bytes(16), '$1$salt$'),
'email' => $this->faker->unique()->safeEmail(),
'api_key' => bin2hex(random_bytes(32)),
+ 'updated_at' => $this->faker->dateTimeInInterval('-3 months', 'now'),
];
}
}
diff --git a/db/install.sql b/db/install.sql
deleted file mode 100644
index e1c9d5798..000000000
--- a/db/install.sql
+++ /dev/null
@@ -1,802 +0,0 @@
--- phpMyAdmin SQL Dump
--- version 4.5.2
--- http://www.phpmyadmin.net
---
--- Host: localhost
--- Erstellungszeit: 27. Sep 2016 um 17:48
--- Server-Version: 10.1.10-MariaDB
--- PHP-Version: 7.0.4
-
-SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
-SET time_zone = "+00:00";
-
---
--- Datenbank: `engelsystem`
---
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `AngelTypes`
---
-
-DROP TABLE IF EXISTS `AngelTypes`;
-CREATE TABLE `AngelTypes` (
- `id` int(11) NOT NULL,
- `name` varchar(50) NOT NULL DEFAULT '',
- `restricted` int(1) NOT NULL,
- `description` text NOT NULL,
- `requires_driver_license` tinyint(1) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `EventConfig`
---
-
-DROP TABLE IF EXISTS `EventConfig`;
-CREATE TABLE `EventConfig` (
- `event_name` varchar(255) DEFAULT NULL,
- `buildup_start_date` int(11) DEFAULT NULL,
- `event_start_date` int(11) DEFAULT NULL,
- `event_end_date` int(11) DEFAULT NULL,
- `teardown_end_date` int(11) DEFAULT NULL,
- `event_welcome_msg` varchar(255) DEFAULT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `GroupPrivileges`
---
-
-DROP TABLE IF EXISTS `GroupPrivileges`;
-CREATE TABLE `GroupPrivileges` (
- `id` int(11) NOT NULL,
- `group_id` int(11) NOT NULL,
- `privilege_id` int(11) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `GroupPrivileges`
---
-
-INSERT INTO `GroupPrivileges` (`id`, `group_id`, `privilege_id`) VALUES
-(85, -7, 10),
-(87, -7, 18),
-(86, -7, 21),
-(216, -6, 5),
-(212, -6, 6),
-(207, -6, 7),
-(211, -6, 12),
-(208, -6, 13),
-(210, -6, 14),
-(214, -6, 16),
-(209, -6, 21),
-(213, -6, 28),
-(206, -6, 31),
-(215, -6, 33),
-(257, -6, 38),
-(219, -5, 14),
-(221, -5, 25),
-(220, -5, 33),
-(241, -4, 5),
-(238, -4, 14),
-(240, -4, 16),
-(237, -4, 19),
-(242, -4, 25),
-(235, -4, 27),
-(239, -4, 28),
-(236, -4, 32),
-(218, -4, 39),
-(258, -3, 31),
-(247, -2, 3),
-(246, -2, 4),
-(255, -2, 8),
-(252, -2, 9),
-(254, -2, 11),
-(248, -2, 15),
-(251, -2, 17),
-(256, -2, 24),
-(253, -2, 26),
-(245, -2, 30),
-(244, -2, 34),
-(249, -2, 35),
-(243, -2, 36),
-(250, -2, 37),
-(88, -1, 1),
-(23, -1, 2),
-(24, -1, 5);
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `Groups`
---
-
-DROP TABLE IF EXISTS `Groups`;
-CREATE TABLE `Groups` (
- `Name` varchar(35) NOT NULL,
- `UID` int(11) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `Groups`
---
-
-INSERT INTO `Groups` (`Name`, `UID`) VALUES
-('6-Developer', -7),
-('5-BΓΌrokrat', -6),
-('4-Team Coordinator', -5),
-('3-Shift Coordinator', -4),
-('Shirt-Manager', -3),
-('2-Engel', -2),
-('1-Gast', -1);
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `LogEntries`
---
-
-DROP TABLE IF EXISTS `LogEntries`;
-CREATE TABLE `LogEntries` (
- `id` int(11) NOT NULL,
- `timestamp` int(11) NOT NULL,
- `nick` text NOT NULL,
- `message` text NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `Messages`
---
-
-DROP TABLE IF EXISTS `Messages`;
-CREATE TABLE `Messages` (
- `id` int(11) NOT NULL,
- `Datum` int(11) NOT NULL,
- `SUID` int(11) NOT NULL DEFAULT '0',
- `RUID` int(11) NOT NULL DEFAULT '0',
- `isRead` char(1) NOT NULL DEFAULT 'N',
- `Text` text NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Fuers interen Communikationssystem';
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `NeededAngelTypes`
---
-
-DROP TABLE IF EXISTS `NeededAngelTypes`;
-CREATE TABLE `NeededAngelTypes` (
- `id` int(11) NOT NULL,
- `room_id` int(11) DEFAULT NULL,
- `shift_id` int(11) DEFAULT NULL,
- `angel_type_id` int(11) NOT NULL,
- `count` int(11) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `News`
---
-
-DROP TABLE IF EXISTS `News`;
-CREATE TABLE `News` (
- `ID` int(11) NOT NULL,
- `Datum` int(11) NOT NULL,
- `Betreff` varchar(150) NOT NULL DEFAULT '',
- `Text` text NOT NULL,
- `UID` int(11) NOT NULL DEFAULT '0',
- `Treffen` tinyint(4) NOT NULL DEFAULT '0'
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `NewsComments`
---
-
-DROP TABLE IF EXISTS `NewsComments`;
-CREATE TABLE `NewsComments` (
- `ID` bigint(11) NOT NULL,
- `Refid` int(11) NOT NULL DEFAULT '0',
- `Datum` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
- `Text` text NOT NULL,
- `UID` int(11) NOT NULL DEFAULT '0'
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `Privileges`
---
-
-DROP TABLE IF EXISTS `Privileges`;
-CREATE TABLE `Privileges` (
- `id` int(11) NOT NULL,
- `name` varchar(128) NOT NULL,
- `desc` varchar(1024) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `Privileges`
---
-
-INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES
-(1, 'start', 'Startseite fΓΌr GΓ€ste/Nicht eingeloggte User'),
-(2, 'login', 'Logindialog'),
-(3, 'news', 'Anzeigen der News-Seite'),
-(4, 'logout', 'User darf sich ausloggen'),
-(5, 'register', 'Einen neuen Engel registerieren'),
-(6, 'admin_rooms', 'RΓ€ume administrieren'),
-(7, 'admin_angel_types', 'Engel Typen administrieren'),
-(8, 'user_settings', 'User profile settings'),
-(9, 'user_messages', 'Writing and reading messages from user to user'),
-(10, 'admin_groups', 'Manage usergroups and their rights'),
-(11, 'user_questions', 'Let users ask questions'),
-(12, 'admin_questions', 'Answer user''s questions'),
-(13, 'admin_faq', 'Edit FAQs'),
-(14, 'admin_news', 'Administrate the news section'),
-(15, 'news_comments', 'User can comment news'),
-(16, 'admin_user', 'Administrate the angels'),
-(17, 'user_meetings', 'Lists meetings (news)'),
-(18, 'admin_language', 'Translate the system'),
-(19, 'admin_log', 'Display recent changes'),
-(20, 'user_wakeup', 'User wakeup-service organization'),
-(21, 'admin_import', 'Import rooms and shifts from pentabarf'),
-(22, 'credits', 'View credits'),
-(23, 'faq', 'View FAQ'),
-(24, 'user_shifts', 'Signup for shifts'),
-(25, 'user_shifts_admin', 'Signup other angels for shifts.'),
-(26, 'user_myshifts', 'Allow angels to view their own shifts and cancel them.'),
-(27, 'admin_arrive', 'Mark angels when they arrive.'),
-(28, 'admin_shifts', 'Create shifts'),
-(30, 'ical', 'iCal shift export'),
-(31, 'admin_active', 'Mark angels as active and if they got a t-shirt.'),
-(32, 'admin_free', 'Show a list of free/unemployed angels.'),
-(33, 'admin_user_angeltypes', 'Confirm restricted angel types'),
-(34, 'atom', ' Atom news export'),
-(35, 'shifts_json_export', 'Export shifts in JSON format'),
-(36, 'angeltypes', 'View angeltypes'),
-(37, 'user_angeltypes', 'Join angeltypes.'),
-(38, 'shifttypes', 'Administrate shift types'),
-(39, 'admin_event_config', 'Allow editing event config');
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `Questions`
---
-
-DROP TABLE IF EXISTS `Questions`;
-CREATE TABLE `Questions` (
- `QID` bigint(20) NOT NULL,
- `UID` int(11) NOT NULL DEFAULT '0',
- `Question` text NOT NULL,
- `AID` int(11) DEFAULT NULL,
- `Answer` text
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Fragen und Antworten';
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `Room`
---
-
-DROP TABLE IF EXISTS `Room`;
-CREATE TABLE `Room` (
- `RID` int(11) NOT NULL,
- `Name` varchar(35) NOT NULL DEFAULT '',
- `Man` text,
- `FromPentabarf` char(1) NOT NULL DEFAULT 'N',
- `show` char(1) NOT NULL DEFAULT 'Y',
- `Number` int(11) DEFAULT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `Room`
---
-
-INSERT INTO `Room` (`RID`, `Name`, `Man`, `FromPentabarf`, `show`, `Number`) VALUES
-(1, 'Testraum', NULL, '', 'Y', 0);
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `ShiftEntry`
---
-
-DROP TABLE IF EXISTS `ShiftEntry`;
-CREATE TABLE `ShiftEntry` (
- `id` int(11) NOT NULL,
- `SID` int(11) NOT NULL DEFAULT '0',
- `TID` int(11) NOT NULL DEFAULT '0',
- `UID` int(11) NOT NULL DEFAULT '0',
- `Comment` text,
- `freeload_comment` text,
- `freeloaded` tinyint(1) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `Shifts`
---
-
-DROP TABLE IF EXISTS `Shifts`;
-CREATE TABLE `Shifts` (
- `SID` int(11) NOT NULL,
- `title` text,
- `shifttype_id` int(11) NOT NULL,
- `start` int(11) NOT NULL,
- `end` int(11) NOT NULL,
- `RID` int(11) NOT NULL DEFAULT '0',
- `URL` text,
- `PSID` int(11) DEFAULT NULL,
- `created_by_user_id` int(11) DEFAULT NULL,
- `created_at_timestamp` int(11) NOT NULL,
- `edited_by_user_id` int(11) DEFAULT NULL,
- `edited_at_timestamp` int(11) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `ShiftTypes`
---
-
-DROP TABLE IF EXISTS `ShiftTypes`;
-CREATE TABLE `ShiftTypes` (
- `id` int(11) NOT NULL,
- `name` varchar(255) NOT NULL,
- `angeltype_id` int(11) DEFAULT NULL,
- `description` text NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `ShiftTypes`
---
-
-INSERT INTO `ShiftTypes` (`id`, `name`, `angeltype_id`, `description`) VALUES
-(4, 'Schichttyp1', NULL, '');
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `User`
---
-
-DROP TABLE IF EXISTS `User`;
-CREATE TABLE `User` (
- `UID` int(11) NOT NULL,
- `Nick` varchar(23) NOT NULL DEFAULT '',
- `Name` varchar(23) DEFAULT NULL,
- `Vorname` varchar(23) DEFAULT NULL,
- `Alter` int(4) DEFAULT NULL,
- `Telefon` varchar(40) DEFAULT NULL,
- `DECT` varchar(5) DEFAULT NULL,
- `Handy` varchar(40) DEFAULT NULL,
- `email` varchar(123) DEFAULT NULL,
- `email_shiftinfo` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'User wants to be informed by mail about changes in his shifts',
- `jabber` varchar(200) DEFAULT NULL,
- `Size` varchar(4) DEFAULT NULL,
- `Passwort` varchar(128) DEFAULT NULL,
- `password_recovery_token` varchar(32) DEFAULT NULL,
- `Gekommen` tinyint(4) NOT NULL DEFAULT '0',
- `Aktiv` tinyint(4) NOT NULL DEFAULT '0',
- `force_active` tinyint(1) NOT NULL,
- `Tshirt` tinyint(4) DEFAULT '0',
- `color` tinyint(4) DEFAULT '10',
- `Sprache` char(64) NOT NULL,
- `Menu` char(1) NOT NULL DEFAULT 'L',
- `lastLogIn` int(11) NOT NULL,
- `CreateDate` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
- `Art` varchar(30) DEFAULT NULL,
- `kommentar` text,
- `Hometown` varchar(255) NOT NULL DEFAULT '',
- `api_key` varchar(32) NOT NULL,
- `got_voucher` int(11) NOT NULL,
- `arrival_date` int(11) DEFAULT NULL,
- `planned_arrival_date` int(11) NOT NULL,
- `planned_departure_date` int(11) DEFAULT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `User`
---
-
-INSERT INTO `User` (`UID`, `Nick`, `Name`, `Vorname`, `Alter`, `Telefon`, `DECT`, `Handy`, `email`, `email_shiftinfo`, `jabber`, `Size`, `Passwort`, `password_recovery_token`, `Gekommen`, `Aktiv`, `force_active`, `Tshirt`, `color`, `Sprache`, `Menu`, `lastLogIn`, `CreateDate`, `Art`, `kommentar`, `Hometown`, `api_key`, `got_voucher`, `arrival_date`, `planned_arrival_date`, `planned_departure_date`) VALUES
-(1, 'admin', 'Gates', 'Bill', 42, '', '-', '', 'admin@example.com', 1, '', 'XL', '$6$rounds=5000$hjXbIhoRTH3vKiRa$Wl2P2iI5T9iRR.HHu/YFHswBW0WVn0yxCfCiX0Keco9OdIoDK6bIAADswP6KvMCJSwTGdV8PgA8g8Xfw5l8BD1', NULL, 1, 1, 0, 1, 0, 'de_DE.UTF-8', 'L', 1474990948, '0001-01-01 00:00:00', '', '', '', '038850abdd1feb264406be3ffa746235', 0, 1439490478, 1436964455, 1440161255);
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `UserAngelTypes`
---
-
-DROP TABLE IF EXISTS `UserAngelTypes`;
-CREATE TABLE `UserAngelTypes` (
- `id` int(11) NOT NULL,
- `user_id` int(11) NOT NULL,
- `angeltype_id` int(11) NOT NULL,
- `confirm_user_id` int(11) DEFAULT NULL,
- `coordinator` tinyint(1) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `UserDriverLicenses`
---
-
-DROP TABLE IF EXISTS `UserDriverLicenses`;
-CREATE TABLE `UserDriverLicenses` (
- `user_id` int(11) NOT NULL,
- `has_car` tinyint(1) NOT NULL,
- `has_license_car` tinyint(1) NOT NULL,
- `has_license_3_5t_transporter` tinyint(1) NOT NULL,
- `has_license_7_5t_truck` tinyint(1) NOT NULL,
- `has_license_12_5t_truck` tinyint(1) NOT NULL,
- `has_license_forklift` tinyint(1) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `UserDriverLicenses`
---
-
-INSERT INTO `UserDriverLicenses` (`user_id`, `has_car`, `has_license_car`, `has_license_3_5t_transporter`, `has_license_7_5t_truck`, `has_license_12_5t_truck`, `has_license_forklift`) VALUES
-(1, 1, 1, 1, 1, 1, 1);
-
--- --------------------------------------------------------
-
---
--- Tabellenstruktur fΓΌr Tabelle `UserGroups`
---
-
-DROP TABLE IF EXISTS `UserGroups`;
-CREATE TABLE `UserGroups` (
- `id` int(11) NOT NULL,
- `uid` int(11) NOT NULL,
- `group_id` int(11) NOT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- Daten fΓΌr Tabelle `UserGroups`
---
-
-INSERT INTO `UserGroups` (`id`, `uid`, `group_id`) VALUES
-(3, 1, -7),
-(4, 1, -6),
-(12, 1, -5),
-(2, 1, -4),
-(1, 1, -2);
-
---
--- Indizes der exportierten Tabellen
---
-
---
--- Indizes fΓΌr die Tabelle `AngelTypes`
---
-ALTER TABLE `AngelTypes`
- ADD PRIMARY KEY (`id`),
- ADD UNIQUE KEY `Name` (`name`);
-
---
--- Indizes fΓΌr die Tabelle `GroupPrivileges`
---
-ALTER TABLE `GroupPrivileges`
- ADD PRIMARY KEY (`id`),
- ADD KEY `group_id` (`group_id`,`privilege_id`),
- ADD KEY `privilege_id` (`privilege_id`);
-
---
--- Indizes fΓΌr die Tabelle `Groups`
---
-ALTER TABLE `Groups`
- ADD PRIMARY KEY (`UID`);
-
---
--- Indizes fΓΌr die Tabelle `LogEntries`
---
-ALTER TABLE `LogEntries`
- ADD PRIMARY KEY (`id`),
- ADD KEY `timestamp` (`timestamp`);
-
---
--- Indizes fΓΌr die Tabelle `Messages`
---
-ALTER TABLE `Messages`
- ADD PRIMARY KEY (`id`),
- ADD KEY `Datum` (`Datum`),
- ADD KEY `SUID` (`SUID`),
- ADD KEY `RUID` (`RUID`);
-
---
--- Indizes fΓΌr die Tabelle `NeededAngelTypes`
---
-ALTER TABLE `NeededAngelTypes`
- ADD PRIMARY KEY (`id`),
- ADD KEY `room_id` (`room_id`,`angel_type_id`),
- ADD KEY `shift_id` (`shift_id`),
- ADD KEY `angel_type_id` (`angel_type_id`);
-
---
--- Indizes fΓΌr die Tabelle `News`
---
-ALTER TABLE `News`
- ADD PRIMARY KEY (`ID`),
- ADD KEY `UID` (`UID`);
-
---
--- Indizes fΓΌr die Tabelle `NewsComments`
---
-ALTER TABLE `NewsComments`
- ADD PRIMARY KEY (`ID`),
- ADD KEY `Refid` (`Refid`),
- ADD KEY `UID` (`UID`);
-
---
--- Indizes fΓΌr die Tabelle `Privileges`
---
-ALTER TABLE `Privileges`
- ADD PRIMARY KEY (`id`),
- ADD UNIQUE KEY `name` (`name`);
-
---
--- Indizes fΓΌr die Tabelle `Questions`
---
-ALTER TABLE `Questions`
- ADD PRIMARY KEY (`QID`),
- ADD KEY `UID` (`UID`),
- ADD KEY `AID` (`AID`);
-
---
--- Indizes fΓΌr die Tabelle `Room`
---
-ALTER TABLE `Room`
- ADD PRIMARY KEY (`RID`),
- ADD UNIQUE KEY `Name` (`Name`);
-
---
--- Indizes fΓΌr die Tabelle `ShiftEntry`
---
-ALTER TABLE `ShiftEntry`
- ADD PRIMARY KEY (`id`),
- ADD KEY `TID` (`TID`),
- ADD KEY `UID` (`UID`),
- ADD KEY `SID` (`SID`,`TID`),
- ADD KEY `freeloaded` (`freeloaded`);
-
---
--- Indizes fΓΌr die Tabelle `Shifts`
---
-ALTER TABLE `Shifts`
- ADD PRIMARY KEY (`SID`),
- ADD UNIQUE KEY `PSID` (`PSID`),
- ADD KEY `RID` (`RID`),
- ADD KEY `shifttype_id` (`shifttype_id`),
- ADD KEY `created_by_user_id` (`created_by_user_id`),
- ADD KEY `edited_by_user_id` (`edited_by_user_id`);
-
---
--- Indizes fΓΌr die Tabelle `ShiftTypes`
---
-ALTER TABLE `ShiftTypes`
- ADD PRIMARY KEY (`id`),
- ADD KEY `angeltype_id` (`angeltype_id`);
-
---
--- Indizes fΓΌr die Tabelle `User`
---
-ALTER TABLE `User`
- ADD PRIMARY KEY (`UID`),
- ADD UNIQUE KEY `Nick` (`Nick`),
- ADD KEY `api_key` (`api_key`),
- ADD KEY `password_recovery_token` (`password_recovery_token`),
- ADD KEY `force_active` (`force_active`),
- ADD KEY `arrival_date` (`arrival_date`,`planned_arrival_date`),
- ADD KEY `planned_departure_date` (`planned_departure_date`);
-
---
--- Indizes fΓΌr die Tabelle `UserAngelTypes`
---
-ALTER TABLE `UserAngelTypes`
- ADD PRIMARY KEY (`id`),
- ADD KEY `user_id` (`user_id`,`angeltype_id`,`confirm_user_id`),
- ADD KEY `angeltype_id` (`angeltype_id`),
- ADD KEY `confirm_user_id` (`confirm_user_id`),
- ADD KEY `coordinator` (`coordinator`);
-
---
--- Indizes fΓΌr die Tabelle `UserDriverLicenses`
---
-ALTER TABLE `UserDriverLicenses`
- ADD PRIMARY KEY (`user_id`);
-
---
--- Indizes fΓΌr die Tabelle `UserGroups`
---
-ALTER TABLE `UserGroups`
- ADD PRIMARY KEY (`id`),
- ADD KEY `uid` (`uid`,`group_id`),
- ADD KEY `group_id` (`group_id`);
-
---
--- AUTO_INCREMENT fΓΌr exportierte Tabellen
---
-
---
--- AUTO_INCREMENT fΓΌr Tabelle `AngelTypes`
---
-ALTER TABLE `AngelTypes`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
---
--- AUTO_INCREMENT fΓΌr Tabelle `GroupPrivileges`
---
-ALTER TABLE `GroupPrivileges`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=259;
---
--- AUTO_INCREMENT fΓΌr Tabelle `LogEntries`
---
-ALTER TABLE `LogEntries`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
---
--- AUTO_INCREMENT fΓΌr Tabelle `Messages`
---
-ALTER TABLE `Messages`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
---
--- AUTO_INCREMENT fΓΌr Tabelle `NeededAngelTypes`
---
-ALTER TABLE `NeededAngelTypes`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
---
--- AUTO_INCREMENT fΓΌr Tabelle `News`
---
-ALTER TABLE `News`
- MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT;
---
--- AUTO_INCREMENT fΓΌr Tabelle `NewsComments`
---
-ALTER TABLE `NewsComments`
- MODIFY `ID` bigint(11) NOT NULL AUTO_INCREMENT;
---
--- AUTO_INCREMENT fΓΌr Tabelle `Privileges`
---
-ALTER TABLE `Privileges`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=40;
---
--- AUTO_INCREMENT fΓΌr Tabelle `Questions`
---
-ALTER TABLE `Questions`
- MODIFY `QID` bigint(20) NOT NULL AUTO_INCREMENT;
---
--- AUTO_INCREMENT fΓΌr Tabelle `Room`
---
-ALTER TABLE `Room`
- MODIFY `RID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
---
--- AUTO_INCREMENT fΓΌr Tabelle `ShiftEntry`
---
-ALTER TABLE `ShiftEntry`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
---
--- AUTO_INCREMENT fΓΌr Tabelle `Shifts`
---
-ALTER TABLE `Shifts`
- MODIFY `SID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
---
--- AUTO_INCREMENT fΓΌr Tabelle `ShiftTypes`
---
-ALTER TABLE `ShiftTypes`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
---
--- AUTO_INCREMENT fΓΌr Tabelle `User`
---
-ALTER TABLE `User`
- MODIFY `UID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
---
--- AUTO_INCREMENT fΓΌr Tabelle `UserAngelTypes`
---
-ALTER TABLE `UserAngelTypes`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
---
--- AUTO_INCREMENT fΓΌr Tabelle `UserGroups`
---
-ALTER TABLE `UserGroups`
- MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
---
--- Constraints der exportierten Tabellen
---
-
---
--- Constraints der Tabelle `GroupPrivileges`
---
-ALTER TABLE `GroupPrivileges`
- ADD CONSTRAINT `groupprivileges_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `Groups` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `groupprivileges_ibfk_2` FOREIGN KEY (`privilege_id`) REFERENCES `Privileges` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `Messages`
---
-ALTER TABLE `Messages`
- ADD CONSTRAINT `messages_ibfk_1` FOREIGN KEY (`SUID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `messages_ibfk_2` FOREIGN KEY (`RUID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `NeededAngelTypes`
---
-ALTER TABLE `NeededAngelTypes`
- ADD CONSTRAINT `neededangeltypes_ibfk_1` FOREIGN KEY (`room_id`) REFERENCES `Room` (`RID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `neededangeltypes_ibfk_2` FOREIGN KEY (`shift_id`) REFERENCES `Shifts` (`SID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `neededangeltypes_ibfk_3` FOREIGN KEY (`angel_type_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `News`
---
-ALTER TABLE `News`
- ADD CONSTRAINT `news_ibfk_1` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `NewsComments`
---
-ALTER TABLE `NewsComments`
- ADD CONSTRAINT `newscomments_ibfk_1` FOREIGN KEY (`Refid`) REFERENCES `News` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `newscomments_ibfk_2` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `Questions`
---
-ALTER TABLE `Questions`
- ADD CONSTRAINT `questions_ibfk_1` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `questions_ibfk_2` FOREIGN KEY (`AID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `ShiftEntry`
---
-ALTER TABLE `ShiftEntry`
- ADD CONSTRAINT `shiftentry_ibfk_1` FOREIGN KEY (`SID`) REFERENCES `Shifts` (`SID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `shiftentry_ibfk_2` FOREIGN KEY (`UID`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `shiftentry_ibfk_3` FOREIGN KEY (`TID`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `Shifts`
---
-ALTER TABLE `Shifts`
- ADD CONSTRAINT `shifts_ibfk_1` FOREIGN KEY (`RID`) REFERENCES `Room` (`RID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `shifts_ibfk_2` FOREIGN KEY (`shifttype_id`) REFERENCES `ShiftTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `shifts_ibfk_3` FOREIGN KEY (`created_by_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE,
- ADD CONSTRAINT `shifts_ibfk_4` FOREIGN KEY (`edited_by_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `ShiftTypes`
---
-ALTER TABLE `ShiftTypes`
- ADD CONSTRAINT `shifttypes_ibfk_1` FOREIGN KEY (`angeltype_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `UserAngelTypes`
---
-ALTER TABLE `UserAngelTypes`
- ADD CONSTRAINT `userangeltypes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `userangeltypes_ibfk_2` FOREIGN KEY (`angeltype_id`) REFERENCES `AngelTypes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `userangeltypes_ibfk_3` FOREIGN KEY (`confirm_user_id`) REFERENCES `User` (`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `UserDriverLicenses`
---
-ALTER TABLE `UserDriverLicenses`
- ADD CONSTRAINT `userdriverlicenses_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
-
---
--- Constraints der Tabelle `UserGroups`
---
-ALTER TABLE `UserGroups`
- ADD CONSTRAINT `usergroups_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `Groups` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE,
- ADD CONSTRAINT `usergroups_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `User` (`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/db/migrations/2018_01_01_000001_import_install_sql.php b/db/migrations/2018_01_01_000001_import_install_sql.php
index f13559e27..175706c14 100644
--- a/db/migrations/2018_01_01_000001_import_install_sql.php
+++ b/db/migrations/2018_01_01_000001_import_install_sql.php
@@ -29,24 +29,9 @@ class ImportInstallSql extends Migration
'UserAngelTypes',
'UserDriverLicenses',
'UserGroups',
+ 'UserWorkLog',
];
- /**
- * Run the migration
- */
- public function up(): void
- {
- foreach ($this->oldTables as $table) {
- if ($this->schema->hasTable($table)) {
- return;
- }
- }
-
- $sql = file_get_contents(__DIR__ . '/../install.sql');
- $this->schema->getConnection()->unprepared($sql);
- }
-
-
/**
* Reverse the migration
*/
@@ -54,6 +39,7 @@ public function down(): void
{
$this->schema->getConnection()->statement('SET FOREIGN_KEY_CHECKS=0;');
+ // Delete all remaining tables
foreach ($this->oldTables as $table) {
if ($this->schema->hasTable($table)) {
$this->schema->dropIfExists($table);
diff --git a/db/migrations/2018_01_01_000002_import_update_sql.php b/db/migrations/2018_01_01_000002_import_update_sql.php
index af311249c..44b6c8c28 100644
--- a/db/migrations/2018_01_01_000002_import_update_sql.php
+++ b/db/migrations/2018_01_01_000002_import_update_sql.php
@@ -8,24 +8,5 @@
class ImportUpdateSql extends Migration
{
- /**
- * Run the migration
- */
- public function up(): void
- {
- if ($this->schema->hasTable('UserWorkLog')) {
- return;
- }
-
- $sql = file_get_contents(__DIR__ . '/../update.sql');
- $this->schema->getConnection()->unprepared($sql);
- }
-
- /**
- * Reverse the migration
- */
- public function down(): void
- {
- $this->schema->dropIfExists('UserWorkLog');
- }
+ // Do nothing as the tables will be created by later migrations and deleted by ImportInstall
}
diff --git a/db/migrations/2020_09_02_000000_create_rooms_table.php b/db/migrations/2020_09_02_000000_create_rooms_table.php
index c527d096b..81b91f388 100644
--- a/db/migrations/2020_09_02_000000_create_rooms_table.php
+++ b/db/migrations/2020_09_02_000000_create_rooms_table.php
@@ -11,7 +11,6 @@
class CreateRoomsTable extends Migration
{
use ChangesReferences;
- use Reference;
/**
* Run the migration
diff --git a/db/migrations/2020_09_07_000000_create_worklogs_table.php b/db/migrations/2020_09_07_000000_create_worklogs_table.php
index 7a078e1e0..cc6e2f4e8 100644
--- a/db/migrations/2020_09_07_000000_create_worklogs_table.php
+++ b/db/migrations/2020_09_07_000000_create_worklogs_table.php
@@ -37,6 +37,7 @@ public function up(): void
->get();
foreach ($previousRecords as $previousRecord) {
+ $worked_at = Carbon::createFromTimestamp($previousRecord->work_timestamp);
$created_at = Carbon::createFromTimestamp($previousRecord->created_timestamp);
$this->schema->getConnection()
->table('worklogs')
@@ -44,7 +45,7 @@ public function up(): void
'id' => $previousRecord->id,
'user_id' => $previousRecord->user_id,
'creator_id' => $previousRecord->created_user_id,
- 'worked_at' => $previousRecord->work_timestamp,
+ 'worked_at' => $worked_at,
'hours' => $previousRecord->work_hours,
'comment' => $previousRecord->comment,
'created_at' => $created_at,
@@ -87,11 +88,11 @@ public function down(): void
->insert([
'id' => $record->id,
'user_id' => $record->user_id,
- 'work_timestamp' => $record->worked_at->timestamp,
+ 'work_timestamp' => Carbon::createFromFormat('Y-m-d', $record->worked_at)->timestamp,
'work_hours' => $record->hours,
'comment' => $record->comment,
'created_user_id' => $record->creator_id,
- 'created_timestamp' => $record->created_at->timestamp,
+ 'created_timestamp' => Carbon::createFromFormat('Y-m-d H:i:s', $record->created_at)->timestamp,
]);
}
diff --git a/db/migrations/2020_09_27_000000_add_timestamps_to_questions.php b/db/migrations/2020_09_27_000000_add_timestamps_to_questions.php
index c2a0abc1d..272c0c95f 100644
--- a/db/migrations/2020_09_27_000000_add_timestamps_to_questions.php
+++ b/db/migrations/2020_09_27_000000_add_timestamps_to_questions.php
@@ -10,8 +10,6 @@
class AddTimestampsToQuestions extends Migration
{
- use ChangesReferences;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2020_11_20_000000_add_name_minutes_and_timestamps_to_schedules.php b/db/migrations/2020_11_20_000000_add_name_minutes_and_timestamps_to_schedules.php
index 923457f0e..c9aab6498 100644
--- a/db/migrations/2020_11_20_000000_add_name_minutes_and_timestamps_to_schedules.php
+++ b/db/migrations/2020_11_20_000000_add_name_minutes_and_timestamps_to_schedules.php
@@ -21,7 +21,7 @@ public function up(): void
$this->schema->table('schedules', function (Blueprint $table): void {
$table->string('name')->default('')->after('id');
- $table->integer('shift_type')->default(0)->after('name');
+ $table->unsignedInteger('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();
@@ -36,7 +36,7 @@ public function up(): void
$this->schema->table('schedules', function (Blueprint $table): void {
$table->string('name')->default(null)->change();
- $table->integer('shift_type')->default(null)->change();
+ $table->unsignedInteger('shift_type')->default(null)->change();
$table->integer('minutes_before')->default(null)->change();
$table->integer('minutes_after')->default(null)->change();
});
diff --git a/db/migrations/2020_12_25_000000_add_email_news_to_users_settings.php b/db/migrations/2020_12_25_000000_add_email_news_to_users_settings.php
index d7e17b832..c32c32b10 100644
--- a/db/migrations/2020_12_25_000000_add_email_news_to_users_settings.php
+++ b/db/migrations/2020_12_25_000000_add_email_news_to_users_settings.php
@@ -9,8 +9,6 @@
class AddEmailNewsToUsersSettings extends Migration
{
- use Reference;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2020_12_25_000000_oauth_add_tokens.php b/db/migrations/2020_12_25_000000_oauth_add_tokens.php
index 1c02d8cd7..e8a0cba11 100644
--- a/db/migrations/2020_12_25_000000_oauth_add_tokens.php
+++ b/db/migrations/2020_12_25_000000_oauth_add_tokens.php
@@ -9,8 +9,6 @@
class OauthAddTokens extends Migration
{
- use Reference;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2020_12_26_000000_news_add_is_pinned.php b/db/migrations/2020_12_26_000000_news_add_is_pinned.php
index e60e5a5ea..68d6e9835 100644
--- a/db/migrations/2020_12_26_000000_news_add_is_pinned.php
+++ b/db/migrations/2020_12_26_000000_news_add_is_pinned.php
@@ -9,8 +9,6 @@
class NewsAddIsPinned extends Migration
{
- use Reference;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2020_12_28_000001_oauth_change_tokens_to_text.php b/db/migrations/2020_12_28_000001_oauth_change_tokens_to_text.php
index 685322c83..1db6eb400 100644
--- a/db/migrations/2020_12_28_000001_oauth_change_tokens_to_text.php
+++ b/db/migrations/2020_12_28_000001_oauth_change_tokens_to_text.php
@@ -9,8 +9,6 @@
class OauthChangeTokensToText extends Migration
{
- use Reference;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2021_05_23_000000_create_first_user.php b/db/migrations/2021_05_23_000000_create_first_user.php
new file mode 100644
index 000000000..d01473a1e
--- /dev/null
+++ b/db/migrations/2021_05_23_000000_create_first_user.php
@@ -0,0 +1,45 @@
+schema->getConnection();
+ if ($db->table('users')->count() > 0) {
+ return;
+ }
+
+ $db->table('users')->insert([
+ 'name' => 'admin',
+ 'email' => 'admin@localhost',
+ 'password' => password_hash('asdfasdf', PASSWORD_DEFAULT),
+ 'api_key' => bin2hex(random_bytes(16)),
+ 'created_at' => Carbon::now(),
+ ]);
+
+ /** @var stdClass $admin */
+ $admin = $db->table('users')->where('name', 'admin')->first();
+ foreach (['users_contact', 'users_personal_data', 'users_state'] as $table) {
+ $db->table($table)->insert(['user_id' => $admin->id]);
+ }
+ $db->table('users_settings')->insert(['user_id' => $admin->id, 'language' => 'en_US', 'theme' => 0]);
+ }
+}
diff --git a/db/migrations/2021_05_23_000000_set_admin_password.php b/db/migrations/2021_05_23_000000_set_admin_password.php
index a02bc5baf..7bbd421f0 100644
--- a/db/migrations/2021_05_23_000000_set_admin_password.php
+++ b/db/migrations/2021_05_23_000000_set_admin_password.php
@@ -6,14 +6,12 @@
use Engelsystem\Config\Config;
use Engelsystem\Database\Migration\Migration;
-use Engelsystem\Helpers\Authenticator;
use Illuminate\Database\Schema\Builder as SchemaBuilder;
+use stdClass;
class SetAdminPassword extends Migration
{
- use Reference;
-
- public function __construct(SchemaBuilder $schemaBuilder, protected Authenticator $auth, protected Config $config)
+ public function __construct(SchemaBuilder $schemaBuilder, protected Config $config)
{
parent::__construct($schemaBuilder);
}
@@ -23,12 +21,21 @@ public function __construct(SchemaBuilder $schemaBuilder, protected Authenticato
*/
public function up(): void
{
- $admin = $this->auth->authenticate('admin', 'asdfasdf');
+ $db = $this->schema->getConnection();
+ /** @var stdClass $admin */
+ $admin = $db->table('users')->where('name', 'admin')->first();
$setupPassword = $this->config->get('setup_admin_password');
- if (!$admin || !$setupPassword) {
+
+ if (
+ !$admin
+ || !password_verify('asdfasdf', $admin->password)
+ || !$setupPassword
+ ) {
return;
}
- $this->auth->setPassword($admin, $setupPassword);
+ $db->table('users')
+ ->where('id', $admin->id)
+ ->update(['password' => password_hash($setupPassword, PASSWORD_DEFAULT)]);
}
}
diff --git a/db/migrations/2021_10_12_000000_add_shifts_description.php b/db/migrations/2021_10_12_000000_add_shifts_description.php
index 47ad04dd2..b2de144ef 100644
--- a/db/migrations/2021_10_12_000000_add_shifts_description.php
+++ b/db/migrations/2021_10_12_000000_add_shifts_description.php
@@ -9,8 +9,6 @@
class AddShiftsDescription extends Migration
{
- use Reference;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2021_12_29_000000_users_settings_add_email_goody.php b/db/migrations/2021_12_29_000000_users_settings_add_email_goody.php
index 643bab03e..bfff55fa1 100644
--- a/db/migrations/2021_12_29_000000_users_settings_add_email_goody.php
+++ b/db/migrations/2021_12_29_000000_users_settings_add_email_goody.php
@@ -9,8 +9,6 @@
class UsersSettingsAddEmailGoody extends Migration
{
- use Reference;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2022_10_23_000001_fill_privileges_and_groups_related_tables.php b/db/migrations/2022_10_23_000001_fill_privileges_and_groups_related_tables.php
new file mode 100644
index 000000000..0453da923
--- /dev/null
+++ b/db/migrations/2022_10_23_000001_fill_privileges_and_groups_related_tables.php
@@ -0,0 +1,158 @@
+schema->getConnection();
+ if ($db->table('privileges')->count() > 0) {
+ return;
+ }
+
+ $db->table('groups')
+ ->insert([
+ ['id' => 10, 'name' => 'Guest'],
+ ['id' => 20, 'name' => 'Angel'],
+ ['id' => 30, 'name' => 'Welcome Angel'],
+ ['id' => 35, 'name' => 'Voucher Angel'],
+ ['id' => 50, 'name' => 'Shirt Manager'],
+ ['id' => 60, 'name' => 'Shift Coordinator'],
+ ['id' => 65, 'name' => 'Team Coordinator'],
+ ['id' => 80, 'name' => 'Bureaucrat'],
+ ['id' => 85, 'name' => 'News Admin'],
+ ['id' => 90, 'name' => 'Developer'],
+ ]);
+
+ $db->table('privileges')
+ ->insert([
+ ['id' => 1, 'name' => 'start', 'description' => 'Startseite fΓΌr GΓ€ste/Nicht eingeloggte User'],
+ ['id' => 2, 'name' => 'login', 'description' => 'Logindialog'],
+ ['id' => 3, 'name' => 'news', 'description' => 'Anzeigen der News-Seite'],
+ ['id' => 4, 'name' => 'logout', 'description' => 'User darf sich ausloggen'],
+ ['id' => 5, 'name' => 'register', 'description' => 'Einen neuen Engel registerieren'],
+ ['id' => 6, 'name' => 'admin_rooms', 'description' => 'RΓ€ume administrieren'],
+ ['id' => 7, 'name' => 'admin_angel_types', 'description' => 'Engel Typen administrieren'],
+ ['id' => 8, 'name' => 'user_settings', 'description' => 'User profile settings'],
+ ['id' => 9, 'name' => 'user_messages',
+ 'description' => 'Writing and reading messages from user to user'],
+ ['id' => 10, 'name' => 'admin_groups', 'description' => 'Manage usergroups and their rights'],
+ ['id' => 14, 'name' => 'admin_news', 'description' => 'Administrate the news section'],
+ ['id' => 15, 'name' => 'news_comments', 'description' => 'User can comment news'],
+ ['id' => 16, 'name' => 'admin_user', 'description' => 'Administrate the angels'],
+ ['id' => 17, 'name' => 'user_meetings', 'description' => 'Lists meetings (news)'],
+ ['id' => 18, 'name' => 'admin_language', 'description' => 'Translate the system'],
+ ['id' => 19, 'name' => 'admin_log', 'description' => 'Display recent changes'],
+ ['id' => 21, 'name' => 'schedule.import', 'description' => 'Import rooms and shifts from schedule.xml'],
+ ['id' => 24, 'name' => 'user_shifts', 'description' => 'Signup for shifts'],
+ ['id' => 25, 'name' => 'user_shifts_admin', 'description' => 'Signup other angels for shifts.'],
+ ['id' => 26, 'name' => 'user_myshifts',
+ 'description' => 'Allow angels to view their own shifts and cancel them.'],
+ ['id' => 27, 'name' => 'admin_arrive', 'description' => 'Mark angels when they arrive.'],
+ ['id' => 28, 'name' => 'admin_shifts', 'description' => 'Create shifts'],
+ ['id' => 30, 'name' => 'ical', 'description' => 'iCal shift export'],
+ ['id' => 31, 'name' => 'admin_active',
+ 'description' => 'Mark angels as active and if they got a t-shirt.'],
+ ['id' => 32, 'name' => 'admin_free', 'description' => 'Show a list of free/unemployed angels.'],
+ ['id' => 33, 'name' => 'admin_user_angeltypes', 'description' => 'Confirm restricted angel types'],
+ ['id' => 34, 'name' => 'atom', 'description' => ' Atom news export'],
+ ['id' => 35, 'name' => 'shifts_json_export', 'description' => 'Export shifts in JSON format'],
+ ['id' => 36, 'name' => 'angeltypes', 'description' => 'View angeltypes'],
+ ['id' => 37, 'name' => 'user_angeltypes', 'description' => 'Join angeltypes.'],
+ ['id' => 38, 'name' => 'shifttypes', 'description' => 'Administrate shift types'],
+ ['id' => 39, 'name' => 'admin_event_config', 'description' => 'Allow editing event config'],
+ ['id' => 40, 'name' => 'view_rooms', 'description' => 'User can view rooms'],
+ ['id' => 41, 'name' => 'shiftentry_edit_angeltype_supporter',
+ 'description' => 'If user with this privilege is angeltype supporter, '
+ . 'he can put users in shifts for their angeltype'],
+ ['id' => 43, 'name' => 'admin_user_worklog', 'description' => 'Manage user work log entries.'],
+ ['id' => 44, 'name' => 'faq.view', 'description' => 'View FAQ entries'],
+ ['id' => 45, 'name' => 'faq.edit', 'description' => 'Edit FAQ entries'],
+ ['id' => 46, 'name' => 'question.add', 'description' => 'Ask questions'],
+ ['id' => 47, 'name' => 'question.edit', 'description' => 'Answer questions'],
+ ['id' => 48, 'name' => 'user.edit.shirt', 'description' => 'Edit user shirts'],
+ ['id' => 49, 'name' => 'voucher.edit', 'description' => 'Edit vouchers'],
+ ]);
+
+ $db->table('group_privileges')->insert([
+ ['id' => 23, 'group_id' => 10, 'privilege_id' => 2],
+ ['id' => 24, 'group_id' => 10, 'privilege_id' => 5],
+ ['id' => 85, 'group_id' => 90, 'privilege_id' => 10],
+ ['id' => 86, 'group_id' => 90, 'privilege_id' => 21],
+ ['id' => 87, 'group_id' => 90, 'privilege_id' => 18],
+ ['id' => 88, 'group_id' => 10, 'privilege_id' => 1],
+ ['id' => 206, 'group_id' => 80, 'privilege_id' => 31],
+ ['id' => 207, 'group_id' => 80, 'privilege_id' => 7],
+ ['id' => 209, 'group_id' => 80, 'privilege_id' => 21],
+ ['id' => 210, 'group_id' => 80, 'privilege_id' => 14],
+ ['id' => 212, 'group_id' => 80, 'privilege_id' => 6],
+ ['id' => 213, 'group_id' => 80, 'privilege_id' => 28],
+ ['id' => 214, 'group_id' => 80, 'privilege_id' => 16],
+ ['id' => 215, 'group_id' => 80, 'privilege_id' => 33],
+ ['id' => 216, 'group_id' => 80, 'privilege_id' => 5],
+ ['id' => 218, 'group_id' => 60, 'privilege_id' => 39],
+ ['id' => 219, 'group_id' => 65, 'privilege_id' => 14],
+ ['id' => 220, 'group_id' => 65, 'privilege_id' => 33],
+ ['id' => 221, 'group_id' => 65, 'privilege_id' => 25],
+ ['id' => 235, 'group_id' => 60, 'privilege_id' => 27],
+ ['id' => 236, 'group_id' => 60, 'privilege_id' => 32],
+ ['id' => 237, 'group_id' => 60, 'privilege_id' => 19],
+ ['id' => 238, 'group_id' => 60, 'privilege_id' => 14],
+ ['id' => 239, 'group_id' => 60, 'privilege_id' => 28],
+ ['id' => 240, 'group_id' => 60, 'privilege_id' => 16],
+ ['id' => 241, 'group_id' => 60, 'privilege_id' => 5],
+ ['id' => 242, 'group_id' => 60, 'privilege_id' => 25],
+ ['id' => 243, 'group_id' => 20, 'privilege_id' => 36],
+ ['id' => 244, 'group_id' => 20, 'privilege_id' => 34],
+ ['id' => 245, 'group_id' => 20, 'privilege_id' => 30],
+ ['id' => 246, 'group_id' => 20, 'privilege_id' => 4],
+ ['id' => 247, 'group_id' => 20, 'privilege_id' => 3],
+ ['id' => 248, 'group_id' => 20, 'privilege_id' => 15],
+ ['id' => 249, 'group_id' => 20, 'privilege_id' => 35],
+ ['id' => 250, 'group_id' => 20, 'privilege_id' => 37],
+ ['id' => 251, 'group_id' => 20, 'privilege_id' => 17],
+ ['id' => 252, 'group_id' => 20, 'privilege_id' => 9],
+ ['id' => 253, 'group_id' => 20, 'privilege_id' => 26],
+ ['id' => 255, 'group_id' => 20, 'privilege_id' => 8],
+ ['id' => 256, 'group_id' => 20, 'privilege_id' => 24],
+ ['id' => 257, 'group_id' => 80, 'privilege_id' => 38],
+ ['id' => 258, 'group_id' => 50, 'privilege_id' => 31],
+ ['id' => 259, 'group_id' => 20, 'privilege_id' => 40],
+ ['id' => 260, 'group_id' => 85, 'privilege_id' => 14],
+ ['id' => 262, 'group_id' => 60, 'privilege_id' => 43],
+ ['id' => 263, 'group_id' => 20, 'privilege_id' => 41],
+ ['id' => 264, 'group_id' => 30, 'privilege_id' => 27],
+ ['id' => 265, 'group_id' => 10, 'privilege_id' => 44],
+ ['id' => 266, 'group_id' => 20, 'privilege_id' => 44],
+ ['id' => 267, 'group_id' => 60, 'privilege_id' => 45],
+ ['id' => 268, 'group_id' => 20, 'privilege_id' => 46],
+ ['id' => 269, 'group_id' => 60, 'privilege_id' => 47],
+ ['id' => 270, 'group_id' => 60, 'privilege_id' => 48],
+ ['id' => 271, 'group_id' => 50, 'privilege_id' => 48],
+ ['id' => 272, 'group_id' => 50, 'privilege_id' => 27],
+ ['id' => 273, 'group_id' => 60, 'privilege_id' => 49],
+ ['id' => 274, 'group_id' => 35, 'privilege_id' => 49],
+ ['id' => 275, 'group_id' => 35, 'privilege_id' => 27],
+ ]);
+
+ /** @var stdClass $admin */
+ $admin = $db->table('users')->where('name', 'admin')->first();
+ if (!$admin) {
+ return;
+ }
+
+ // Angel, ShiCo, Team coordinator, Bureaucrat, Dev
+ foreach ([20, 60, 65, 80, 90] as $group) {
+ $db->table('users_groups')->insert(['user_id' => $admin->id, 'group_id' => $group]);
+ }
+ }
+}
diff --git a/db/migrations/2022_12_06_000000_change_api_key_length.php b/db/migrations/2022_12_06_000000_change_api_key_length.php
index d5e811ded..f51bcb742 100644
--- a/db/migrations/2022_12_06_000000_change_api_key_length.php
+++ b/db/migrations/2022_12_06_000000_change_api_key_length.php
@@ -6,6 +6,7 @@
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Str;
class ChangeApiKeyLength extends Migration
{
@@ -24,6 +25,19 @@ public function up(): void
*/
public function down(): void
{
+ $connection = $this->schema->getConnection();
+ $data = $connection->table('users')->get(['id', 'api_key']);
+ foreach ($data as $user) {
+ if (Str::length($user->api_key) <= 32) {
+ continue;
+ }
+
+ $key = Str::substr($user->api_key, 0, 32);
+ $connection->table('users')
+ ->where('id', $user->id)
+ ->update(['api_key' => $key]);
+ }
+
$this->schema->table('users', function (Blueprint $table): void {
$table->string('api_key', 32)->change();
});
diff --git a/db/migrations/2023_02_25_000000_fix_email_messages_migration_name.php b/db/migrations/2023_02_25_000000_fix_email_messages_migration_name.php
new file mode 100644
index 000000000..4acfb4e1c
--- /dev/null
+++ b/db/migrations/2023_02_25_000000_fix_email_messages_migration_name.php
@@ -0,0 +1,25 @@
+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
+}
diff --git a/db/migrations/2023_02_26_000000_AddEmailMessagesToUsersSettings.php b/db/migrations/2023_02_26_000000_add_email_messages_to_users_settings.php
similarity index 97%
rename from db/migrations/2023_02_26_000000_AddEmailMessagesToUsersSettings.php
rename to db/migrations/2023_02_26_000000_add_email_messages_to_users_settings.php
index 12a7450b6..52f72def1 100644
--- a/db/migrations/2023_02_26_000000_AddEmailMessagesToUsersSettings.php
+++ b/db/migrations/2023_02_26_000000_add_email_messages_to_users_settings.php
@@ -9,8 +9,6 @@
class AddEmailMessagesToUsersSettings extends Migration
{
- use Reference;
-
/**
* Run the migration
*/
diff --git a/db/migrations/2023_05_21_000000_create_api_permissions.php b/db/migrations/2023_05_21_000000_create_api_permissions.php
new file mode 100644
index 000000000..8c9b87021
--- /dev/null
+++ b/db/migrations/2023_05_21_000000_create_api_permissions.php
@@ -0,0 +1,45 @@
+schema->getConnection();
+ $db->table('privileges')->insert([
+ ['name' => 'api', 'description' => 'Use the API'],
+ ]);
+ $db->table('groups')->insert([
+ ['id' => 40, 'name' => 'API'],
+ ]);
+
+ $bureaucratGroup = 80;
+ $apiId = $db->table('privileges')->where('name', 'api')->first()->id;
+ $db->table('group_privileges')->insert([
+ ['group_id' => $bureaucratGroup, 'privilege_id' => $apiId],
+ ['group_id' => 40, 'privilege_id' => $apiId],
+ ]);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $db = $this->schema->getConnection();
+ $db->table('privileges')
+ ->where('name', 'api')
+ ->delete();
+ $db->table('groups')
+ ->where('id', 40)
+ ->delete();
+ }
+}
diff --git a/db/migrations/2023_05_21_000001_cleanup_short_api_keys.php b/db/migrations/2023_05_21_000001_cleanup_short_api_keys.php
new file mode 100644
index 000000000..7f666eefc
--- /dev/null
+++ b/db/migrations/2023_05_21_000001_cleanup_short_api_keys.php
@@ -0,0 +1,28 @@
+schema->getConnection();
+ foreach ($db->table('users')->get() as $user) {
+ if (Str::length($user->api_key) > 42) {
+ continue;
+ }
+
+ $db->table('users')
+ ->where('id', $user->id)
+ ->update(['api_key' => bin2hex(random_bytes(32))]);
+ }
+ }
+}
diff --git a/db/migrations/2023_08_07_000000_add_ifsg_cerificates_to_users_licenses.php b/db/migrations/2023_08_07_000000_add_ifsg_cerificates_to_users_licenses.php
new file mode 100644
index 000000000..461404d79
--- /dev/null
+++ b/db/migrations/2023_08_07_000000_add_ifsg_cerificates_to_users_licenses.php
@@ -0,0 +1,33 @@
+schema->table('users_licenses', function (Blueprint $table): void {
+ $table->boolean('ifsg_certificate_light')->default(false)->after('drive_12t');
+ $table->boolean('ifsg_certificate')->default(false)->after('ifsg_certificate_light');
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('users_licenses', function (Blueprint $table): void {
+ $table->dropColumn('ifsg_certificate_light');
+ $table->dropColumn('ifsg_certificate');
+ });
+ }
+}
diff --git a/db/migrations/2023_08_08_000000_add_requires_ifsg_cerificate_to_angeltypes.php b/db/migrations/2023_08_08_000000_add_requires_ifsg_cerificate_to_angeltypes.php
new file mode 100644
index 000000000..3e09ad394
--- /dev/null
+++ b/db/migrations/2023_08_08_000000_add_requires_ifsg_cerificate_to_angeltypes.php
@@ -0,0 +1,31 @@
+schema->table('angel_types', function (Blueprint $table): void {
+ $table->boolean('requires_ifsg_certificate')->default(false)->after('requires_driver_license');
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('angel_types', function (Blueprint $table): void {
+ $table->dropColumn('requires_ifsg_certificate');
+ });
+ }
+}
diff --git a/db/migrations/2023_08_26_000000_angeltypes_rename_no_self_signup_to_shift_self_signup.php b/db/migrations/2023_08_26_000000_angeltypes_rename_no_self_signup_to_shift_self_signup.php
new file mode 100644
index 000000000..c4078ec2d
--- /dev/null
+++ b/db/migrations/2023_08_26_000000_angeltypes_rename_no_self_signup_to_shift_self_signup.php
@@ -0,0 +1,39 @@
+schema->table('angel_types', function (Blueprint $table): void {
+ $table->renameColumn('no_self_signup', 'shift_self_signup')->default(true);
+ $connection = $this->schema->getConnection();
+ $connection->table('angel_types')
+ ->update(['no_self_signup' => $connection->raw('NOT no_self_signup'),
+ ]);
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('angel_types', function (Blueprint $table): void {
+ $table->renameColumn('shift_self_signup', 'no_self_signup');
+ $connection = $this->schema->getConnection();
+ $connection->table('angel_types')
+ ->update(['shift_self_signup' => $connection->raw('NOT shift_self_signup'),
+ ]);
+ });
+ }
+}
diff --git a/db/migrations/2023_08_27_000000_add_hide_on_shift_view_to_angeltypes.php b/db/migrations/2023_08_27_000000_add_hide_on_shift_view_to_angeltypes.php
new file mode 100644
index 000000000..3fe8a1757
--- /dev/null
+++ b/db/migrations/2023_08_27_000000_add_hide_on_shift_view_to_angeltypes.php
@@ -0,0 +1,31 @@
+schema->table('angel_types', function (Blueprint $table): void {
+ $table->boolean('hide_on_shift_view')->default(false)->after('hide_register');
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('angel_types', function (Blueprint $table): void {
+ $table->dropColumn('hide_on_shift_view');
+ });
+ }
+}
diff --git a/db/migrations/2023_09_17_000000_add_user_to_sessions_table.php b/db/migrations/2023_09_17_000000_add_user_to_sessions_table.php
new file mode 100644
index 000000000..935e5be91
--- /dev/null
+++ b/db/migrations/2023_09_17_000000_add_user_to_sessions_table.php
@@ -0,0 +1,34 @@
+schema->table('sessions', function (Blueprint $table): void {
+ $this->referencesUser($table)->nullable()->index()->after('payload');
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('sessions', function (Blueprint $table): void {
+ $table->dropForeign('sessions_user_id_foreign');
+ $table->dropColumn('user_id');
+ });
+ }
+}
diff --git a/db/migrations/2023_09_18_000000_news_rename_important_to_highlight.php b/db/migrations/2023_09_18_000000_news_rename_important_to_highlight.php
new file mode 100644
index 000000000..352ac3b62
--- /dev/null
+++ b/db/migrations/2023_09_18_000000_news_rename_important_to_highlight.php
@@ -0,0 +1,41 @@
+schema->table('news', function (Blueprint $table): void {
+ $table->renameColumn('is_important', 'is_highlighted');
+ });
+
+ $this->schema->getConnection()
+ ->table('privileges')
+ ->where('name', 'news.important')
+ ->update(['name' => 'news.highlight', 'description' => 'Highlight News']);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('news', function (Blueprint $table): void {
+ $table->renameColumn('is_highlighted', 'is_important');
+ });
+
+ $this->schema->getConnection()
+ ->table('privileges')
+ ->where('name', 'news.highlight')
+ ->update(['name' => 'news.important', 'description' => 'Make News Important']);
+ }
+}
diff --git a/db/migrations/2023_10_13_000000_rename_rooms_to_locations.php b/db/migrations/2023_10_13_000000_rename_rooms_to_locations.php
new file mode 100644
index 000000000..f71a10d18
--- /dev/null
+++ b/db/migrations/2023_10_13_000000_rename_rooms_to_locations.php
@@ -0,0 +1,69 @@
+schema->rename('rooms', 'locations');
+
+ $this->schema->table('shifts', function (Blueprint $table): void {
+ $table->renameColumn('room_id', 'location_id');
+ });
+
+ $this->schema->table('needed_angel_types', function (Blueprint $table): void {
+ $table->renameColumn('room_id', 'location_id');
+ });
+
+ $db = $this->schema->getConnection();
+ $db->table('privileges')->where('name', 'admin_rooms')->update([
+ 'name' => 'admin_locations',
+ 'description' => 'Manage locations',
+ ]);
+ $db->table('privileges')->where('name', 'view_rooms')->update([
+ 'name' => 'view_locations',
+ 'description' => 'User can view locations',
+ ]);
+ $db->table('privileges')->where('name', 'schedule.import')->update([
+ 'description' => 'Import locations and shifts from schedule.xml',
+ ]);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->rename('locations', 'rooms');
+
+ $this->schema->table('shifts', function (Blueprint $table): void {
+ $table->renameColumn('location_id', 'room_id');
+ });
+
+ $this->schema->table('needed_angel_types', function (Blueprint $table): void {
+ $table->renameColumn('location_id', 'room_id');
+ });
+
+ $db = $this->schema->getConnection();
+ $db->table('privileges')->where('name', 'admin_locations')->update([
+ 'name' => 'admin_rooms',
+ 'description' => 'RΓ€ume administrieren',
+ ]);
+ $db->table('privileges')->where('name', 'view_locations')->update([
+ 'name' => 'view_rooms',
+ 'description' => 'User can view rooms',
+ ]);
+ $db->table('privileges')->where('name', 'schedule.import')->update([
+ 'description' => 'Import rooms and shifts from schedule.xml',
+ ]);
+ }
+}
diff --git a/db/migrations/2023_10_22_000000_add_missing_schedule_foreign_keys.php b/db/migrations/2023_10_22_000000_add_missing_schedule_foreign_keys.php
new file mode 100644
index 000000000..da95ab90f
--- /dev/null
+++ b/db/migrations/2023_10_22_000000_add_missing_schedule_foreign_keys.php
@@ -0,0 +1,39 @@
+schema->getConnection()->getDoctrineSchemaManager();
+
+ $hasShiftTypeReference = $schemaManager->introspectTable('schedules')
+ ->hasIndex('schedules_shift_type_foreign');
+ if (!$hasShiftTypeReference) {
+ $this->schema->table('schedules', function (Blueprint $table): void {
+ $table->unsignedInteger('shift_type')->change();
+ $this->addReference($table, 'shift_type', 'shift_types');
+ });
+ }
+
+ $hasShiftIdReference = $schemaManager->introspectTable('schedule_shift')
+ ->hasIndex('schedule_shift_schedule_id_foreign');
+ if (!$hasShiftIdReference) {
+ $this->schema->table('schedule_shift', function (Blueprint $table): void {
+ $table->unsignedInteger('shift_id')->change();
+ $this->addReference($table, 'shift_id', 'shifts');
+ });
+ }
+ }
+}
diff --git a/db/migrations/2023_10_25_000000_degender_shirt_sizes.php b/db/migrations/2023_10_25_000000_degender_shirt_sizes.php
new file mode 100644
index 000000000..e41c8ee4d
--- /dev/null
+++ b/db/migrations/2023_10_25_000000_degender_shirt_sizes.php
@@ -0,0 +1,50 @@
+ 'S-F',
+ 'M-G' => 'M-F',
+ 'L-G' => 'L-F',
+ 'XL-G' => 'XL-F',
+ ];
+
+ /**
+ * Run the migration
+ */
+ public function up(): void
+ {
+ $this->migrate($this->sizes);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->migrate(array_flip($this->sizes));
+ }
+
+ /**
+ * @param string[] $sizes
+ */
+ private function migrate(array $sizes): void
+ {
+ $connection = $this->schema->getConnection();
+ foreach ($sizes as $from => $to) {
+ $connection
+ ->table('users_personal_data')
+ ->where('shirt_size', $from)
+ ->update([
+ 'shirt_size' => $to,
+ ]);
+ }
+ }
+}
diff --git a/db/migrations/2023_11_16_000000_add_user_info_to_users_state.php b/db/migrations/2023_11_16_000000_add_user_info_to_users_state.php
new file mode 100644
index 000000000..53484a469
--- /dev/null
+++ b/db/migrations/2023_11_16_000000_add_user_info_to_users_state.php
@@ -0,0 +1,31 @@
+schema->table('users_state', function (Blueprint $table): void {
+ $table->string('user_info')->nullable()->default(null)->after('arrival_date');
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('users_state', function (Blueprint $table): void {
+ $table->dropColumn('user_info');
+ });
+ }
+}
diff --git a/db/migrations/2023_11_16_000001_add_user_info_permissions.php b/db/migrations/2023_11_16_000001_add_user_info_permissions.php
new file mode 100644
index 000000000..6d272c5b8
--- /dev/null
+++ b/db/migrations/2023_11_16_000001_add_user_info_permissions.php
@@ -0,0 +1,52 @@
+schema->getConnection();
+ $db->table('privileges')
+ ->insert([
+ ['name' => 'user.info.show', 'description' => 'Show User Info'],
+ ['name' => 'user.info.edit', 'description' => 'Edit User Info'],
+ ]);
+
+ $showUserInfo = $db->table('privileges')
+ ->where('name', 'user.info.show')
+ ->get(['id'])
+ ->first();
+
+ $editUserInfo = $db->table('privileges')
+ ->where('name', 'user.info.edit')
+ ->get(['id'])
+ ->first();
+
+ $buerocrat = 80;
+ $shico = 60;
+ $db->table('group_privileges')
+ ->insertOrIgnore([
+ ['group_id' => $buerocrat, 'privilege_id' => $editUserInfo->id],
+ ['group_id' => $shico, 'privilege_id' => $showUserInfo->id],
+ ]);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $db = $this->schema->getConnection();
+ $db->table('privileges')
+ ->whereIn('name', ['user.info.edit', 'user.info.show'])
+ ->delete();
+ }
+}
diff --git a/db/migrations/2023_12_06_000000_add_user_id_to_log_entries.php b/db/migrations/2023_12_06_000000_add_user_id_to_log_entries.php
new file mode 100644
index 000000000..a3bd80292
--- /dev/null
+++ b/db/migrations/2023_12_06_000000_add_user_id_to_log_entries.php
@@ -0,0 +1,38 @@
+schema->table('log_entries', function (Blueprint $table): void {
+ $table->unsignedInteger('user_id')->after('id')->nullable()->default(null);
+ $table->foreign('user_id')
+ ->references('id')->on('users')
+ ->onUpdate('cascade')
+ ->nullOnDelete();
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('log_entries', function (Blueprint $table): void {
+ $table->dropForeign('log_entries_user_id_foreign');
+ $table->dropColumn('user_id');
+ });
+ }
+}
diff --git a/db/migrations/2023_12_06_000000_change_edit_shirt_require_bureaucrat.php b/db/migrations/2023_12_06_000000_change_edit_shirt_require_bureaucrat.php
new file mode 100644
index 000000000..32e91ece7
--- /dev/null
+++ b/db/migrations/2023_12_06_000000_change_edit_shirt_require_bureaucrat.php
@@ -0,0 +1,57 @@
+db = $this->schema->getConnection();
+
+ $this->editShirt = $this->db->table('privileges')
+ ->where('name', 'user.edit.shirt')
+ ->get(['id'])
+ ->first()->id;
+ }
+
+ /**
+ * Run the migration
+ */
+ public function up(): void
+ {
+ $this->movePermission($this->editShirt, $this->shiCo, $this->bureaucrat);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->movePermission($this->editShirt, $this->bureaucrat, $this->shiCo);
+ }
+
+ protected function movePermission(int $privilege, int $oldGroup, int $newGroup): void
+ {
+ $this->db->table('group_privileges')
+ ->insertOrIgnore(['group_id' => $newGroup, 'privilege_id' => $privilege]);
+
+ $this->db->table('group_privileges')
+ ->where(['group_id' => $oldGroup, 'privilege_id' => $privilege])
+ ->delete();
+ }
+}
diff --git a/db/migrations/2023_12_06_000001_add_logs_all_permission.php b/db/migrations/2023_12_06_000001_add_logs_all_permission.php
new file mode 100644
index 000000000..41a2df792
--- /dev/null
+++ b/db/migrations/2023_12_06_000001_add_logs_all_permission.php
@@ -0,0 +1,44 @@
+schema->getConnection();
+ $db->table('privileges')
+ ->insert([
+ ['name' => 'logs.all', 'description' => 'View all logs'],
+ ]);
+
+ $logsAll = $db->table('privileges')
+ ->where('name', 'logs.all')
+ ->get(['id'])
+ ->first();
+
+ $bureaucrat = 80;
+ $db->table('group_privileges')
+ ->insertOrIgnore([
+ ['group_id' => $bureaucrat, 'privilege_id' => $logsAll->id],
+ ]);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $db = $this->schema->getConnection();
+ $db->table('privileges')
+ ->where('name', 'logs.all')
+ ->delete();
+ }
+}
diff --git a/db/migrations/2023_12_19_000000_schedule_shift_type_needed_angel_types.php b/db/migrations/2023_12_19_000000_schedule_shift_type_needed_angel_types.php
new file mode 100644
index 000000000..e9ce54d59
--- /dev/null
+++ b/db/migrations/2023_12_19_000000_schedule_shift_type_needed_angel_types.php
@@ -0,0 +1,40 @@
+schema->table('schedules', function (Blueprint $table): void {
+ $table->boolean('needed_from_shift_type')->after('shift_type')->default(false);
+ });
+ $this->schema->table('needed_angel_types', function (Blueprint $table): void {
+ $this->references($table, 'shift_types')->after('shift_id')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $this->schema->table('schedules', function (Blueprint $table): void {
+ $table->dropColumn('needed_from_shift_type');
+ });
+ $this->schema->table('needed_angel_types', function (Blueprint $table): void {
+ $table->dropForeign('needed_angel_types_shift_type_id_foreign');
+ $table->dropColumn('shift_type_id');
+ });
+ }
+}
diff --git a/db/migrations/2023_12_21_000000_add_user_edit_permission.php b/db/migrations/2023_12_21_000000_add_user_edit_permission.php
new file mode 100644
index 000000000..922840bb9
--- /dev/null
+++ b/db/migrations/2023_12_21_000000_add_user_edit_permission.php
@@ -0,0 +1,44 @@
+schema->getConnection();
+ $db->table('privileges')
+ ->insert([
+ 'name' => 'user.edit', 'description' => 'Edit user',
+ ]);
+
+ $editUser = $db->table('privileges')
+ ->where('name', 'user.edit')
+ ->get(['id'])
+ ->first();
+
+ $buerocrat = 80;
+ $db->table('group_privileges')
+ ->insertOrIgnore([
+ 'group_id' => $buerocrat, 'privilege_id' => $editUser->id,
+ ]);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $db = $this->schema->getConnection();
+ $db->table('privileges')
+ ->where('name', 'user.edit')
+ ->delete();
+ }
+}
diff --git a/db/migrations/2023_12_26_000000_create_schedule_locations_table.php b/db/migrations/2023_12_26_000000_create_schedule_locations_table.php
new file mode 100644
index 000000000..2f5e5d3ef
--- /dev/null
+++ b/db/migrations/2023_12_26_000000_create_schedule_locations_table.php
@@ -0,0 +1,52 @@
+schema->getConnection();
+
+ $this->schema->create('schedule_locations', function (Blueprint $table): void {
+ $table->increments('id');
+ $this->references($table, 'schedules');
+ $this->references($table, 'locations');
+
+ $table->index(['schedule_id', 'location_id']);
+ });
+
+ $scheduleLocations = $connection
+ ->table('schedule_shift')
+ ->select(['schedules.id AS schedule_id', 'locations.id AS location_id'])
+ ->leftJoin('schedules', 'schedules.id', 'schedule_shift.schedule_id')
+ ->leftJoin('shifts', 'shifts.id', 'schedule_shift.shift_id')
+ ->leftJoin('locations', 'locations.id', 'shifts.location_id')
+ ->groupBy(['schedules.id', 'locations.id'])
+ ->get();
+
+ foreach ($scheduleLocations as $scheduleLocation) {
+ $connection->table('schedule_locations')
+ ->insert((array) $scheduleLocation);
+ }
+ }
+
+ /**
+ * Drops the table
+ */
+ public function down(): void
+ {
+ $this->schema->drop('schedule_locations');
+ }
+}
diff --git a/db/migrations/2023_12_27_000000_add_shifttypes_edit_permission_and_shifttypes_requires_shico.php b/db/migrations/2023_12_27_000000_add_shifttypes_edit_permission_and_shifttypes_requires_shico.php
new file mode 100644
index 000000000..2237670bd
--- /dev/null
+++ b/db/migrations/2023_12_27_000000_add_shifttypes_edit_permission_and_shifttypes_requires_shico.php
@@ -0,0 +1,77 @@
+db = $this->schema->getConnection();
+
+ $this->shifttypes = $this->db->table('privileges')
+ ->where('name', 'shifttypes')
+ ->get(['id'])
+ ->first()->id;
+ }
+
+ /**
+ * Run the migration
+ */
+ public function up(): void
+ {
+ $db = $this->schema->getConnection();
+ $db->table('privileges')
+ ->insert([
+ 'name' => 'shifttypes.edit', 'description' => 'Edit shift types',
+ ]);
+
+ $editShifttypes = $db->table('privileges')
+ ->where('name', 'shifttypes.edit')
+ ->get(['id'])
+ ->first();
+
+ $this->movePermission($this->shifttypes, $this->bureaucrat, $this->shiCo);
+
+ $db->table('group_privileges')
+ ->insertOrIgnore([
+ 'group_id' => $this->bureaucrat, 'privilege_id' => $editShifttypes->id,
+ ]);
+ }
+
+ /**
+ * Reverse the migration
+ */
+ public function down(): void
+ {
+ $db = $this->schema->getConnection();
+ $db->table('privileges')
+ ->where('name', 'shifttypes.edit')
+ ->delete();
+
+ $this->movePermission($this->shifttypes, $this->shiCo, $this->bureaucrat);
+ }
+
+ protected function movePermission(int $privilege, int $oldGroup, int $newGroup): void
+ {
+ $this->db->table('group_privileges')
+ ->insertOrIgnore(['group_id' => $newGroup, 'privilege_id' => $privilege]);
+
+ $this->db->table('group_privileges')
+ ->where(['group_id' => $oldGroup, 'privilege_id' => $privilege])
+ ->delete();
+ }
+}
diff --git a/db/migrations/Reference.php b/db/migrations/Reference.php
index 7f502f3a9..0a242e9bd 100644
--- a/db/migrations/Reference.php
+++ b/db/migrations/Reference.php
@@ -30,7 +30,7 @@ protected function references(
$table->primary($fromColumn);
}
- $this->addReference($table, $fromColumn, $targetTable, $targetColumn ?: 'id');
+ $this->addReference($table, $fromColumn, $targetTable, $targetColumn);
return $col;
}
diff --git a/db/update.sql b/db/update.sql
deleted file mode 100644
index 56663071c..000000000
--- a/db/update.sql
+++ /dev/null
@@ -1,59 +0,0 @@
-INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (40, 'view_rooms', 'User can view rooms');
-INSERT INTO `GroupPrivileges` (`id`, `group_id`, `privilege_id`) VALUES (NULL, '-2', '40');
-
-ALTER TABLE `UserAngelTypes` CHANGE `coordinator` `supporter` BOOLEAN;
-
-ALTER TABLE `User` ADD COLUMN `email_by_human_allowed` BOOLEAN NOT NULL;
-
--- No Self Sign Up for some Angel Types
-ALTER TABLE AngelTypes ADD no_self_signup TINYINT(1) NOT NULL;
-
-ALTER TABLE `AngelTypes`
- ADD `contact_user_id` INT NULL,
- ADD `contact_name` VARCHAR(250) NULL,
- ADD `contact_dect` VARCHAR(5) NULL,
- ADD `contact_email` VARCHAR(250) NULL,
- ADD INDEX (`contact_user_id`);
-ALTER TABLE `AngelTypes`
- ADD FOREIGN KEY (`contact_user_id`) REFERENCES `User`(`UID`) ON DELETE SET NULL ON UPDATE CASCADE;
-
-INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (NULL, 'shiftentry_edit_angeltype_supporter', 'If user with this privilege is angeltype supporter, he can put users in shifts for their angeltype');
-
--- DB Performance
-ALTER TABLE `Shifts` ADD INDEX(`start`);
-ALTER TABLE `NeededAngelTypes` ADD INDEX(`count`);
-
--- Security
-UPDATE `Groups` SET UID = UID * 10;
-INSERT INTO `Groups` (Name, UID) VALUES ('News Admin', -65);
-INSERT INTO `Privileges` (id, name, `desc`) VALUES (42, 'admin_news_html', 'Use HTML in news');
-INSERT INTO `GroupPrivileges` (group_id, privilege_id) VALUES (-65, 14), (-65, 42);
-
--- Add log level to LogEntries
-ALTER TABLE `LogEntries` CHANGE COLUMN `nick` `level` VARCHAR(20) NOT NULL;
-
--- Angeltype contact update
-ALTER TABLE `AngelTypes` DROP FOREIGN KEY angeltypes_ibfk_1;
-ALTER TABLE `AngelTypes` DROP `contact_user_id`;
-
--- Room update
-ALTER TABLE `Room` DROP `Number`;
-ALTER TABLE `Room` DROP `show`;
-ALTER TABLE `Room` DROP `Man`;
-ALTER TABLE `Room` ADD `from_frab` BOOLEAN NOT NULL AFTER `FromPentabarf`;
-UPDATE Room SET `from_frab` = (`FromPentabarf` = 'Y');
-ALTER TABLE `Room` DROP `FromPentabarf`;
-ALTER TABLE `Room` ADD `map_url` VARCHAR(300) NULL AFTER `from_frab`;
-ALTER TABLE `Room` ADD `description` TEXT NULL AFTER `map_url`;
-
--- Dashboard
-ALTER TABLE `AngelTypes` ADD `show_on_dashboard` BOOLEAN NOT NULL AFTER `contact_email`;
-UPDATE `AngelTypes` SET `show_on_dashboard` = TRUE;
-
--- Work Log
-CREATE TABLE `UserWorkLog` ( `id` INT NOT NULL AUTO_INCREMENT , `user_id` INT NOT NULL , `work_hours` DECIMAL NOT NULL , `comment` VARCHAR(200) NOT NULL , `created_user_id` INT NOT NULL , `created_timestamp` INT NOT NULL , PRIMARY KEY (`id`), INDEX (`user_id`), INDEX (`created_user_id`)) ENGINE = InnoDB;
-ALTER TABLE `UserWorkLog` ADD FOREIGN KEY (`created_user_id`) REFERENCES `User`(`UID`) ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE `UserWorkLog` ADD FOREIGN KEY (`user_id`) REFERENCES `User`(`UID`) ON DELETE CASCADE ON UPDATE CASCADE;
-ALTER TABLE `UserWorkLog` ADD INDEX(`created_timestamp`);
-INSERT INTO `Privileges` (`id`, `name`, `desc`) VALUES (NULL, 'admin_user_worklog', 'Manage user work log entries.');
-ALTER TABLE `UserWorkLog` CHANGE `work_hours` `work_hours` DECIMAL(10,2) NOT NULL;
-ALTER TABLE `UserWorkLog` ADD `work_timestamp` INT NOT NULL AFTER `user_id`;
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 2d3385b76..58aa7c729 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -5,13 +5,13 @@ RUN composer --no-ansi install --no-dev --ignore-platform-reqs
RUN composer --no-ansi dump-autoload --optimize
# Generate .mo files
-FROM alpine as translation
+FROM alpine AS translation
RUN apk add gettext
COPY resources/lang/ /data
-RUN find /data -type f -name '*.po' -exec sh -c 'file="{}"; msgfmt "${file%.*}.po" -o "${file%.*}.mo"' \;
+RUN find /data -type f -name '*.po' -exec sh -c 'msgfmt "${1%.*}.po" -o"${1%.*}.mo"' shell {} \;
# Build the themes
-FROM node:14-alpine as themes
+FROM node:20-alpine AS themes
WORKDIR /app
COPY .babelrc .browserslistrc package.json webpack.config.js yarn.lock /app/
RUN yarn --frozen-lockfile
@@ -19,13 +19,14 @@ COPY resources/assets/ /app/resources/assets
RUN yarn build
# Generate application structure
-FROM alpine as data
+FROM alpine AS data
COPY .babelrc .browserslistrc composer.json LICENSE package.json README.md webpack.config.js yarn.lock /app/
COPY bin/ /app/bin
COPY config/ /app/config
COPY db/ /app/db
COPY includes/ /app/includes
COPY public/ /app/public
+COPY resources/api /app/resources/api
COPY resources/views /app/resources/views
COPY src/ /app/src
COPY storage/ /app/storage
diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile
index 6998fc152..685cc8aa8 100644
--- a/docker/dev/Dockerfile
+++ b/docker/dev/Dockerfile
@@ -24,7 +24,7 @@ ENV TRUSTED_PROXIES 10.0.0.0/8,::ffff:10.0.0.0/8,\
# Engelsystem development workspace
# Contains all tools required to build / manage the system
FROM es_base AS es_workspace
-RUN echo 'memory_limit = 512M' > /usr/local/etc/php/conf.d/docker-php.ini
+RUN echo 'memory_limit = 1024M' > /usr/local/etc/php/conf.d/docker-php.ini
RUN apk add --no-cache gettext git nodejs npm yarn
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
ENTRYPOINT php -r 'sleep(PHP_INT_MAX);'
diff --git a/includes/controller/angeltypes_controller.php b/includes/controller/angeltypes_controller.php
index bdc005720..741f8afb2 100644
--- a/includes/controller/angeltypes_controller.php
+++ b/includes/controller/angeltypes_controller.php
@@ -2,7 +2,7 @@
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\AngelType;
-use Engelsystem\Models\Room;
+use Engelsystem\Models\Location;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftsFilter;
use Engelsystem\ShiftsFilterRenderer;
@@ -17,7 +17,7 @@
*/
function angeltypes_title()
{
- return __('Angeltypes');
+ return __('angeltypes.angeltypes');
}
/**
@@ -48,7 +48,7 @@ function angeltypes_controller()
function angeltype_link($angeltype_id, $params = [])
{
$params = array_merge(['action' => 'view', 'angeltype_id' => $angeltype_id], $params);
- return page_link_to('angeltypes', $params);
+ return url('/angeltypes', $params);
}
/**
@@ -59,7 +59,7 @@ function angeltype_link($angeltype_id, $params = [])
function angeltype_delete_controller()
{
if (!auth()->can('admin_angel_types')) {
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
@@ -68,11 +68,11 @@ function angeltype_delete_controller()
$angeltype->delete();
engelsystem_log('Deleted angeltype: ' . AngelType_name_render($angeltype, true));
success(sprintf(__('Angeltype %s deleted.'), $angeltype->name));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
return [
- sprintf(__('Delete angeltype %s'), $angeltype->name),
+ sprintf(__('Delete angeltype %s'), htmlspecialchars($angeltype->name)),
AngelType_delete_view($angeltype),
];
}
@@ -92,14 +92,14 @@ function angeltype_edit_controller()
// Edit existing angeltype
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
- if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
- throw_redirect(page_link_to('angeltypes'));
+ if (!auth()->user()?->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
+ throw_redirect(url('/angeltypes'));
}
} else {
// New angeltype
if ($supporter_mode) {
// Supporters aren't allowed to create new angeltypes.
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
$angeltype = new AngelType();
}
@@ -118,11 +118,13 @@ function angeltype_edit_controller()
}
$angeltype->restricted = $request->has('restricted');
- $angeltype->no_self_signup = $request->has('no_self_signup');
+ $angeltype->shift_self_signup = $request->has('shift_self_signup');
$angeltype->show_on_dashboard = $request->has('show_on_dashboard');
$angeltype->hide_register = $request->has('hide_register');
+ $angeltype->hide_on_shift_view = $request->has('hide_on_shift_view');
$angeltype->requires_driver_license = $request->has('requires_driver_license');
+ $angeltype->requires_ifsg_certificate = $request->has('requires_ifsg_certificate');
}
$angeltype->description = strip_request_item_nl('description', $angeltype->description);
@@ -137,20 +139,22 @@ function angeltype_edit_controller()
success('Angel type saved.');
engelsystem_log(
'Saved angeltype: ' . $angeltype->name . ($angeltype->restricted ? ', restricted' : '')
- . ($angeltype->no_self_signup ? ', no_self_signup' : '')
+ . ($angeltype->shift_self_signup ? ', shift_self_signup' : '')
. ($angeltype->requires_driver_license ? ', requires driver license' : '') . ', '
+ . ($angeltype->requires_ifsg_certificate ? ', requires ifsg certificate' : '') . ', '
. $angeltype->contact_name . ', '
. $angeltype->contact_dect . ', '
. $angeltype->contact_email . ', '
. $angeltype->show_on_dashboard . ', '
- . $angeltype->hide_register
+ . $angeltype->hide_register . ', '
+ . $angeltype->hide_on_shift_view
);
throw_redirect(angeltype_link($angeltype->id));
}
}
return [
- sprintf(__('Edit %s'), $angeltype->name),
+ sprintf(__('Edit %s'), htmlspecialchars((string) $angeltype->name)),
AngelType_edit_view($angeltype, $supporter_mode),
];
}
@@ -165,14 +169,15 @@ function angeltype_controller()
$user = auth()->user();
if (!auth()->can('angeltypes')) {
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
$angeltype = AngelType::findOrFail(request()->input('angeltype_id'));
/** @var UserAngelType $user_angeltype */
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
- $members = $angeltype->userAngelTypes->sortBy('name');
-
+ $members = $angeltype->userAngelTypes
+ ->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE)
+ ->load(['state', 'personalData', 'contact']);
$days = angeltype_controller_shiftsFilterDays($angeltype);
$shiftsFilter = angeltype_controller_shiftsFilter($angeltype, $days);
if (request()->input('showFilledShifts')) {
@@ -192,7 +197,7 @@ function angeltype_controller()
$isSupporter = !is_null($user_angeltype) && $user_angeltype->supporter;
return [
- sprintf(__('Team %s'), $angeltype->name),
+ sprintf(__('Team %s'), htmlspecialchars($angeltype->name)),
AngelType_view(
$angeltype,
$members,
@@ -221,9 +226,8 @@ function angeltype_controller_shiftsFilterDays(AngelType $angeltype)
$days = [];
foreach ($all_shifts as $shift) {
$day = Carbon::make($shift['start'])->format('Y-m-d');
- $dayFormatted = Carbon::make($shift['start'])->format(__('Y-m-d'));
if (!isset($days[$day])) {
- $days[$day] = $dayFormatted;
+ $days[$day] = dateWithEventDay($day);
}
}
ksort($days);
@@ -240,13 +244,13 @@ function angeltype_controller_shiftsFilterDays(AngelType $angeltype)
function angeltype_controller_shiftsFilter(AngelType $angeltype, $days)
{
$request = request();
- $roomIds = Room::query()
+ $locationIds = Location::query()
->select('id')
->pluck('id')
->toArray();
$shiftsFilter = new ShiftsFilter(
auth()->can('user_shifts_admin'),
- $roomIds,
+ $locationIds,
[$angeltype->id]
);
$selected_day = date('Y-m-d');
@@ -270,59 +274,70 @@ function angeltype_controller_shiftsFilter(AngelType $angeltype, $days)
function angeltypes_list_controller()
{
$user = auth()->user();
+ $admin_angeltypes = auth()->can('admin_angel_types');
if (!auth()->can('angeltypes')) {
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
$angeltypes = AngelTypes_with_user($user->id);
foreach ($angeltypes as $angeltype) {
$actions = [
button(
- page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
- icon('eye') . __('view'),
- 'btn-sm'
+ url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
+ icon('eye') . ($admin_angeltypes ? '' : __('View')),
+ 'btn-sm btn-info',
+ '',
+ ($admin_angeltypes ? __('View') : '')
),
];
- if (auth()->can('admin_angel_types')) {
+ if ($admin_angeltypes) {
$actions[] = button(
- page_link_to('angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
- icon('pencil') . __('edit'),
- 'btn-sm'
+ url('/angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
+ icon('pencil'),
+ 'btn-sm',
+ '',
+ __('form.edit')
);
$actions[] = button(
- page_link_to('angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
- icon('trash') . __('delete'),
- 'btn-sm'
+ url('/angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
+ icon('trash'),
+ 'btn-sm btn-danger',
+ '',
+ __('form.delete')
);
}
$angeltype->membership = AngelType_render_membership($angeltype);
if (!empty($angeltype->user_angel_type_id)) {
$actions[] = button(
- page_link_to(
- 'user_angeltypes',
+ url(
+ '/user-angeltypes',
['action' => 'delete', 'user_angeltype_id' => $angeltype->user_angel_type_id]
),
- icon('box-arrow-right') . __('leave'),
- 'btn-sm'
+ icon('box-arrow-right') . ($admin_angeltypes ? '' : __('Leave')),
+ 'btn-sm',
+ '',
+ ($admin_angeltypes ? __('Leave') : '')
);
} else {
$actions[] = button(
- page_link_to('user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
- icon('box-arrow-in-right') . __('join'),
- 'btn-sm'
+ url('/user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
+ icon('box-arrow-in-right') . ($admin_angeltypes ? '' : __('Join')),
+ 'btn-sm',
+ '',
+ ($admin_angeltypes ? __('Join') : '')
);
}
$angeltype->is_restricted = $angeltype->restricted ? icon('mortarboard-fill') : '';
- $angeltype->no_self_signup_allowed = $angeltype->no_self_signup ? '' : icon('pencil-square');
+ $angeltype->shift_self_signup_allowed = $angeltype->shift_self_signup ? icon('pencil-square') : '';
$angeltype->name = ''
- . $angeltype->name
+ . htmlspecialchars($angeltype->name)
. '';
$angeltype->actions = table_buttons($actions);
diff --git a/includes/controller/event_config_controller.php b/includes/controller/event_config_controller.php
index 24e07df37..16322acf7 100644
--- a/includes/controller/event_config_controller.php
+++ b/includes/controller/event_config_controller.php
@@ -17,7 +17,7 @@ function event_config_title()
function event_config_edit_controller()
{
if (!auth()->can('admin_event_config')) {
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
$request = request();
@@ -117,8 +117,8 @@ function event_config_edit_controller()
$teardown_end_date ? $teardown_end_date->format('Y-m-d H:i') : ''
)
);
- success(__('Settings saved.'));
- throw_redirect(page_link_to('admin_event_config'));
+ success(__('settings.success'));
+ throw_redirect(url('/admin_event_config'));
}
}
diff --git a/includes/controller/rooms_controller.php b/includes/controller/locations_controller.php
similarity index 52%
rename from includes/controller/rooms_controller.php
rename to includes/controller/locations_controller.php
index 2136565ab..36bb80947 100644
--- a/includes/controller/rooms_controller.php
+++ b/includes/controller/locations_controller.php
@@ -1,40 +1,40 @@
can('view_rooms')) {
- throw_redirect(page_link_to());
+ if (!auth()->can('view_locations')) {
+ throw_redirect(url('/'));
}
$request = request();
- $room = load_room();
+ $location = load_location();
- $all_shifts = $room->shifts->sortBy('start');
+ $all_shifts = $location->shifts->sortBy('start');
$days = [];
foreach ($all_shifts as $shift) {
$day = $shift->start->format('Y-m-d');
if (!isset($days[$day])) {
- $days[$day] = $shift->start->format(__('Y-m-d'));
+ $days[$day] = dateWithEventDay($day);
}
}
$shiftsFilter = new ShiftsFilter(
true,
- [$room->id],
+ [$location->id],
AngelType::query()->get('id')->pluck('id')->toArray()
);
$selected_day = date('Y-m-d');
@@ -53,17 +53,17 @@ function room_controller(): array
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
return [
- $room->name,
- Room_view($room, $shiftsFilterRenderer, $shiftCalendarRenderer),
+ htmlspecialchars($location->name),
+ location_view($location, $shiftsFilterRenderer, $shiftCalendarRenderer),
];
}
/**
- * Dispatch different room actions.
+ * Dispatch different location actions.
*
* @return array
*/
-function rooms_controller(): array
+function locations_controller(): array
{
$request = request();
$action = $request->input('action');
@@ -72,36 +72,36 @@ function rooms_controller(): array
}
return match ($action) {
- 'view' => room_controller(),
- 'list' => throw_redirect(page_link_to('admin/rooms')),
- default => throw_redirect(page_link_to('admin/rooms')),
+ 'view' => location_controller(),
+ 'list' => throw_redirect(url('/admin/locations')),
+ default => throw_redirect(url('/admin/locations')),
};
}
/**
- * @param Room $room
+ * @param Location $location
* @return string
*/
-function room_link(Room $room)
+function location_link(Location $location)
{
- return page_link_to('rooms', ['action' => 'view', 'room_id' => $room->id]);
+ return url('/locations', ['action' => 'view', 'location_id' => $location->id]);
}
/**
- * Loads room by request param room_id
+ * Loads location by request param location_id
*
- * @return Room
+ * @return Location
*/
-function load_room()
+function load_location()
{
- if (!test_request_int('room_id')) {
- throw_redirect(page_link_to());
+ if (!test_request_int('location_id')) {
+ throw_redirect(url('/'));
}
- $room = Room::find(request()->input('room_id'));
- if (!$room) {
- throw_redirect(page_link_to());
+ $location = Location::find(request()->input('location_id'));
+ if (!$location) {
+ throw_redirect(url('/'));
}
- return $room;
+ return $location;
}
diff --git a/includes/controller/public_dashboard_controller.php b/includes/controller/public_dashboard_controller.php
index d4f73434f..223705776 100644
--- a/includes/controller/public_dashboard_controller.php
+++ b/includes/controller/public_dashboard_controller.php
@@ -1,8 +1,8 @@
get('filtered')) {
- $requestRooms = check_request_int_array('rooms');
+ $requestLocations = check_request_int_array('locations');
$requestAngelTypes = check_request_int_array('types');
- if (!$requestRooms && !$requestAngelTypes) {
+ if (!$requestLocations && !$requestAngelTypes) {
$sessionFilter = collect(session()->get('shifts-filter', []));
- $requestRooms = $sessionFilter->get('rooms', []);
+ $requestLocations = $sessionFilter->get('locations', []);
$requestAngelTypes = $sessionFilter->get('types', []);
}
$angelTypes = collect(unrestricted_angeltypes());
- $rooms = $requestRooms ?: Room::orderBy('name')->get()->pluck('id')->toArray();
+ $locations = $requestLocations ?: Location::orderBy('name')->get()->pluck('id')->toArray();
$angelTypes = $requestAngelTypes ?: $angelTypes->pluck('id')->toArray();
$filterValues = [
'userShiftsAdmin' => false,
'filled' => [],
- 'rooms' => $rooms,
+ 'locations' => $locations,
'types' => $angelTypes,
'startTime' => null,
'endTime' => null,
@@ -57,14 +57,14 @@ function public_dashboard_controller()
}
}
- $important_news = News::whereIsImportant(true)
+ $highlighted_news = News::whereIsHighlighted(true)
->orderBy('updated_at')
->limit(1)
->get();
return [
__('Public Dashboard'),
- public_dashboard_view($stats, $free_shifts, $important_news),
+ public_dashboard_view($stats, $free_shifts, $highlighted_news),
];
}
@@ -87,7 +87,7 @@ function public_dashboard_controller_free_shift(Shift $shift, ShiftsFilter $filt
'duration' => round(($shift->end->timestamp - $shift->start->timestamp) / 3600),
'shifttype_name' => $shift->shiftType->name,
'title' => $shift->title,
- 'room_name' => $shift->room->name,
+ 'location_name' => $shift->location->name,
'needed_angels' => public_dashboard_needed_angels($shift->neededAngels, $filter),
];
@@ -136,5 +136,5 @@ function public_dashboard_needed_angels($needed_angels, ShiftsFilter $filter = n
*/
function public_dashboard_link(array $parameters = []): string
{
- return page_link_to('public-dashboard', $parameters);
+ return url('/public-dashboard', $parameters);
}
diff --git a/includes/controller/shift_entries_controller.php b/includes/controller/shift_entries_controller.php
index ccb0515c9..0951a8a58 100644
--- a/includes/controller/shift_entries_controller.php
+++ b/includes/controller/shift_entries_controller.php
@@ -18,7 +18,7 @@ function shift_entries_controller(): array
{
$user = auth()->user();
if (!$user) {
- throw_redirect(page_link_to('login'));
+ throw_redirect(url('/login'));
}
$action = strip_request_item('action');
@@ -44,7 +44,7 @@ function shift_entry_create_controller(): array
$request = request();
if ($user->isFreeloader()) {
- throw_redirect(page_link_to('user_myshifts'));
+ throw_redirect(url('/user_myshifts'));
}
$shift = Shift($request->input('shift_id'));
@@ -113,17 +113,21 @@ function shift_entry_create_controller_admin(Shift $shift, ?AngelType $angeltype
}
/** @var User[]|Collection $users */
- $users = User::query()->orderBy('name')->get();
+ $users = User::with('userAngelTypes')->orderBy('name')->get();
$users_select = [];
foreach ($users as $user) {
- $users_select[$user->id] = $user->displayName;
+ $name = $user->displayName;
+ if ($user->userAngelTypes->where('id', $angeltype->id)->isEmpty()) {
+ $name = __('%s (not "%s")', [$name, $angeltype->name]);
+ }
+ $users_select[$user->id] = $name;
}
$angeltypes_select = $angeltypes->pluck('name', 'id')->toArray();
- $room = $shift->room;
+ $location = $shift->location;
return [
ShiftEntry_create_title(),
- ShiftEntry_create_view_admin($shift, $room, $angeltype, $angeltypes_select, $signup_user, $users_select),
+ ShiftEntry_create_view_admin($shift, $location, $angeltype, $angeltypes_select, $signup_user, $users_select),
];
}
@@ -167,10 +171,10 @@ function shift_entry_create_controller_supporter(Shift $shift, AngelType $angelt
$users_select[$u->id] = $u->displayName;
}
- $room = $shift->room;
+ $location = $shift->location;
return [
ShiftEntry_create_title(),
- ShiftEntry_create_view_supporter($shift, $room, $angeltype, $signup_user, $users_select),
+ ShiftEntry_create_view_supporter($shift, $location, $angeltype, $signup_user, $users_select),
];
}
@@ -206,7 +210,7 @@ function shift_entry_create_controller_user(Shift $shift, AngelType $angeltype):
$request = request();
$signup_user = auth()->user();
- $needed_angeltype = (new AngelType())->forceFill(NeededAngeltype_by_Shift_and_Angeltype($shift, $angeltype));
+ $needed_angeltype = (new AngelType())->forceFill(NeededAngeltype_by_Shift_and_Angeltype($shift, $angeltype) ?: []);
$shift_entries = $shift->shiftEntries()
->where('angel_type_id', $angeltype->id)
->get();
@@ -250,10 +254,10 @@ function shift_entry_create_controller_user(Shift $shift, AngelType $angeltype):
throw_redirect(shift_link($shift));
}
- $room = $shift->room;
+ $location = $shift->location;
return [
ShiftEntry_create_title(),
- ShiftEntry_create_view_user($shift, $room, $angeltype, $comment),
+ ShiftEntry_create_view_user($shift, $location, $angeltype, $comment),
];
}
@@ -272,7 +276,7 @@ function shift_entry_create_link(Shift $shift, AngelType $angeltype, $params = [
'shift_id' => $shift->id,
'angeltype_id' => $angeltype->id,
], $params);
- return page_link_to('shift_entries', $params);
+ return url('/shift-entries', $params);
}
/**
@@ -288,7 +292,7 @@ function shift_entry_create_link_admin(Shift $shift, $params = [])
'action' => 'create',
'shift_id' => $shift->id,
], $params);
- return page_link_to('shift_entries', $params);
+ return url('/shift-entries', $params);
}
/**
@@ -301,7 +305,7 @@ function shift_entry_load()
$request = request();
if (!$request->has('shift_entry_id') || !test_request_int('shift_entry_id')) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
$shiftEntry = ShiftEntry::findOrFail($request->input('shift_entry_id'));
@@ -362,5 +366,5 @@ function shift_entry_delete_link($shiftEntry, $params = [])
'action' => 'delete',
'shift_entry_id' => $shiftEntry['shift_entry_id'] ?? $shiftEntry['id'],
], $params);
- return page_link_to('shift_entries', $params);
+ return url('/shift-entries', $params);
}
diff --git a/includes/controller/shifts_controller.php b/includes/controller/shifts_controller.php
index fe3b8939b..c552f91b2 100644
--- a/includes/controller/shifts_controller.php
+++ b/includes/controller/shifts_controller.php
@@ -1,8 +1,8 @@
$shift->id]);
+ return url('/user-shifts', ['delete_shift' => $shift->id]);
}
/**
@@ -38,7 +38,7 @@ function shift_delete_link(Shift $shift)
*/
function shift_edit_link(Shift $shift)
{
- return page_link_to('user_shifts', ['edit_shift' => $shift->id]);
+ return url('/user-shifts', ['edit_shift' => $shift->id]);
}
/**
@@ -52,11 +52,11 @@ function shift_edit_controller()
$request = request();
if (!auth()->can('admin_shifts')) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
if (!$request->has('edit_shift') || !test_request_int('edit_shift')) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
$shift_id = $request->input('edit_shift');
@@ -67,14 +67,14 @@ function shift_edit_controller()
));
}
- $rooms = [];
- foreach (Room::orderBy('name')->get() as $room) {
- $rooms[$room->id] = $room->name;
+ $locations = [];
+ foreach (Location::orderBy('name')->get() as $location) {
+ $locations[$location->id] = $location->name;
}
$angeltypes = AngelType::all()->pluck('name', 'id')->toArray();
$shifttypes = ShiftType::all()->pluck('name', 'id')->toArray();
- $needed_angel_types = collect(NeededAngelTypes_by_shift($shift_id))->pluck('count', 'angel_type_id')->toArray();
+ $needed_angel_types = collect(NeededAngelTypes_by_shift($shift))->pluck('count', 'angel_type_id')->toArray();
foreach (array_keys($angeltypes) as $angeltype_id) {
if (!isset($needed_angel_types[$angeltype_id])) {
$needed_angel_types[$angeltype_id] = 0;
@@ -84,7 +84,7 @@ function shift_edit_controller()
$shifttype_id = $shift->shift_type_id;
$title = $shift->title;
$description = $shift->description;
- $rid = $shift->room_id;
+ $rid = $shift->location_id;
$start = $shift->start;
$end = $shift->end;
@@ -97,12 +97,12 @@ function shift_edit_controller()
if (
$request->has('rid')
&& preg_match('/^\d+$/', $request->input('rid'))
- && isset($rooms[$request->input('rid')])
+ && isset($locations[$request->input('rid')])
) {
$rid = $request->input('rid');
} else {
$valid = false;
- error(__('Please select a room.'));
+ error(__('Please select a location.'));
}
if ($request->has('shifttype_id') && isset($shifttypes[$request->input('shifttype_id')])) {
@@ -154,13 +154,16 @@ function shift_edit_controller()
$shift->shift_type_id = $shifttype_id;
$shift->title = $title;
$shift->description = $description;
- $shift->room_id = $rid;
+ $shift->location_id = $rid;
$shift->start = $start;
$shift->end = $end;
$shift->updatedBy()->associate(auth()->user());
$shift->save();
- mail_shift_change($oldShift, $shift);
+ event('shift.updating', [
+ 'shift' => $shift,
+ 'oldShift' => $oldShift,
+ ]);
NeededAngelType::whereShiftId($shift_id)->delete();
$needed_angel_types_info = [];
@@ -194,13 +197,16 @@ function shift_edit_controller()
foreach ($angeltypes as $angeltype_id => $angeltype_name) {
$angel_types_spinner .= form_spinner(
'angeltype_count_' . $angeltype_id,
- $angeltype_name,
- $needed_angel_types[$angeltype_id]
+ htmlspecialchars($angeltype_name),
+ $needed_angel_types[$angeltype_id],
+ [],
+ ScheduleShift::whereShiftId($shift->id)->first() ? true : false,
);
}
+ $link = button(url('/shifts', ['action' => 'view', 'shift_id' => $shift_id]), icon('chevron-left'), 'btn-sm', '', __('general.back'));
return page_with_title(
- shifts_title(),
+ $link . ' ' . shifts_title(),
[
msg(),
'',
form([
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
- form_text('title', __('Title'), $title),
- form_select('rid', __('Room:'), $rooms, $rid),
+ form_text('title', __('title.title'), $title),
+ form_select('rid', __('Location:'), $locations, $rid),
form_text('start', __('Start:'), $start->format('Y-m-d H:i')),
form_text('end', __('End:'), $end->format('Y-m-d H:i')),
form_textarea('description', __('Additional description'), $description),
- form_info('', __('This description is for single shifts, otherwise please use the description in shift type.')),
+ form_info(
+ '',
+ __('This description is for single shifts, otherwise please use the description in shift type.')
+ ),
'
' . __('Needed angels') . '
',
$angel_types_spinner,
- form_submit('submit', __('Save')),
+ form_submit('submit', icon('save') . __('form.save')),
]),
]
);
@@ -230,18 +239,18 @@ function shift_delete_controller()
$request = request();
if (!auth()->can('user_shifts_admin')) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
// Schicht komplett lΓΆschen (nur fΓΌr admins/user mit user_shifts_admin privileg)
if (!$request->has('delete_shift') || !preg_match('/^\d+$/', $request->input('delete_shift'))) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
$shift_id = $request->input('delete_shift');
$shift = Shift($shift_id);
if (empty($shift)) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
// Schicht lΓΆschen bestΓ€tigt
@@ -254,7 +263,7 @@ function shift_delete_controller()
'name' => $shift->shiftType->name,
'title' => $shift->title,
'type' => $entry->angelType->name,
- 'room' => $shift->room,
+ 'location' => $shift->location,
'freeloaded' => $entry->freeloaded,
]);
}
@@ -267,21 +276,25 @@ function shift_delete_controller()
. ' to ' . $shift->end->format('Y-m-d H:i')
);
success(__('Shift deleted.'));
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
- return page_with_title(shifts_title(), [
- error(sprintf(
- __('Do you want to delete the shift %s from %s to %s?'),
- $shift->shiftType->name,
- $shift->start->format(__('Y-m-d H:i')),
- $shift->end->format(__('H:i'))
- ), true),
- form([
- form_hidden('delete_shift', $shift->id),
- form_submit('delete', __('delete')),
- ]),
- ]);
+ $link = button(url('/shifts', ['action' => 'view', 'shift_id' => $shift_id]), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title(
+ $link . ' ' . shifts_title(),
+ [
+ error(sprintf(
+ __('Do you want to delete the shift %s from %s to %s?'),
+ $shift->shiftType->name,
+ $shift->start->format(__('general.datetime')),
+ $shift->end->format(__('H:i'))
+ ), true),
+ form([
+ form_hidden('delete_shift', $shift->id),
+ form_submit('delete', icon('trash') . __('form.delete'), '', true, 'danger'),
+ ]),
+ ]
+ );
}
/**
@@ -293,21 +306,21 @@ function shift_controller()
$request = request();
if (!auth()->can('user_shifts')) {
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
if (!$request->has('shift_id')) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
$shift = Shift($request->input('shift_id'));
if (empty($shift)) {
error(__('Shift could not be found.'));
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
$shifttype = $shift->shiftType;
- $room = $shift->room;
+ $location = $shift->location;
/** @var AngelType[] $angeltypes */
$angeltypes = AngelType::all();
$user_shifts = Shifts_by_user($user->id);
@@ -338,8 +351,8 @@ function shift_controller()
}
return [
- $shift->shiftType->name,
- Shift_view($shift, $shifttype, $room, $angeltypes, $shift_signup_state),
+ htmlspecialchars($shift->shiftType->name),
+ Shift_view($shift, $shifttype, $location, $angeltypes, $shift_signup_state),
];
}
@@ -350,13 +363,13 @@ function shifts_controller()
{
$request = request();
if (!$request->has('action')) {
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
return match ($request->input('action')) {
'view' => shift_controller(),
'next' => shift_next_controller(), // throws redirect
- default => throw_redirect(page_link_to('/')),
+ default => throw_redirect(url('/')),
};
}
@@ -366,7 +379,7 @@ function shifts_controller()
function shift_next_controller()
{
if (!auth()->can('user_shifts')) {
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
$upcoming_shifts = ShiftEntries_upcoming_for_user(auth()->user());
@@ -375,5 +388,5 @@ function shift_next_controller()
throw_redirect(shift_link($upcoming_shifts[0]->shift));
}
- throw_redirect(page_link_to('user_shifts'));
+ throw_redirect(url('/user-shifts'));
}
diff --git a/includes/controller/shifttypes_controller.php b/includes/controller/shifttypes_controller.php
deleted file mode 100644
index 800034fce..000000000
--- a/includes/controller/shifttypes_controller.php
+++ /dev/null
@@ -1,163 +0,0 @@
- 'view', 'shifttype_id' => $shifttype->id]);
-}
-
-/**
- * Delete a shifttype.
- *
- * @return array
- */
-function shifttype_delete_controller()
-{
- $request = request();
- if (!$request->has('shifttype_id')) {
- throw_redirect(page_link_to('shifttypes'));
- }
-
- $shifttype = ShiftType::findOrFail($request->input('shifttype_id'));
- if ($request->hasPostData('delete')) {
- engelsystem_log('Deleted shifttype ' . $shifttype->name);
- success(sprintf(__('Shifttype %s deleted.'), $shifttype->name));
-
- $shifttype->delete();
- throw_redirect(page_link_to('shifttypes'));
- }
-
- return [
- sprintf(__('Delete shifttype %s'), $shifttype->name),
- ShiftType_delete_view($shifttype),
- ];
-}
-
-/**
- * Edit or create shift type.
- *
- * @return array
- */
-function shifttype_edit_controller()
-{
- $shifttype_id = null;
- $name = '';
- $description = '';
-
- $request = request();
-
- if ($request->has('shifttype_id')) {
- $shifttype = ShiftType::findOrFail($request->input('shifttype_id'));
- $shifttype_id = $shifttype->id;
- $name = $shifttype->name;
- $description = $shifttype->description;
- }
-
- if ($request->hasPostData('submit')) {
- $valid = true;
-
- if ($request->has('name') && $request->input('name') != '') {
- $name = strip_request_item('name');
- } else {
- $valid = false;
- error(__('Please enter a name.'));
- }
-
- if ($request->has('description')) {
- $description = strip_request_item_nl('description');
- }
-
- if ($valid) {
- $shiftType = ShiftType::findOrNew($shifttype_id);
- $shiftType->name = $name;
- $shiftType->description = $description;
- $shiftType->save();
-
- if ($shifttype_id) {
- engelsystem_log('Updated shifttype ' . $name);
- success(__('Updated shifttype.'));
- } else {
- $shifttype_id = $shiftType->id;
-
- engelsystem_log('Created shifttype ' . $name);
- success(__('Created shifttype.'));
- }
-
- throw_redirect(page_link_to('shifttypes', ['action' => 'view', 'shifttype_id' => $shifttype_id]));
- }
- }
-
- return [
- shifttypes_title(),
- ShiftType_edit_view($name, $description, $shifttype_id),
- ];
-}
-
-/**
- * @return array
- */
-function shifttype_controller()
-{
- $request = request();
- if (!$request->has('shifttype_id')) {
- throw_redirect(page_link_to('shifttypes'));
- }
- $shifttype = ShiftType::findOrFail($request->input('shifttype_id'));
-
- return [
- $shifttype->name,
- ShiftType_view($shifttype),
- ];
-}
-
-/**
- * List all shift types.
- *
- * @return array
- */
-function shifttypes_list_controller()
-{
- $shifttypes = ShiftType::all();
-
- return [
- shifttypes_title(),
- ShiftTypes_list_view($shifttypes),
- ];
-}
-
-/**
- * Text for shift type related links.
- *
- * @return string
- */
-function shifttypes_title()
-{
- return __('Shifttypes');
-}
-
-/**
- * Route shift type actions
- *
- * @return array
- */
-function shifttypes_controller()
-{
- $request = request();
- $action = 'list';
- if ($request->has('action')) {
- $action = $request->input('action');
- }
-
- return match ($action) {
- 'view' => shifttype_controller(),
- 'edit' => shifttype_edit_controller(),
- 'delete' => shifttype_delete_controller(),
- 'list' => shifttypes_list_controller(),
- default => shifttypes_list_controller(),
- };
-}
diff --git a/includes/controller/user_angeltypes_controller.php b/includes/controller/user_angeltypes_controller.php
index d0ab2499f..d37398681 100644
--- a/includes/controller/user_angeltypes_controller.php
+++ b/includes/controller/user_angeltypes_controller.php
@@ -5,8 +5,6 @@
use Engelsystem\Models\User\User;
use Engelsystem\Models\UserAngelType;
use Illuminate\Database\Eloquent\Collection;
-use Psr\Log\LoggerInterface;
-use Symfony\Component\Mailer\Exception\TransportException;
/**
* Display a hint for team/angeltype supporters if there are unconfirmed users for his angeltype.
@@ -37,9 +35,9 @@ function user_angeltypes_unconfirmed_hint()
$unconfirmed_links = [];
foreach ($unconfirmed_user_angeltypes as $user_angeltype) {
- $unconfirmed_links[] = '' . $user_angeltype->angelType->name
+ $unconfirmed_links[] = '' . htmlspecialchars($user_angeltype->angelType->name)
. ' (+' . $user_angeltype->count . ')'
. '';
}
@@ -67,13 +65,13 @@ function user_angeltypes_delete_all_controller(): array
if (!$request->has('angeltype_id')) {
error(__('Angeltype doesn\'t exist.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
if (!auth()->user()->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
error(__('You are not allowed to delete all users for this angeltype.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
if ($request->hasPostData('deny_all')) {
@@ -83,7 +81,7 @@ function user_angeltypes_delete_all_controller(): array
engelsystem_log(sprintf('Denied all users for angeltype %s', AngelType_name_render($angeltype, true)));
success(sprintf(__('Denied all users for angeltype %s.'), $angeltype->name));
- throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
+ throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
}
return [
@@ -104,13 +102,13 @@ function user_angeltypes_confirm_all_controller(): array
if (!$request->has('angeltype_id')) {
error(__('Angeltype doesn\'t exist.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
$angeltype = AngelType::findOrFail($request->input('angeltype_id'));
if (!auth()->can('admin_user_angeltypes') && !$user->isAngelTypeSupporter($angeltype)) {
error(__('You are not allowed to confirm all users for this angeltype.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
if ($request->hasPostData('confirm_all')) {
@@ -127,7 +125,7 @@ function user_angeltypes_confirm_all_controller(): array
user_angeltype_confirm_email($user, $angeltype);
}
- throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
+ throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
}
return [
@@ -148,7 +146,7 @@ function user_angeltype_confirm_controller(): array
if (!$request->has('user_angeltype_id')) {
error(__('User angeltype doesn\'t exist.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
/** @var UserAngelType $user_angeltype */
@@ -156,7 +154,7 @@ function user_angeltype_confirm_controller(): array
$angeltype = $user_angeltype->angelType;
if (!$user->isAngelTypeSupporter($angeltype) && !auth()->can('admin_user_angeltypes')) {
error(__('You are not allowed to confirm this users angeltype.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
$user_source = $user_angeltype->user;
@@ -173,7 +171,7 @@ function user_angeltype_confirm_controller(): array
user_angeltype_confirm_email($user_source, $angeltype);
- throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
+ throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
}
return [
@@ -188,23 +186,14 @@ function user_angeltype_confirm_email(User $user, AngelType $angeltype): void
return;
}
- try {
- /** @var EngelsystemMailer $mailer */
- $mailer = app(EngelsystemMailer::class);
- $mailer->sendViewTranslated(
- $user,
- 'notification.angeltype.confirmed',
- 'emails/angeltype-confirmed',
- ['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
- );
- } catch (TransportException $e) {
- /** @var LoggerInterface $logger */
- $logger = app('logger');
- $logger->error(
- 'Unable to send email "{title}" to user {user} with {exception}',
- ['title' => __('notification.angeltype.confirmed'), 'user' => $user->name, 'exception' => $e]
- );
- }
+ /** @var EngelsystemMailer $mailer */
+ $mailer = app(EngelsystemMailer::class);
+ $mailer->sendViewTranslated(
+ $user,
+ 'notification.angeltype.confirmed',
+ 'emails/angeltype-confirmed',
+ ['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
+ );
}
function user_angeltype_add_email(User $user, AngelType $angeltype): void
@@ -213,23 +202,14 @@ function user_angeltype_add_email(User $user, AngelType $angeltype): void
return;
}
- try {
- /** @var EngelsystemMailer $mailer */
- $mailer = app(EngelsystemMailer::class);
- $mailer->sendViewTranslated(
- $user,
- 'notification.angeltype.added',
- 'emails/angeltype-added',
- ['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
- );
- } catch (TransportException $e) {
- /** @var LoggerInterface $logger */
- $logger = app('logger');
- $logger->error(
- 'Unable to send email "{title}" to user {user} with {exception}',
- ['title' => __('notification.angeltype.added'), 'user' => $user->name, 'exception' => $e]
- );
- }
+ /** @var EngelsystemMailer $mailer */
+ $mailer = app(EngelsystemMailer::class);
+ $mailer->sendViewTranslated(
+ $user,
+ 'notification.angeltype.added',
+ 'emails/angeltype-added',
+ ['name' => $angeltype->name, 'angeltype' => $angeltype, 'username' => $user->displayName]
+ );
}
/**
@@ -244,7 +224,7 @@ function user_angeltype_delete_controller(): array
if (!$request->has('user_angeltype_id')) {
error(__('User angeltype doesn\'t exist.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
/** @var UserAngelType $user_angeltype */
@@ -257,7 +237,7 @@ function user_angeltype_delete_controller(): array
&& !auth()->can('admin_user_angeltypes')
) {
error(__('You are not allowed to delete this users angeltype.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
if ($request->hasPostData('delete')) {
@@ -266,7 +246,7 @@ function user_angeltype_delete_controller(): array
engelsystem_log(sprintf('User %s removed from %s.', User_Nick_render($user_source, true), $angeltype->name));
success(sprintf(__('User %s removed from %s.'), $user_source->displayName, $angeltype->name));
- throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
+ throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
}
return [
@@ -287,19 +267,19 @@ function user_angeltype_update_controller(): array
if (!auth()->can('admin_angel_types')) {
error(__('You are not allowed to set supporter rights.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
if (!$request->has('user_angeltype_id')) {
error(__('User angeltype doesn\'t exist.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
if ($request->has('supporter') && preg_match('/^[01]$/', $request->input('supporter'))) {
$supporter = $request->input('supporter') == '1';
} else {
error(__('No supporter update given.'));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
/** @var UserAngelType $user_angeltype */
@@ -321,7 +301,7 @@ function user_angeltype_update_controller(): array
));
success(sprintf($msg, $angeltype->name, $user_source->displayName));
- throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
+ throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
}
return [
@@ -382,7 +362,7 @@ function user_angeltype_add_controller(): array
user_angeltype_add_email($user_source, $angeltype);
- throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
+ throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
}
}
@@ -406,7 +386,7 @@ function user_angeltype_join_controller(AngelType $angeltype)
$user_angeltype = UserAngelType::whereUserId($user->id)->where('angel_type_id', $angeltype->id)->first();
if (!empty($user_angeltype)) {
error(sprintf(__('You are already a %s.'), $angeltype->name));
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
$request = request();
@@ -434,11 +414,11 @@ function user_angeltype_join_controller(AngelType $angeltype)
));
}
- throw_redirect(page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
+ throw_redirect(url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]));
}
return [
- sprintf(__('Become a %s'), $angeltype->name),
+ sprintf(__('Become a %s'), htmlspecialchars($angeltype->name)),
UserAngelType_join_view($user, $angeltype),
];
}
@@ -452,7 +432,7 @@ function user_angeltypes_controller(): array
{
$request = request();
if (!$request->has('action')) {
- throw_redirect(page_link_to('angeltypes'));
+ throw_redirect(url('/angeltypes'));
}
return match ($request->input('action')) {
@@ -462,6 +442,6 @@ function user_angeltypes_controller(): array
'delete' => user_angeltype_delete_controller(),
'update' => user_angeltype_update_controller(),
'add' => user_angeltype_add_controller(),
- default => throw_redirect(page_link_to('angeltyps')),
+ default => throw_redirect(url('/angeltyps')),
};
}
diff --git a/includes/controller/user_driver_licenses_controller.php b/includes/controller/user_driver_licenses_controller.php
deleted file mode 100644
index d19776561..000000000
--- a/includes/controller/user_driver_licenses_controller.php
+++ /dev/null
@@ -1,143 +0,0 @@
-user();
-
- // User has already entered data, no hint needed.
- if ($user->license->wantsToDrive()) {
- return null;
- }
-
- $angeltypes = $user->userAngelTypes;
- foreach ($angeltypes as $angeltype) {
- if ($angeltype->requires_driver_license) {
- return sprintf(
- __('You joined an angeltype which requires a driving license. Please edit your driving license information here: %s.'),
- '' . __('driving license information') . ''
- );
- }
- }
-
- return null;
-}
-
-/**
- * Route user driver licenses actions.
- *
- * @return array
- */
-function user_driver_licenses_controller()
-{
- $user = auth()->user();
-
- if (!$user) {
- throw_redirect(page_link_to());
- }
-
- $action = strip_request_item('action', 'edit');
-
- return match ($action) {
- 'edit' => user_driver_license_edit_controller(),
- default => user_driver_license_edit_controller(),
- };
-}
-
-/**
- * Link to user driver license edit page for given user.
- *
- * @param User $user
- * @return string
- */
-function user_driver_license_edit_link($user = null)
-{
- if (!$user) {
- return page_link_to('user_driver_licenses');
- }
-
- return page_link_to('user_driver_licenses', ['user_id' => $user->id]);
-}
-
-/**
- * Loads the user for the driver license.
- *
- * @return User
- */
-function user_driver_license_load_user()
-{
- $request = request();
- $user_source = auth()->user();
-
- if ($request->has('user_id')) {
- $user_source = User::find($request->input('user_id'));
- if (empty($user_source)) {
- throw_redirect(user_driver_license_edit_link());
- }
- }
-
- return $user_source;
-}
-
-/**
- * Edit a users driver license information.
- *
- * @return array
- */
-function user_driver_license_edit_controller()
-{
- $user = auth()->user();
- $request = request();
- $user_source = user_driver_license_load_user();
-
- // only privilege admin_user can edit other users driver license information
- if ($user->id != $user_source->id && !auth()->can('admin_user')) {
- throw_redirect(user_driver_license_edit_link());
- }
-
- $driverLicense = $user_source->license;
- if ($request->hasPostData('submit')) {
- if ($request->has('wants_to_drive')) {
- $driverLicense->has_car = $request->has('has_car');
- $driverLicense->drive_car = $request->has('has_license_car');
- $driverLicense->drive_3_5t = $request->has('has_license_3_5t_transporter');
- $driverLicense->drive_7_5t = $request->has('has_license_7_5t_truck');
- $driverLicense->drive_12t = $request->has('has_license_12t_truck');
- $driverLicense->drive_forklift = $request->has('has_license_forklift');
-
- if ($driverLicense->wantsToDrive()) {
- $driverLicense->save();
-
- engelsystem_log('Driver license information updated.');
- success(__('Your driver license information has been saved.'));
- throw_redirect(user_link($user_source->id));
- } else {
- error(__('Please select at least one driving license.'));
- }
- } else {
- $driverLicense->has_car = false;
- $driverLicense->drive_car = false;
- $driverLicense->drive_3_5t = false;
- $driverLicense->drive_7_5t = false;
- $driverLicense->drive_12t = false;
- $driverLicense->drive_forklift = false;
- $driverLicense->save();
-
- engelsystem_log('Driver license information removed.');
- success(__('Your driver license information has been removed.'));
- throw_redirect(user_link($user_source->id));
- }
- }
-
- return [
- sprintf(__('Edit %s driving license information'), $user_source->displayName),
- UserDriverLicense_edit_view($user_source, $driverLicense),
- ];
-}
diff --git a/includes/controller/users_controller.php b/includes/controller/users_controller.php
index 5ed7a7e6e..91b311143 100644
--- a/includes/controller/users_controller.php
+++ b/includes/controller/users_controller.php
@@ -7,6 +7,7 @@
use Engelsystem\ShiftCalendarRenderer;
use Engelsystem\ShiftsFilter;
use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
/**
@@ -20,7 +21,7 @@ function users_controller()
$request = request();
if (!$user) {
- throw_redirect(page_link_to());
+ throw_redirect(url('/'));
}
$action = 'list';
@@ -55,7 +56,7 @@ function user_delete_controller()
}
if (!auth()->can('admin_user')) {
- throw_redirect(page_link_to());
+ throw_redirect(url('/'));
}
// You cannot delete yourself
@@ -91,7 +92,7 @@ function user_delete_controller()
}
return [
- sprintf(__('Delete %s'), $user_source->displayName),
+ sprintf(__('Delete %s'), htmlspecialchars($user_source->displayName)),
User_delete_view($user_source),
];
}
@@ -101,7 +102,7 @@ function user_delete_controller()
*/
function users_link()
{
- return page_link_to('users');
+ return url('/users');
}
/**
@@ -110,7 +111,7 @@ function users_link()
*/
function user_edit_link($userId)
{
- return page_link_to('admin_user', ['user_id' => $userId]);
+ return url('/admin-user', ['user_id' => $userId]);
}
/**
@@ -119,7 +120,7 @@ function user_edit_link($userId)
*/
function user_delete_link($userId)
{
- return page_link_to('users', ['action' => 'delete', 'user_id' => $userId]);
+ return url('/users', ['action' => 'delete', 'user_id' => $userId]);
}
/**
@@ -128,7 +129,7 @@ function user_delete_link($userId)
*/
function user_link($userId)
{
- return page_link_to('users', ['action' => 'view', 'user_id' => $userId]);
+ return url('/users', ['action' => 'view', 'user_id' => $userId]);
}
/**
@@ -149,7 +150,7 @@ function user_edit_vouchers_controller()
(!auth()->can('admin_user') && !auth()->can('voucher.edit'))
|| !config('enable_voucher')
) {
- throw_redirect(page_link_to());
+ throw_redirect(url('/'));
}
if ($request->hasPostData('submit')) {
@@ -182,7 +183,7 @@ function user_edit_vouchers_controller()
}
return [
- sprintf(__('%s\'s vouchers'), $user_source->displayName),
+ sprintf(__('%s\'s vouchers'), htmlspecialchars($user_source->displayName)),
User_edit_vouchers_view($user_source),
];
}
@@ -200,7 +201,7 @@ function user_controller()
$user_source = User::find($request->input('user_id'));
if (!$user_source) {
error(__('User not found.'));
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
}
@@ -234,7 +235,7 @@ function user_controller()
}
if (empty($user_source->api_key)) {
- User_reset_api_key($user_source, false);
+ auth()->resetApiKey($user_source);
}
if ($user_source->state->force_active) {
@@ -243,8 +244,12 @@ function user_controller()
$tshirt_score = sprintf('%.2f', User_tshirt_score($user_source->id)) . ' h';
}
+ $worklogs = $user_source->worklogs()
+ ->with(['user', 'creator'])
+ ->get();
+
return [
- $user_source->displayName,
+ htmlspecialchars($user_source->displayName),
User_view(
$user_source,
auth()->can('admin_user'),
@@ -256,7 +261,7 @@ function user_controller()
$tshirt_score,
auth()->can('admin_active'),
auth()->can('admin_user_worklog'),
- UserWorkLogsForUser($user_source->id)
+ $worklogs
),
];
}
@@ -271,7 +276,7 @@ function users_list_controller()
$request = request();
if (!auth()->can('admin_user')) {
- throw_redirect(page_link_to());
+ throw_redirect(url('/'));
}
$order_by = 'name';
@@ -297,13 +302,15 @@ function users_list_controller()
}
/** @var User[]|Collection $users */
- $users = User::with(['contact', 'personalData', 'state'])
+ $users = User::with(['contact', 'personalData', 'state', 'shiftEntries' => function (HasMany $query) {
+ $query->where('freeloaded', true);
+ }])
->orderBy('name')
->get();
foreach ($users as $user) {
$user->setAttribute(
'freeloads',
- $user->shiftEntries()
+ $user->shiftEntries
->where('freeloaded', true)
->count()
);
@@ -343,13 +350,13 @@ function load_user()
{
$request = request();
if (!$request->has('user_id')) {
- throw_redirect(page_link_to());
+ throw_redirect(url('/'));
}
$user = User::find($request->input('user_id'));
if (!$user) {
error(__('User doesn\'t exist.'));
- throw_redirect(page_link_to());
+ throw_redirect(url('/'));
}
return $user;
@@ -437,3 +444,57 @@ function shiftCalendarRendererByShiftFilter(ShiftsFilter $shiftsFilter)
return new ShiftCalendarRenderer($filtered_shifts, $needed_angeltypes, $shift_entries, $shiftsFilter);
}
+
+/**
+ * Generates a hint, if user joined angeltypes that require a driving license and the user has no driver license
+ * information provided.
+ *
+ * @return string|null
+ */
+function user_driver_license_required_hint()
+{
+ $user = auth()->user();
+
+ // User has already entered data, no hint needed.
+ if ($user->license->wantsToDrive()) {
+ return null;
+ }
+
+ $angeltypes = $user->userAngelTypes;
+ foreach ($angeltypes as $angeltype) {
+ if ($angeltype->requires_driver_license) {
+ return sprintf(
+ __('angeltype.driving_license.required.info.here'),
+ '' . __('driving_license.info') . ''
+ );
+ }
+ }
+
+ return null;
+}
+
+function user_ifsg_certificate_required_hint()
+{
+ $user = auth()->user();
+
+ // User has already entered data, no hint needed.
+ if (!config('ifsg_enabled') || $user->license->ifsg_light || $user->license->ifsg) {
+ return null;
+ }
+
+ $angeltypes = $user->userAngelTypes;
+ foreach ($angeltypes as $angeltype) {
+ if (
+ $angeltype->requires_ifsg_certificate && !(
+ $user->license->ifsg_certificate || $user->license->ifsg_certificate_light
+ )
+ ) {
+ return sprintf(
+ __('angeltype.ifsg.required.info.here'),
+ '' . __('ifsg.info') . ''
+ );
+ }
+ }
+
+ return null;
+}
diff --git a/includes/engelsystem.php b/includes/engelsystem.php
index b156c68a7..0c368dc81 100644
--- a/includes/engelsystem.php
+++ b/includes/engelsystem.php
@@ -23,7 +23,7 @@
http_response_code(503);
$url = $app->get(UrlGeneratorInterface::class);
$maintenance = file_get_contents(__DIR__ . '/../resources/views/layouts/maintenance.html');
- $maintenance = str_replace('%APP_NAME%', $app->get('config')->get('app_name'), $maintenance);
+ $maintenance = str_replace('%APP_NAME%', htmlspecialchars($app->get('config')->get('app_name')), $maintenance);
$maintenance = str_replace('%ASSETS_PATH%', $url->to(''), $maintenance);
echo $maintenance;
die();
diff --git a/includes/helper/email_helper.php b/includes/helper/email_helper.php
index fb3401077..b5ef0186e 100644
--- a/includes/helper/email_helper.php
+++ b/includes/helper/email_helper.php
@@ -1,9 +1,7 @@
get('translator');
- $locale = $translator->getLocale();
-
- $status = true;
- try {
- /** @var EngelsystemMailer $mailer */
- $mailer = app('mailer');
-
- $translator->setLocale($recipientUser->settings->language);
- $mailer->sendView(
- $recipientUser->contact->email ?: $recipientUser->email,
- $title,
- 'emails/mail',
- ['username' => $recipientUser->displayName, 'message' => $message]
- );
- } catch (Exception $e) {
- $status = false;
- engelsystem_log(sprintf(
- 'An exception occurred while sending a mail to %s in %s:%u: %s',
- $recipientUser->name,
- $e->getFile(),
- $e->getLine(),
- $e->getMessage()
- ), LogLevel::CRITICAL);
- }
-
- $translator->setLocale($locale);
+ /** @var EngelsystemMailer $mailer */
+ $mailer = app('mailer');
+ $status = $mailer->sendViewTranslated(
+ $recipientUser,
+ $title,
+ 'emails/mail',
+ ['username' => $recipientUser->displayName, 'message' => $message]
+ );
if (!$status) {
- error(sprintf(__('User %s could not be notified by email due to an error.'), $recipientUser->displayName));
- engelsystem_log(sprintf('User %s could not be notified by email due to an error.', $recipientUser->name));
+ error(sprintf(__('User %s could not be notified by e-mail due to an error.'), $recipientUser->displayName));
+ engelsystem_log(sprintf('User %s could not be notified by e-mail due to an error.', $recipientUser->name));
}
return $status;
diff --git a/includes/helper/legacy_helper.php b/includes/helper/legacy_helper.php
index 8cfeb5c47..220a6268d 100644
--- a/includes/helper/legacy_helper.php
+++ b/includes/helper/legacy_helper.php
@@ -3,6 +3,8 @@
declare(strict_types=1);
use Engelsystem\Renderer\Twig\Extensions\Globals;
+use Engelsystem\Helpers\Carbon;
+use Engelsystem\Helpers\DayOfEvent;
function theme_id(): int
{
@@ -25,3 +27,16 @@ function theme_type(): string
{
return theme()['type'];
}
+
+function dateWithEventDay(string $day): string
+{
+ $date = Carbon::createFromFormat('Y-m-d', $day);
+ $dayOfEvent = DayOfEvent::get($date);
+ $dateFormatted = $date->format(__('general.date'));
+
+ if (!config('enable_show_day_of_event') || is_null($dayOfEvent)) {
+ return $dateFormatted;
+ }
+
+ return $dateFormatted . ' (' . $dayOfEvent . ')';
+}
diff --git a/includes/helper/message_helper.php b/includes/helper/message_helper.php
index 13526a630..d550fd44a 100644
--- a/includes/helper/message_helper.php
+++ b/includes/helper/message_helper.php
@@ -17,11 +17,12 @@ function msg()
*
* @param string $msg
* @param bool $immediately
+ * @param bool $immediatelyRaw
* @return string
*/
-function info($msg, $immediately = false)
+function info($msg, $immediately = false, $immediatelyRaw = false)
{
- return alert(NotificationType::INFORMATION, $msg, $immediately);
+ return alert(NotificationType::INFORMATION, $msg, $immediately, $immediatelyRaw);
}
/**
@@ -29,11 +30,12 @@ function info($msg, $immediately = false)
*
* @param string $msg
* @param bool $immediately
+ * @param bool $immediatelyRaw
* @return string
*/
-function warning($msg, $immediately = false)
+function warning($msg, $immediately = false, $immediatelyRaw = false)
{
- return alert(NotificationType::WARNING, $msg, $immediately);
+ return alert(NotificationType::WARNING, $msg, $immediately, $immediatelyRaw);
}
/**
@@ -41,11 +43,12 @@ function warning($msg, $immediately = false)
*
* @param string $msg
* @param bool $immediately
+ * @param bool $immediatelyRaw
* @return string
*/
-function error($msg, $immediately = false)
+function error($msg, $immediately = false, $immediatelyRaw = false)
{
- return alert(NotificationType::ERROR, $msg, $immediately);
+ return alert(NotificationType::ERROR, $msg, $immediately, $immediatelyRaw);
}
/**
@@ -53,24 +56,27 @@ function error($msg, $immediately = false)
*
* @param string $msg
* @param bool $immediately
+ * @param bool $immediatelyRaw
* @return string
*/
-function success($msg, $immediately = false)
+function success($msg, $immediately = false, $immediatelyRaw = false)
{
- return alert(NotificationType::MESSAGE, $msg, $immediately);
+ return alert(NotificationType::MESSAGE, $msg, $immediately, $immediatelyRaw);
}
/**
* Renders an alert message with the given alert-* class or sets it in session
*
- * @see \Engelsystem\Controllers\HasUserNotifications
- *
* @param NotificationType $type
* @param string $msg
* @param bool $immediately
+ * @param bool $immediatelyRaw
* @return string
+ *
+ * @see \Engelsystem\Controllers\HasUserNotifications
+ *
*/
-function alert(NotificationType $type, $msg, $immediately = false)
+function alert(NotificationType $type, $msg, $immediately = false, $immediatelyRaw = false)
{
if (empty($msg)) {
return '';
@@ -87,6 +93,7 @@ function alert(NotificationType $type, $msg, $immediately = false)
['danger', 'warning', 'info', 'success'],
$type->value
);
+ $msg = $immediatelyRaw ? $msg : htmlspecialchars($msg);
return '' . $msg . '
';
}
diff --git a/includes/helper/shift_helper.php b/includes/helper/shift_helper.php
index e6edb6141..fd27f70bb 100644
--- a/includes/helper/shift_helper.php
+++ b/includes/helper/shift_helper.php
@@ -5,11 +5,13 @@
use Carbon\Carbon;
use Engelsystem\Helpers\Shifts;
use Engelsystem\Mail\EngelsystemMailer;
-use Engelsystem\Models\Room;
+use Engelsystem\Models\Location;
+use Engelsystem\Models\Shifts\Shift as ShiftModel;
+use Engelsystem\Models\Shifts\ShiftEntry;
use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
+use Illuminate\Database\Eloquent\Collection;
use Psr\Log\LoggerInterface;
-use Symfony\Component\Mailer\Exception\TransportException;
class Shift
{
@@ -26,7 +28,7 @@ public function deletedEntryCreateWorklog(
string $name,
string $title,
string $type,
- Room $room,
+ Location $location,
bool $freeloaded
): void {
if ($freeloaded || $start > Carbon::now()) {
@@ -45,9 +47,9 @@ public function deletedEntryCreateWorklog(
$name,
$title,
$type,
- $room->name,
- $start->format(__('Y-m-d H:i')),
- $end->format(__('Y-m-d H:i'))
+ $location->name,
+ $start->format(__('general.datetime')),
+ $end->format(__('general.datetime'))
);
$workLog->save();
@@ -64,34 +66,70 @@ public function deletedEntrySendEmail(
string $name,
string $title,
string $type,
- Room $room,
+ Location $location,
bool $freeloaded
): void {
if (!$user->settings->email_shiftinfo) {
return;
}
- $subject = 'notification.shift.deleted';
- try {
+ $this->mailer->sendViewTranslated(
+ $user,
+ 'notification.shift.deleted',
+ 'emails/worklog-from-shift',
+ [
+ 'name' => $name,
+ 'title' => $title,
+ 'start' => $start,
+ 'end' => $end,
+ 'location' => $location,
+ 'freeloaded' => $freeloaded,
+ 'username' => $user->displayName,
+ ]
+ );
+ }
+
+ public function updatedShiftSendEmail(
+ ShiftModel $shift,
+ ShiftModel $oldShift
+ ): void {
+ // Only send e-mail on relevant changes
+ if (
+ $oldShift->shift_type_id == $shift->shift_type_id
+ && $oldShift->title == $shift->title
+ && $oldShift->start == $shift->start
+ && $oldShift->end == $shift->end
+ && $oldShift->location_id == $shift->location_id
+ ) {
+ return;
+ }
+
+ $shift->load(['shiftType', 'location']);
+ $oldShift->load(['shiftType', 'location']);
+ /** @var ShiftEntry[]|Collection $shiftEntries */
+ $shiftEntries = $shift->shiftEntries()
+ ->with(['angelType', 'user.settings'])
+ ->get();
+
+ foreach ($shiftEntries as $shiftEntry) {
+ $user = $shiftEntry->user;
+ $angelType = $shiftEntry->angelType;
+
+ if (!$user->settings->email_shiftinfo || $shift->end < Carbon::now()) {
+ continue;
+ }
+
$this->mailer->sendViewTranslated(
$user,
- $subject,
- 'emails/worklog-from-shift',
+ 'notification.shift.updated',
+ 'emails/updated-shift',
[
- 'name' => $name,
- 'title' => $title,
- 'start' => $start,
- 'end' => $end,
- 'room' => $room,
- 'freeloaded' => $freeloaded,
- 'username' => $user->displayName,
+ 'shift' => $shift,
+ 'oldShift' => $oldShift,
+ 'angelType' => $angelType,
+ 'username' => $user->displayName,
]
);
- } catch (TransportException $e) {
- $this->log->error(
- 'Unable to send email "{title}" to user {user} with {exception}',
- ['title' => $subject, 'user' => $user->name, 'exception' => $e]
- );
}
}
}
diff --git a/includes/includes.php b/includes/includes.php
index e16c4170d..d8df64f76 100644
--- a/includes/includes.php
+++ b/includes/includes.php
@@ -18,35 +18,30 @@
__DIR__ . '/../includes/model/ShiftSignupState.php',
__DIR__ . '/../includes/model/Stats.php',
__DIR__ . '/../includes/model/User_model.php',
- __DIR__ . '/../includes/model/UserWorkLog_model.php',
__DIR__ . '/../includes/model/ValidationResult.php',
__DIR__ . '/../includes/view/AngelTypes_view.php',
__DIR__ . '/../includes/view/EventConfig_view.php',
__DIR__ . '/../includes/view/PublicDashboard_view.php',
- __DIR__ . '/../includes/view/Rooms_view.php',
+ __DIR__ . '/../includes/view/Locations_view.php',
__DIR__ . '/../includes/view/ShiftCalendarLane.php',
__DIR__ . '/../includes/view/ShiftCalendarRenderer.php',
__DIR__ . '/../includes/view/ShiftCalendarShiftRenderer.php',
__DIR__ . '/../includes/view/ShiftsFilterRenderer.php',
__DIR__ . '/../includes/view/Shifts_view.php',
__DIR__ . '/../includes/view/ShiftEntry_view.php',
- __DIR__ . '/../includes/view/ShiftTypes_view.php',
__DIR__ . '/../includes/view/UserAngelTypes_view.php',
- __DIR__ . '/../includes/view/UserDriverLicenses_view.php',
__DIR__ . '/../includes/view/UserHintsRenderer.php',
__DIR__ . '/../includes/view/User_view.php',
__DIR__ . '/../includes/controller/angeltypes_controller.php',
__DIR__ . '/../includes/controller/event_config_controller.php',
__DIR__ . '/../includes/controller/public_dashboard_controller.php',
- __DIR__ . '/../includes/controller/rooms_controller.php',
+ __DIR__ . '/../includes/controller/locations_controller.php',
__DIR__ . '/../includes/controller/shift_entries_controller.php',
__DIR__ . '/../includes/controller/shifts_controller.php',
- __DIR__ . '/../includes/controller/shifttypes_controller.php',
__DIR__ . '/../includes/controller/users_controller.php',
__DIR__ . '/../includes/controller/user_angeltypes_controller.php',
- __DIR__ . '/../includes/controller/user_driver_licenses_controller.php',
__DIR__ . '/../includes/helper/legacy_helper.php',
__DIR__ . '/../includes/helper/message_helper.php',
@@ -62,7 +57,6 @@
__DIR__ . '/../includes/pages/admin_groups.php',
__DIR__ . '/../includes/pages/admin_shifts.php',
__DIR__ . '/../includes/pages/admin_user.php',
- __DIR__ . '/../includes/pages/guest_login.php',
__DIR__ . '/../includes/pages/user_myshifts.php',
__DIR__ . '/../includes/pages/user_shifts.php',
diff --git a/includes/mailer/shifts_mailer.php b/includes/mailer/shifts_mailer.php
index ce037e54e..5de920a36 100644
--- a/includes/mailer/shifts_mailer.php
+++ b/includes/mailer/shifts_mailer.php
@@ -1,87 +1,7 @@
shiftEntries()
- ->with(['user', 'user.settings'])
- ->get();
- $old_room = $old_shift->room;
- $new_room = $new_shift->room;
-
- $noticeable_changes = false;
-
- $message = __('A Shift you are registered on has changed:');
- $message .= "\n";
-
- if ($old_shift->shift_type_id != $new_shift->shift_type_id) {
- $message .= sprintf(
- __('* Shift type changed from %s to %s'),
- $old_shift->shiftType->name,
- $new_shift->shiftType->name
- ) . "\n";
- $noticeable_changes = true;
- }
-
- if ($old_shift->title != $new_shift->title) {
- $message .= sprintf(__('* Shift title changed from %s to %s'), $old_shift->title, $new_shift->title) . "\n";
- $noticeable_changes = true;
- }
-
- if ($old_shift->start->timestamp != $new_shift->start->timestamp) {
- $message .= sprintf(
- __('* Shift Start changed from %s to %s'),
- $old_shift->start->format(__('Y-m-d H:i')),
- $new_shift->start->format(__('Y-m-d H:i'))
- ) . "\n";
- $noticeable_changes = true;
- }
-
- if ($old_shift->end->timestamp != $new_shift->end->timestamp) {
- $message .= sprintf(
- __('* Shift End changed from %s to %s'),
- $old_shift->end->format(__('Y-m-d H:i')),
- $new_shift->end->format(__('Y-m-d H:i'))
- ) . "\n";
- $noticeable_changes = true;
- }
-
- if ($old_shift->room_id != $new_shift->room_id) {
- $message .= sprintf(__('* Shift Location changed from %s to %s'), $old_room->name, $new_room->name) . "\n";
- $noticeable_changes = true;
- }
-
- if (!$noticeable_changes) {
- // There are no changes worth sending an E-Mail
- return;
- }
-
- $message .= "\n";
- $message .= __('The updated Shift:') . "\n";
-
- $message .= $new_shift->shiftType->name . "\n";
- $message .= $new_shift->title . "\n";
- $message .= $new_shift->start->format(__('Y-m-d H:i')) . ' - ' . $new_shift->end->format(__('H:i')) . "\n";
- $message .= $new_room->name . "\n\n";
- $message .= url('/shifts', ['action' => 'view', 'shift_id' => $new_shift->id]) . "\n";
-
- foreach ($shiftEntries as $shiftEntry) {
- $user = $shiftEntry->user;
- if ($user->settings->email_shiftinfo) {
- engelsystem_email_to_user(
- $user,
- __('Your Shift has changed'),
- $message,
- true
- );
- }
- }
-}
function mail_shift_assign(User $user, Shift $shift)
{
@@ -89,13 +9,11 @@ function mail_shift_assign(User $user, Shift $shift)
return;
}
- $room = $shift->room;
-
$message = __('You have been assigned to a Shift:') . "\n";
$message .= $shift->shiftType->name . "\n";
$message .= $shift->title . "\n";
- $message .= $shift->start->format(__('Y-m-d H:i')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
- $message .= $room->name . "\n\n";
+ $message .= $shift->start->format(__('general.datetime')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
+ $message .= $shift->location->name . "\n\n";
$message .= url('/shifts', ['action' => 'view', 'shift_id' => $shift->id]) . "\n";
engelsystem_email_to_user($user, __('Assigned to Shift'), $message, true);
@@ -107,13 +25,11 @@ function mail_shift_removed(User $user, Shift $shift)
return;
}
- $room = $shift->room;
-
$message = __('You have been removed from a Shift:') . "\n";
$message .= $shift->shiftType->name . "\n";
$message .= $shift->title . "\n";
- $message .= $shift->start->format(__('Y-m-d H:i')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
- $message .= $room->name . "\n";
+ $message .= $shift->start->format(__('general.datetime')) . ' - ' . $shift->end->format(__('H:i')) . "\n";
+ $message .= $shift->location->name . "\n";
engelsystem_email_to_user($user, __('Removed from Shift'), $message, true);
}
diff --git a/includes/mailer/users_mailer.php b/includes/mailer/users_mailer.php
index 6135bcf7d..1438a5a9c 100644
--- a/includes/mailer/users_mailer.php
+++ b/includes/mailer/users_mailer.php
@@ -10,7 +10,7 @@ function mail_user_delete($user)
{
return engelsystem_email_to_user(
$user,
- __('Your account has been deleted'),
+ __('Your account has been deleted.'),
__(
'Your %s account has been deleted. If you have any questions regarding your account deletion, please contact heaven.',
[config('app_name')]
diff --git a/includes/model/NeededAngelTypes_model.php b/includes/model/NeededAngelTypes_model.php
index 9922b7eb7..c1edbaae3 100644
--- a/includes/model/NeededAngelTypes_model.php
+++ b/includes/model/NeededAngelTypes_model.php
@@ -1,47 +1,70 @@
schedule) {
+ $needed_angeltypes_source = Db::select(
+ '
SELECT
`needed_angel_types`.*,
- `angel_types`.`id`,
`angel_types`.`name`,
`angel_types`.`restricted`,
- `angel_types`.`no_self_signup`
+ `angel_types`.`shift_self_signup`
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
- WHERE `shift_id` = ?
- ORDER BY `room_id` DESC',
- [$shiftId]
- );
+ WHERE `needed_angel_types`.`shift_id` = ?
+ ORDER BY `location_id` DESC
+ ',
+ [$shift->id]
+ );
+ }
+
+ // Get needed by shift type
+ if ($shift->schedule && $shift->schedule->needed_from_shift_type) {
+ $needed_angeltypes_source = Db::select('
+ SELECT
+ `needed_angel_types`.*,
+ `angel_types`.`name`,
+ `angel_types`.`restricted`,
+ `angel_types`.`shift_self_signup`
+ FROM `needed_angel_types`
+ JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
+ WHERE `needed_angel_types`.`shift_type_id` = ?
+ ORDER BY `location_id` DESC
+ ', [$shift->shift_type_id]);
+ }
- // Use settings from room
- if (count($needed_angeltypes_source) == 0) {
+ // Load from room
+ if ($shift->schedule && !$shift->schedule->needed_from_shift_type) {
$needed_angeltypes_source = Db::select('
- SELECT `needed_angel_types`.*, `angel_types`.`name`, `angel_types`.`restricted`
+ SELECT
+ `needed_angel_types`.*,
+ `angel_types`.`name`,
+ `angel_types`.`restricted`,
+ `angel_types`.`shift_self_signup`
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id` = `needed_angel_types`.`angel_type_id`
- JOIN `shifts` ON `shifts`.`room_id` = `needed_angel_types`.`room_id`
- WHERE `shifts`.`id` = ?
- ORDER BY `room_id` DESC
- ', [$shiftId]);
+ WHERE `needed_angel_types`.`location_id` = ?
+ ORDER BY `location_id` DESC
+ ', [$shift->location_id]);
}
/** @var ShiftEntry[]|Collection $shift_entries */
$shift_entries = ShiftEntry::with('user', 'angelType')
- ->where('shift_id', $shiftId)
+ ->where('shift_id', $shift->id)
->get();
$needed_angeltypes = [];
foreach ($needed_angeltypes_source as $angeltype) {
diff --git a/includes/model/ShiftEntry_model.php b/includes/model/ShiftEntry_model.php
index 21ec09210..3f8dd3b57 100644
--- a/includes/model/ShiftEntry_model.php
+++ b/includes/model/ShiftEntry_model.php
@@ -15,7 +15,7 @@ function ShiftEntry_onCreate(ShiftEntry $shiftEntry): void
'User ' . User_Nick_render($shiftEntry->user, true)
. ' signed up for shift ' . $shiftEntry->shift->title
. ' (' . $shift->shiftType->name . ')'
- . ' at ' . $shift->room->name
+ . ' at ' . $shift->location->name
. ' from ' . $shift->start->format('Y-m-d H:i')
. ' to ' . $shift->end->format('Y-m-d H:i')
. ' as ' . $shiftEntry->angelType->name
@@ -33,14 +33,14 @@ function ShiftEntry_onDelete(ShiftEntry $shiftEntry)
$signout_user = $shiftEntry->user;
$shift = Shift($shiftEntry->shift);
$shifttype = $shift->shiftType;
- $room = $shift->room;
+ $location = $shift->location;
$angeltype = $shiftEntry->angelType;
engelsystem_log(
'Shift signout: ' . User_Nick_render($signout_user, true)
. ' from shift ' . $shift->title
. ' (' . $shifttype->name . ')'
- . ' at ' . $room->name
+ . ' at ' . $location->name
. ' from ' . $shift->start->format('Y-m-d H:i')
. ' to ' . $shift->end->format('Y-m-d H:i')
. ' as ' . $angeltype->name
diff --git a/includes/model/ShiftsFilter.php b/includes/model/ShiftsFilter.php
index bb75ed7e3..59fc56aa0 100644
--- a/includes/model/ShiftsFilter.php
+++ b/includes/model/ShiftsFilter.php
@@ -44,10 +44,10 @@ class ShiftsFilter
* ShiftsFilter constructor.
*
* @param bool $user_shifts_admin
- * @param int[] $rooms
+ * @param int[] $locations
* @param int[] $angelTypes
*/
- public function __construct($user_shifts_admin = false, private $rooms = [], $angelTypes = [])
+ public function __construct($user_shifts_admin = false, private $locations = [], $angelTypes = [])
{
$this->types = $angelTypes;
@@ -68,7 +68,7 @@ public function sessionExport()
return [
'userShiftsAdmin' => $this->userShiftsAdmin,
'filled' => $this->filled,
- 'rooms' => $this->rooms,
+ 'locations' => $this->locations,
'types' => $this->types,
'startTime' => $this->startTime,
'endTime' => $this->endTime,
@@ -80,12 +80,12 @@ public function sessionExport()
*/
public function sessionImport($data)
{
- $this->userShiftsAdmin = $data['userShiftsAdmin'];
- $this->filled = $data['filled'];
- $this->rooms = $data['rooms'];
- $this->types = $data['types'];
- $this->startTime = $data['startTime'];
- $this->endTime = $data['endTime'];
+ $this->userShiftsAdmin = $data['userShiftsAdmin'] ?? false;
+ $this->filled = $data['filled'] ?? [];
+ $this->locations = $data['locations'] ?? [];
+ $this->types = $data['types'] ?? [];
+ $this->startTime = $data['startTime'] ?? null;
+ $this->endTime = $data['endTime'] ?? null;
}
/**
@@ -163,28 +163,20 @@ public function setTypes($types)
/**
* @return int[]
*/
- public function getRooms()
+ public function getLocations()
{
- if (count($this->rooms) == 0) {
+ if (count($this->locations) == 0) {
return [0];
}
- return $this->rooms;
+ return $this->locations;
}
/**
- * @param int[] $rooms
+ * @param int[] $locations
*/
- public function setRooms($rooms)
+ public function setLocations($locations)
{
- $this->rooms = $rooms;
- }
-
- /**
- * @return bool
- */
- public function isUserShiftsAdmin()
- {
- return $this->userShiftsAdmin;
+ $this->locations = $locations;
}
/**
diff --git a/includes/model/Shifts_model.php b/includes/model/Shifts_model.php
index 3925460a9..ff2c9dd25 100644
--- a/includes/model/Shifts_model.php
+++ b/includes/model/Shifts_model.php
@@ -28,12 +28,26 @@ function Shifts_by_angeltype(AngelType $angeltype)
UNION
+ /* By shift type */
SELECT DISTINCT `shifts`.* FROM `shifts`
- JOIN `needed_angel_types` ON `needed_angel_types`.`room_id` = `shifts`.`room_id`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id` = `shifts`.`shift_type_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
WHERE `needed_angel_types`.`angel_type_id` = ?
AND NOT s.shift_id IS NULL
- ', [$angeltype->id, $angeltype->id]);
+ AND se.needed_from_shift_type = TRUE
+
+ UNION
+
+ /* By location */
+ SELECT DISTINCT `shifts`.* FROM `shifts`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`location_id` = `shifts`.`location_id`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE `needed_angel_types`.`angel_type_id` = ?
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = FALSE
+ ', [$angeltype->id, $angeltype->id, $angeltype->id]);
}
/**
@@ -53,25 +67,42 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
$shifts = Db::select('
SELECT *
FROM (
- SELECT id, start
+ SELECT shifts.id, start
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE (`end` > ? AND `start` < ?)
AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_id`=`shifts`.`id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
> (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
AND s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
+
+ UNION
+
+ /* By shift type */
+ SELECT shifts.id, start
+ FROM `shifts`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE (`end` > ? AND `start` < ?)
+ AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
+ > (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = TRUE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION
- SELECT id, start
+ /* By location */
+ SELECT shifts.id, start
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
WHERE (`end` > ? AND `start` < ?)
- AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
- > (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND `freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
+ AND (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
+ > (SELECT COUNT(*) FROM `shift_entries` WHERE `shift_entries`.`shift_id`=`shifts`.`id` AND shift_entries.`freeloaded`=0' . ($filter ? ' AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
AND NOT s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ AND se.needed_from_shift_type = FALSE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`
ORDER BY `tmp`.`start`
', [
@@ -79,12 +110,15 @@ function Shifts_free($start, $end, ShiftsFilter $filter = null)
$end,
$start,
$end,
+ $start,
+ $end,
]);
$shifts = collect($shifts);
- return Shift::query()
+ return Shift::with(['location', 'shiftType'])
->whereIn('id', $shifts->pluck('id')->toArray())
+ ->orderBy('shifts.start')
->get();
}
@@ -96,32 +130,51 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
{
$sql = '
SELECT * FROM (
- SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `rooms`.`name` AS `room_name`
+ SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
FROM `shifts`
- JOIN `rooms` ON `shifts`.`room_id` = `rooms`.`id`
+ JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id` = `shifts`.`id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
+ WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND `start` BETWEEN ? AND ?
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
AND s.shift_id IS NULL
UNION
- SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `rooms`.`name` AS `room_name`
+ /* By shift type */
+ SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
+ FROM `shifts`
+ JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
+ JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
+ AND `start` BETWEEN ? AND ?
+ AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = TRUE
+
+ UNION
+
+ /* By location */
+ SELECT DISTINCT `shifts`.*, `shift_types`.`name`, `locations`.`name` AS `location_name`
FROM `shifts`
- JOIN `rooms` ON `shifts`.`room_id` = `rooms`.`id`
+ JOIN `locations` ON `shifts`.`location_id` = `locations`.`id`
JOIN `shift_types` ON `shift_types`.`id` = `shifts`.`shift_type_id`
- JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND `start` BETWEEN ? AND ?
AND `needed_angel_types`.`angel_type_id` IN (' . implode(',', $shiftsFilter->getTypes()) . ')
AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = FALSE
) AS tmp_shifts
- ORDER BY `room_name`, `start`
+ ORDER BY `location_name`, `start`
';
$shiftsData = Db::select(
@@ -131,15 +184,19 @@ function Shifts_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
$shiftsFilter->getEnd(),
$shiftsFilter->getStart(),
$shiftsFilter->getEnd(),
+ $shiftsFilter->getStart(),
+ $shiftsFilter->getEnd(),
]
);
- $shifts = [];
+ $shifts = new Collection();
foreach ($shiftsData as $shift) {
$shifts[] = (new Shift())->forceFill($shift);
}
- return collect($shifts);
+ $shifts->load(['location', 'shiftType']);
+
+ return $shifts;
}
/**
@@ -155,31 +212,54 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
`angel_types`.`id`,
`angel_types`.`name`,
`angel_types`.`restricted`,
- `angel_types`.`no_self_signup`
+ `angel_types`.`shift_self_signup`
FROM `shifts`
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id`=`shifts`.`id`
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
+ WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND shifts.`start` BETWEEN ? AND ?
AND s.shift_id IS NULL
UNION
+ /* By shift type */
SELECT
`needed_angel_types`.*,
`shifts`.`id` AS shift_id,
`angel_types`.`id`,
`angel_types`.`name`,
`angel_types`.`restricted`,
- `angel_types`.`no_self_signup`
+ `angel_types`.`shift_self_signup`
FROM `shifts`
- JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE `shifts`.`room_id` IN (' . implode(',', $shiftsFilter->getRooms()) . ')
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
AND shifts.`start` BETWEEN ? AND ?
AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = TRUE
+
+ UNION
+
+ /* By location */
+ SELECT
+ `needed_angel_types`.*,
+ `shifts`.`id` AS shift_id,
+ `angel_types`.`id`,
+ `angel_types`.`name`,
+ `angel_types`.`restricted`,
+ `angel_types`.`shift_self_signup`
+ FROM `shifts`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
+ JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE `shifts`.`location_id` IN (' . implode(',', $shiftsFilter->getLocations()) . ')
+ AND shifts.`start` BETWEEN ? AND ?
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = FALSE
';
return Db::select(
@@ -189,6 +269,8 @@ function NeededAngeltypes_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
$shiftsFilter->getEnd(),
$shiftsFilter->getStart(),
$shiftsFilter->getEnd(),
+ $shiftsFilter->getStart(),
+ $shiftsFilter->getEnd(),
]
);
}
@@ -208,7 +290,7 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
`angel_types`.`id`,
`angel_types`.`name`,
`angel_types`.`restricted`,
- `angel_types`.`no_self_signup`
+ `angel_types`.`shift_self_signup`
FROM `shifts`
JOIN `needed_angel_types` ON `needed_angel_types`.`shift_id`=`shifts`.`id`
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
@@ -219,26 +301,51 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
UNION
+ /* By shift type */
SELECT
`needed_angel_types`.*,
`shifts`.`id` AS shift_id,
`angel_types`.`id`,
`angel_types`.`name`,
`angel_types`.`restricted`,
- `angel_types`.`no_self_signup`
+ `angel_types`.`shift_self_signup`
FROM `shifts`
- JOIN `needed_angel_types` ON `needed_angel_types`.`room_id`=`shifts`.`room_id`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
WHERE `shifts`.`id`=?
AND `angel_types`.`id`=?
AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = TRUE
+
+ UNION
+
+ /* By location */
+ SELECT
+ `needed_angel_types`.*,
+ `shifts`.`id` AS shift_id,
+ `angel_types`.`id`,
+ `angel_types`.`name`,
+ `angel_types`.`restricted`,
+ `angel_types`.`shift_self_signup`
+ FROM `shifts`
+ JOIN `needed_angel_types` ON `needed_angel_types`.`location_id`=`shifts`.`location_id`
+ JOIN `angel_types` ON `angel_types`.`id`= `needed_angel_types`.`angel_type_id`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE `shifts`.`id`=?
+ AND `angel_types`.`id`=?
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = FALSE
',
[
$shift->id,
$angeltype->id,
$shift->id,
$angeltype->id,
+ $shift->id,
+ $angeltype->id,
]
);
}
@@ -249,9 +356,9 @@ function NeededAngeltype_by_Shift_and_Angeltype(Shift $shift, AngelType $angelty
*/
function ShiftEntries_by_ShiftsFilter(ShiftsFilter $shiftsFilter)
{
- return ShiftEntry::with('user')
+ return ShiftEntry::with('user', 'user.state')
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
- ->whereIn('shifts.room_id', $shiftsFilter->getRooms())
+ ->whereIn('shifts.location_id', $shiftsFilter->getLocations())
->whereBetween('start', [$shiftsFilter->getStart(), $shiftsFilter->getEnd()])
->get();
}
@@ -367,12 +474,12 @@ function Shift_signup_allowed_angel(
if (
empty($user_angeltype)
- || $angeltype->no_self_signup == 1
- || ($angeltype->restricted == 1 && !isset($user_angeltype['confirm_user_id']))
+ || !$angeltype->shift_self_signup
+ || ($angeltype->restricted && !isset($user_angeltype['confirm_user_id']))
) {
// you cannot join if user is not of this angel type
+ // you cannot join if angeltype has shift self signup disabled
// you cannot join if you are not confirmed
- // you cannot join if angeltype has no self signup
return new ShiftSignupState(ShiftSignupStatus::ANGELTYPE, $free_entries);
}
@@ -509,8 +616,8 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
$shiftsData = Db::select(
'
SELECT
- `rooms`.*,
- `rooms`.name AS Name,
+ `locations`.*,
+ `locations`.name AS Name,
`shift_types`.`id` AS `shifttype_id`,
`shift_types`.`name`,
`shift_entries`.`id` as shift_entry_id,
@@ -524,7 +631,7 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
FROM `shift_entries`
JOIN `shifts` ON (`shift_entries`.`shift_id` = `shifts`.`id`)
JOIN `shift_types` ON (`shift_types`.`id` = `shifts`.`shift_type_id`)
- JOIN `rooms` ON (`shifts`.`room_id` = `rooms`.`id`)
+ JOIN `locations` ON (`shifts`.`location_id` = `locations`.`id`)
WHERE shift_entries.`user_id` = ?
ORDER BY `start`
',
@@ -533,12 +640,13 @@ function Shifts_by_user($userId, $include_freeloaded_comments = false)
]
);
- $shifts = [];
+ $shifts = new Collection();
foreach ($shiftsData as $data) {
$shifts[] = (new Shift())->forceFill($data);
}
+ $shifts->load(['shiftType', 'location']);
- return collect($shifts);
+ return $shifts;
}
/**
@@ -558,7 +666,7 @@ function Shift($shift)
}
$neededAngels = [];
- $angelTypes = NeededAngelTypes_by_shift($shift->id);
+ $angelTypes = NeededAngelTypes_by_shift($shift);
foreach ($angelTypes as $type) {
$neededAngels[] = [
'angel_type_id' => $type['angel_type_id'],
diff --git a/includes/model/Stats.php b/includes/model/Stats.php
index adc4af32d..6dc04d513 100644
--- a/includes/model/Stats.php
+++ b/includes/model/Stats.php
@@ -1,6 +1,7 @@
= NOW() AND `start` <= NOW())
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '')
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '')
);
return $result['count'] ?: '-';
@@ -46,20 +47,37 @@ function stats_hours_to_work(ShiftsFilter $filter = null)
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE `shifts`.`end` >= NOW()
+ WHERE shifts.`end` >= NOW()
AND s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION ALL
+ /* By shift type */
SELECT
- (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`room_id`=`shifts`.`room_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
+ (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
* TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE shifts.`end` >= NOW()
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE shifts.`end` >= NOW()
AND NOT s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ AND se.needed_from_shift_type = TRUE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
+
+ UNION ALL
+
+ /* By location */
+ SELECT
+ (SELECT SUM(`count`) FROM `needed_angel_types` WHERE `needed_angel_types`.`location_id`=`shifts`.`location_id`' . ($filter ? ' AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . ')
+ * TIMESTAMPDIFF(MINUTE, `shifts`.`start`, `shifts`.`end`) / 60 AS `count`
+ FROM `shifts`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE shifts.`end` >= NOW()
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = FALSE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`
'
);
@@ -76,7 +94,7 @@ function stats_hours_to_work(ShiftsFilter $filter = null)
*/
function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
{
- $in3hours = time() + 3 * 60 * 60;
+ $in3hours = Carbon::now()->addHours(3)->toDateTimeString();
$result = Db::selectOne('
SELECT SUM(`count`) AS `count` FROM (
SELECT
@@ -89,7 +107,8 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
AND `needed_angel_types`.`shift_id`=`shifts`.`id`
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
) - (
- SELECT COUNT(*) FROM `shift_entries`
+ SELECT COUNT(*)
+ FROM `shift_entries`
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
WHERE `angel_types`.`show_on_dashboard`=TRUE
AND `shift_entries`.`shift_id`=`shifts`.`id`
@@ -102,10 +121,11 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE shifts.`end` > NOW() AND shifts.`start` < ?
AND s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION ALL
+ /* By shift type */
SELECT
GREATEST(0,
(
@@ -113,7 +133,7 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
WHERE `angel_types`.`show_on_dashboard`=TRUE
- AND `needed_angel_types`.`room_id`=`shifts`.`room_id`
+ AND `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
) - (
SELECT COUNT(*)
@@ -128,12 +148,46 @@ function stats_angels_needed_three_hours(ShiftsFilter $filter = null)
AS `count`
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE `end` > NOW() AND `start` < ?
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE shifts.`end` > NOW() AND shifts.`start` < ?
AND NOT s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ AND se.needed_from_shift_type = TRUE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
+
+ UNION ALL
+
+ /* By location */
+ SELECT
+ GREATEST(0,
+ (
+ SELECT SUM(needed_angel_types.`count`)
+ FROM `needed_angel_types`
+ JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
+ WHERE `angel_types`.`show_on_dashboard`=TRUE
+ AND `needed_angel_types`.`location_id`=`shifts`.`location_id`
+ ' . ($filter ? 'AND needed_angel_types.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
+ ) - (
+ SELECT COUNT(*)
+ FROM `shift_entries`
+ JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
+ WHERE `angel_types`.`show_on_dashboard`=TRUE
+ AND `shift_entries`.`shift_id`=`shifts`.`id`
+ AND `freeloaded`=0
+ ' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
+ )
+ )
+ AS `count`
+ FROM `shifts`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE shifts.`end` > NOW() AND shifts.`start` < ?
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = FALSE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`', [
$in3hours,
$in3hours,
+ $in3hours,
]);
return $result['count'] ?: '-';
@@ -157,6 +211,8 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
date('Y-m-d', time() + 12 * 60 * 60) . ' ' . $nightStartTime . ':00'
);
$night_end = $night_start + ($nightEndTime - $nightStartTime) * 60 * 60;
+ $night_start = Carbon::createFromTimestamp($night_start)->toDateTimeString();
+ $night_end = Carbon::createFromTimestamp($night_end)->toDateTimeString();
$result = Db::selectOne('
SELECT SUM(`count`) AS `count` FROM (
SELECT
@@ -182,10 +238,11 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
WHERE shifts.`end` > ? AND shifts.`start` < ?
AND s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
UNION ALL
+ /* By shift type */
SELECT
GREATEST(0,
(
@@ -193,28 +250,62 @@ function stats_angels_needed_for_nightshifts(ShiftsFilter $filter = null)
FROM `needed_angel_types`
JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
WHERE `angel_types`.`show_on_dashboard`=TRUE
- AND `needed_angel_types`.`room_id`=`shifts`.`room_id`
+ AND `needed_angel_types`.`shift_type_id`=`shifts`.`shift_type_id`
' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
) - (
SELECT COUNT(*) FROM `shift_entries`
JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
WHERE `angel_types`.`show_on_dashboard`=TRUE
AND `shift_entries`.`shift_id`=`shifts`.`id`
- AND `freeloaded`=0
+ AND shift_entries.`freeloaded`=0
+ ' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
+ )
+ )
+ AS `count`
+ FROM `shifts`
+ LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE shifts.`end` > ? AND shifts.`start` < ?
+ AND NOT s.shift_id IS NULL
+ AND se.needed_from_shift_type = TRUE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
+
+ UNION ALL
+
+ /* By location */
+ SELECT
+ GREATEST(0,
+ (
+ SELECT SUM(needed_angel_types.`count`)
+ FROM `needed_angel_types`
+ JOIN `angel_types` ON `angel_types`.`id`=`needed_angel_types`.`angel_type_id`
+ WHERE `angel_types`.`show_on_dashboard`=TRUE
+ AND `needed_angel_types`.`location_id`=`shifts`.`location_id`
+ ' . ($filter ? 'AND angel_types.id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
+ ) - (
+ SELECT COUNT(*) FROM `shift_entries`
+ JOIN `angel_types` ON `angel_types`.`id`=`shift_entries`.`angel_type_id`
+ WHERE `angel_types`.`show_on_dashboard`=TRUE
+ AND `shift_entries`.`shift_id`=`shifts`.`id`
+ AND shift_entries.`freeloaded`=0
' . ($filter ? 'AND shift_entries.angel_type_id IN (' . implode(',', $filter->getTypes()) . ')' : '') . '
)
)
AS `count`
FROM `shifts`
LEFT JOIN schedule_shift AS s on shifts.id = s.shift_id
- WHERE `end` > ? AND `start` < ?
+ LEFT JOIN schedules AS se on s.schedule_id = se.id
+ WHERE shifts.`end` > ? AND shifts.`start` < ?
AND NOT s.shift_id IS NULL
- ' . ($filter ? 'AND shifts.room_id IN (' . implode(',', $filter->getRooms()) . ')' : '') . '
+ AND se.needed_from_shift_type = FALSE
+ ' . ($filter ? 'AND shifts.location_id IN (' . implode(',', $filter->getLocations()) . ')' : '') . '
) AS `tmp`', [
$night_start,
$night_end,
$night_start,
$night_end,
+ $night_start,
+ $night_end,
]);
return $result['count'] ?: '-';
diff --git a/includes/model/UserWorkLog_model.php b/includes/model/UserWorkLog_model.php
deleted file mode 100644
index a15c7969c..000000000
--- a/includes/model/UserWorkLog_model.php
+++ /dev/null
@@ -1,23 +0,0 @@
-whereDate('worked_at', '>=', $sinceTime);
- }
-
- return $worklogs->get();
-}
diff --git a/includes/model/User_model.php b/includes/model/User_model.php
index b57059d32..560ab1715 100644
--- a/includes/model/User_model.php
+++ b/includes/model/User_model.php
@@ -5,7 +5,6 @@
use Engelsystem\Models\AngelType;
use Engelsystem\Models\User\User;
use Engelsystem\Models\Worklog;
-use Engelsystem\ValidationResult;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
@@ -67,113 +66,6 @@ function Users_by_angeltype_inverted(AngelType $angeltype)
->get();
}
-/**
- * Strip unwanted characters from a users nick. Allowed are letters, numbers, connecting punctuation and simple space.
- * Nick is trimmed.
- *
- * @param string $nick
- * @return ValidationResult
- */
-function User_validate_Nick($nick)
-{
- $nick = trim($nick);
-
- if (strlen($nick) == 0 || strlen($nick) > 24) {
- return new ValidationResult(false, $nick);
- }
- if (preg_match(config('username_regex', '/([^\p{L}\p{N}\-_. ]+)/ui'), $nick)) {
- return new ValidationResult(false, $nick);
- }
-
- return new ValidationResult(true, $nick);
-}
-
-/**
- * Validate the planned arrival date
- *
- * @param int $planned_arrival_date Unix timestamp
- * @return ValidationResult
- */
-function User_validate_planned_arrival_date($planned_arrival_date)
-{
- if (is_null($planned_arrival_date)) {
- // null is not okay
- return new ValidationResult(false, time());
- }
-
- $config = config();
- $buildup = $config->get('buildup_start');
- $teardown = $config->get('teardown_end');
-
- /** @var Carbon $buildup */
- if (!empty($buildup) && Carbon::createFromTimestamp($planned_arrival_date)->lessThan($buildup->setTime(0, 0))) {
- // Planned arrival can not be before buildup start date
- return new ValidationResult(false, $buildup->getTimestamp());
- }
-
- /** @var Carbon $teardown */
- if (!empty($teardown) && Carbon::createFromTimestamp($planned_arrival_date)->greaterThanOrEqualTo($teardown->addDay()->setTime(0, 0))) {
- // Planned arrival can not be after teardown end date
- return new ValidationResult(false, $teardown->getTimestamp());
- }
-
- return new ValidationResult(true, $planned_arrival_date);
-}
-
-/**
- * Validate the planned departure date
- *
- * @param int $planned_arrival_date Unix timestamp
- * @param int $planned_departure_date Unix timestamp
- * @return ValidationResult
- */
-function User_validate_planned_departure_date($planned_arrival_date, $planned_departure_date)
-{
- if (is_null($planned_departure_date)) {
- // null is okay
- return new ValidationResult(true, null);
- }
-
- if ($planned_arrival_date > $planned_departure_date) {
- // departure cannot be before arrival
- return new ValidationResult(false, $planned_arrival_date);
- }
-
- $config = config();
- $buildup = $config->get('buildup_start');
- $teardown = $config->get('teardown_end');
-
- /** @var Carbon $buildup */
- if (!empty($buildup) && Carbon::createFromTimestamp($planned_departure_date)->lessThan($buildup->setTime(0, 0))) {
- // Planned departure can not be before buildup start date
- return new ValidationResult(false, $buildup->getTimestamp());
- }
-
- /** @var Carbon $teardown */
- if (!empty($teardown) && Carbon::createFromTimestamp($planned_departure_date)->greaterThanOrEqualTo($teardown->addDay()->setTime(0, 0))) {
- // Planned departure can not be after teardown end date
- return new ValidationResult(false, $teardown->getTimestamp());
- }
-
- return new ValidationResult(true, $planned_departure_date);
-}
-
-/**
- * Generates a new api key for given user.
- *
- * @param User $user
- * @param bool $log
- */
-function User_reset_api_key($user, $log = true)
-{
- $user->api_key = bin2hex(random_bytes(32));
- $user->save();
-
- if ($log) {
- engelsystem_log(sprintf('API key resetted (%s).', User_Nick_render($user, true)));
- }
-}
-
/**
* @param User $user
* @return float
@@ -186,7 +78,10 @@ function User_get_eligable_voucher_count($user)
: null;
$shiftEntries = ShiftEntries_finished_by_user($user, $start);
- $worklog = UserWorkLogsForUser($user->id, $start);
+ $worklog = $user->worklogs()
+ ->whereDate('worked_at', '>=', $start ?: 0)
+ ->with(['user', 'creator'])
+ ->get();
$shifts_done =
count($shiftEntries)
+ $worklog->count();
diff --git a/includes/pages/admin_active.php b/includes/pages/admin_active.php
index 4685e76b3..2b4aacd10 100644
--- a/includes/pages/admin_active.php
+++ b/includes/pages/admin_active.php
@@ -3,6 +3,7 @@
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\User\State;
use Engelsystem\Models\User\User;
+use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\JoinClause;
use Engelsystem\Config\GoodieType;
@@ -47,11 +48,11 @@ function admin_active()
__('At least %s angels are forced to be active. The number has to be greater.'),
$forced_count
));
- throw_redirect(page_link_to('admin_active'));
+ throw_redirect(url('/admin-active'));
}
} else {
$msg .= error(__('Please enter a number of angels to be marked as active.'));
- throw_redirect(page_link_to('admin_active'));
+ throw_redirect(url('/admin-active'));
}
if ($request->hasPostData('ack')) {
@@ -78,6 +79,11 @@ function admin_active()
->leftJoin('shifts', 'shift_entries.shift_id', '=', 'shifts.id')
->leftJoin('users_state', 'users.id', '=', 'users_state.user_id')
->where('users_state.arrived', '=', true)
+ ->orWhere(function (EloquentBuilder $userinfo) {
+ $userinfo->where('users_state.arrived', '=', false)
+ ->whereNotNull('users_state.user_info')
+ ->whereNot('users_state.user_info', '');
+ })
->groupBy('users.id')
->orderByDesc('force_active')
->orderByDesc('shift_length')
@@ -97,9 +103,9 @@ function admin_active()
$msg = success(__('Marked angels.'), true);
} else {
$set_active = form([
- button(page_link_to('admin_active', ['search' => $search]), '« ' . __('back')),
- form_submit('ack', '» ' . __('apply')),
- ], page_link_to('admin_active', ['search' => $search, 'count' => $count, 'set_active' => 1]));
+ button(url('/admin-active', ['search' => $search]), '« ' . __('general.back')),
+ form_submit('ack', '» ' . __('Apply')),
+ ], url('/admin-active', ['search' => $search, 'count' => $count, 'set_active' => 1]));
}
}
@@ -133,7 +139,7 @@ function admin_active()
$user_source->state->got_shirt = true;
$user_source->state->save();
engelsystem_log('User ' . User_Nick_render($user_source, true) . ' has tshirt now.');
- $msg = success(($goodie_tshirt ? __('Angel has got a t-shirt.') : __('Angel has got a goodie.')), true);
+ $msg = success(($goodie_tshirt ? __('Angel has got a T-shirt.') : __('Angel has got a goodie.')), true);
} else {
$msg = error('Angel not found.', true);
}
@@ -144,14 +150,14 @@ function admin_active()
$user_source->state->got_shirt = false;
$user_source->state->save();
engelsystem_log('User ' . User_Nick_render($user_source, true) . ' has NO tshirt.');
- $msg = success(($goodie_tshirt ? __('Angel has got no t-shirt.') : __('Angel has got no goodie.')), true);
+ $msg = success(($goodie_tshirt ? __('Angel has got no T-shirt.') : __('Angel has got no goodie.')), true);
} else {
$msg = error(__('Angel not found.'), true);
}
}
}
- $query = User::with('personalData')
+ $query = User::with(['personalData', 'state'])
->selectRaw(
sprintf(
'
@@ -180,6 +186,11 @@ function admin_active()
})
->leftJoin('users_state', 'users.id', '=', 'users_state.user_id')
->where('users_state.arrived', '=', true)
+ ->orWhere(function (EloquentBuilder $userinfo) {
+ $userinfo->where('users_state.arrived', '=', false)
+ ->whereNotNull('users_state.user_info')
+ ->whereNot('users_state.user_info', '');
+ })
->groupBy('users.id')
->orderByDesc('force_active')
->orderByDesc('shift_length')
@@ -215,7 +226,7 @@ function admin_active()
$shirtSize = $usr->personalData->shirt_size;
$userData = [];
$userData['no'] = count($matched_users) + 1;
- $userData['nick'] = User_Nick_render($usr) . User_Pronoun_render($usr);
+ $userData['nick'] = User_Nick_render($usr) . User_Pronoun_render($usr) . user_info_icon($usr);
if ($goodie_tshirt) {
$userData['shirt_size'] = (isset($tshirt_sizes[$shirtSize]) ? $tshirt_sizes[$shirtSize] : '');
}
@@ -236,8 +247,8 @@ function admin_active()
$parameters['show_all_shifts'] = 1;
}
$actions[] = form(
- [form_submit('submit', __('set active'), 'btn-sm', false, 'secondary')],
- page_link_to('admin_active', $parameters),
+ [form_submit('submit', icon('plus-lg') . __('set active'), 'btn-sm', false, 'secondary')],
+ url('/admin-active', $parameters),
false,
true
);
@@ -251,8 +262,8 @@ function admin_active()
$parametersRemove['show_all_shifts'] = 1;
}
$actions[] = form(
- [form_submit('submit', __('remove active'), 'btn-sm', false, 'secondary')],
- page_link_to('admin_active', $parametersRemove),
+ [form_submit('submit', icon('dash-lg') . __('Remove active'), 'btn-sm', false, 'secondary')],
+ url('/admin-active', $parametersRemove),
false,
true
);
@@ -268,8 +279,8 @@ function admin_active()
if ($goodie_enabled) {
$actions[] = form(
- [form_submit('submit', ($goodie_tshirt ? __('got t-shirt') : __('got goodie')), 'btn-sm', false, 'secondary')],
- page_link_to('admin_active', $parametersShirt),
+ [form_submit('submit', icon('person') . ($goodie_tshirt ? __('Got T-shirt') : __('Got goodie')), 'btn-sm', false, 'secondary')],
+ url('/admin-active', $parametersShirt),
false,
true
);
@@ -286,8 +297,8 @@ function admin_active()
if ($goodie_enabled) {
$actions[] = form(
- [form_submit('submit', ($goodie_tshirt ? __('remove t-shirt') : __('remove goodie')), 'btn-sm', false, 'secondary')],
- page_link_to('admin_active', $parameters),
+ [form_submit('submit', icon('person') . ($goodie_tshirt ? __('Remove T-shirt') : __('Remove goodie')), 'btn-sm', false, 'secondary')],
+ url('/admin-active', $parameters),
false,
true
);
@@ -295,7 +306,7 @@ function admin_active()
}
if ($goodie_tshirt) {
- $actions[] = button(url('/admin/user/' . $usr->id . '/goodie'), __('form.edit'), 'btn-secondary btn-sm');
+ $actions[] = button(url('/admin/user/' . $usr->id . '/goodie'), icon('pencil') . __('form.edit'), 'btn-secondary btn-sm');
}
$userData['actions'] = buttons($actions);
@@ -328,18 +339,18 @@ function admin_active()
form([
form_text('search', __('Search angel:'), $search),
form_checkbox('show_all_shifts', __('Show all shifts'), $show_all_shifts),
- form_submit('submit', __('Search')),
- ], page_link_to('admin_active')),
+ form_submit('submit', icon('search') . __('form.search')),
+ ], url('/admin-active')),
$set_active == '' ? form([
form_text('count', __('How much angels should be active?'), $count ?: $forced_count),
- form_submit('set_active', __('Preview')),
+ form_submit('set_active', icon('eye') . __('form.preview'), 'btn-info'),
]) : $set_active,
$msg . msg(),
table(
array_merge(
[
'no' => __('No.'),
- 'nick' => __('Name'),
+ 'nick' => __('general.name'),
],
($goodie_tshirt ? ['shirt_size' => __('Size')] : []),
[
@@ -350,15 +361,15 @@ function admin_active()
],
($goodie_enabled ? ['tshirt' => ($goodie_tshirt ? __('T-shirt?') : __('Goodie?'))] : []),
[
- 'actions' => '',
+ 'actions' => __('general.actions'),
]
),
$matched_users
),
- $goodie_enabled ? '' . ($goodie_tshirt ? __('Shirt statistic') : __('Goodie statistic')) . '
' : '',
+ $goodie_enabled ? '' . ($goodie_tshirt ? __('T-shirt statistic') : __('Goodie statistic')) . '
' : '',
$goodie_enabled ? table(array_merge(
($goodie_tshirt ? ['size' => __('Size')] : []),
- ['given' => $goodie_tshirt ? __('Given shirts') : __('Given goodies') ]
+ ['given' => $goodie_tshirt ? __('Given T-shirts') : __('Given goodies') ]
), $goodie_statistics) : '',
]);
}
diff --git a/includes/pages/admin_arrive.php b/includes/pages/admin_arrive.php
index 31a66707e..51a78d785 100644
--- a/includes/pages/admin_arrive.php
+++ b/includes/pages/admin_arrive.php
@@ -65,7 +65,7 @@ function admin_arrive()
}
/** @var User[] $users */
- $users = User::with('personalData')->orderBy('name')->get();
+ $users = User::with(['personalData', 'state'])->orderBy('name')->get();
$arrival_count_at_day = [];
$planned_arrival_count_at_day = [];
$planned_departure_count_at_day = [];
@@ -78,7 +78,13 @@ function admin_arrive()
foreach ($users as $usr) {
if (count($tokens) > 0) {
$match = false;
- $index = join(' ', $usr->attributesToArray());
+ $data = collect($usr->toArray())->flatten()->filter(function ($value) {
+ // Remove empty values
+ return !empty($value) &&
+ // Skip datetime
+ !preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{6}Z$/', (string) $value);
+ });
+ $index = join(' ', $data->toArray());
foreach ($tokens as $token) {
$token = trim($token);
if (!empty($token) && stristr($index, $token)) {
@@ -92,50 +98,66 @@ function admin_arrive()
}
}
- $usr->name = User_Nick_render($usr) . User_Pronoun_render($usr);
+ $usr->name = User_Nick_render($usr)
+ . User_Pronoun_render($usr)
+ . user_info_icon($usr);
$plannedDepartureDate = $usr->personalData->planned_departure_date;
$arrivalDate = $usr->state->arrival_date;
$plannedArrivalDate = $usr->personalData->planned_arrival_date;
$usr['rendered_planned_departure_date'] = $plannedDepartureDate
- ? $plannedDepartureDate->format(__('Y-m-d'))
+ ? $plannedDepartureDate->format(__('general.date'))
: '-';
- $usr['rendered_planned_arrival_date'] = $plannedArrivalDate ? $plannedArrivalDate->format(__('Y-m-d')) : '-';
- $usr['rendered_arrival_date'] = $arrivalDate ? $arrivalDate->format(__('Y-m-d')) : '-';
+ $usr['rendered_planned_arrival_date'] = $plannedArrivalDate ? $plannedArrivalDate->format(__('general.date')) : '-';
+ $usr['rendered_arrival_date'] = $arrivalDate ? $arrivalDate->format(__('general.date')) : '-';
$usr['arrived'] = icon_bool($usr->state->arrived);
$usr['actions'] = form([
form_hidden('action', $usr->state->arrived ? 'reset' : 'arrived'),
form_hidden('user', $usr->id),
form_submit(
'submit',
- $usr->state->arrived ? __('reset') : __('arrived'),
+ $usr->state->arrived
+ ? icon('arrow-counterclockwise')
+ : icon('house'),
'btn-sm',
true,
- $usr->state->arrived ? 'secondary' : 'primary'
+ $usr->state->arrived ? 'secondary' : 'primary',
+ $usr->state->arrived
+ ? __('Reset')
+ : __('user.arrive')
),
]);
if ($usr->state->arrival_date) {
- $day = $usr->state->arrival_date->format(__('Y-m-d'));
+ $day = $usr->state->arrival_date->format('Y-m-d');
if (!isset($arrival_count_at_day[$day])) {
- $arrival_count_at_day[$day] = 0;
+ $arrival_count_at_day[$day] = [
+ 'day' => $usr->state->arrival_date,
+ 'count' => 0,
+ ];
}
- $arrival_count_at_day[$day]++;
+ $arrival_count_at_day[$day]['count']++;
}
if ($usr->personalData->planned_arrival_date) {
- $day = $usr->personalData->planned_arrival_date->format(__('Y-m-d'));
+ $day = $usr->personalData->planned_arrival_date->format('Y-m-d');
if (!isset($planned_arrival_count_at_day[$day])) {
- $planned_arrival_count_at_day[$day] = 0;
+ $planned_arrival_count_at_day[$day] = [
+ 'day' => $usr->personalData->planned_arrival_date,
+ 'count' => 0,
+ ];
}
- $planned_arrival_count_at_day[$day]++;
+ $planned_arrival_count_at_day[$day]['count']++;
}
if ($usr->personalData->planned_departure_date && $usr->state->arrived) {
- $day = $usr->personalData->planned_departure_date->format(__('Y-m-d'));
+ $day = $usr->personalData->planned_departure_date->format('Y-m-d');
if (!isset($planned_departure_count_at_day[$day])) {
- $planned_departure_count_at_day[$day] = 0;
+ $planned_departure_count_at_day[$day] = [
+ 'day' => $usr->personalData->planned_departure_date,
+ 'count' => 0,
+ ];
}
- $planned_departure_count_at_day[$day]++;
+ $planned_departure_count_at_day[$day]['count']++;
}
$users_matched[] = $usr;
@@ -147,33 +169,33 @@ function admin_arrive()
$arrival_at_day = [];
$arrival_sum = 0;
- foreach ($arrival_count_at_day as $day => $count) {
- $arrival_sum += $count;
+ foreach ($arrival_count_at_day as $day => $entry) {
+ $arrival_sum += $entry['count'];
$arrival_at_day[$day] = [
- 'day' => $day,
- 'count' => $count,
+ 'day' => $entry['day']->format(__('general.date')),
+ 'count' => $entry['count'],
'sum' => $arrival_sum,
];
}
$planned_arrival_at_day = [];
$planned_arrival_sum = 0;
- foreach ($planned_arrival_count_at_day as $day => $count) {
- $planned_arrival_sum += $count;
+ foreach ($planned_arrival_count_at_day as $day => $entry) {
+ $planned_arrival_sum += $entry['count'];
$planned_arrival_at_day[$day] = [
- 'day' => $day,
- 'count' => $count,
+ 'day' => $entry['day']->format(__('general.date')),
+ 'count' => $entry['count'],
'sum' => $planned_arrival_sum,
];
}
$planned_departure_at_day = [];
$planned_departure_sum = 0;
- foreach ($planned_departure_count_at_day as $day => $count) {
- $planned_departure_sum += $count;
+ foreach ($planned_departure_count_at_day as $day => $entry) {
+ $planned_departure_sum += $entry['count'];
$planned_departure_at_day[$day] = [
- 'day' => $day,
- 'count' => $count,
+ 'day' => $entry['day']->format(__('general.date')),
+ 'count' => $entry['count'],
'sum' => $planned_departure_sum,
];
}
@@ -181,60 +203,60 @@ function admin_arrive()
return page_with_title(admin_arrive_title(), [
$msg . msg(),
form([
- form_text('search', __('Search'), $search),
- form_submit('submit', __('Search')),
- ], page_link_to('admin_arrive')),
+ form_text('search', __('form.search'), $search),
+ form_submit('submit', icon('search') . __('form.search')),
+ ], url('/admin-arrive')),
table([
- 'name' => __('Name'),
+ 'name' => __('general.name'),
'rendered_planned_arrival_date' => __('Planned arrival'),
'arrived' => __('Arrived?'),
'rendered_arrival_date' => __('Arrival date'),
'rendered_planned_departure_date' => __('Planned departure'),
- 'actions' => '',
+ 'actions' => __('general.actions'),
], $users_matched),
div('row', [
div('col-md-4', [
heading(__('Planned arrival statistics'), 3),
BarChart::render([
- 'count' => __('arrived'),
+ 'count' => __('user.arrived'),
'sum' => __('arrived sum'),
], [
'count' => '#090',
'sum' => '#888',
], $planned_arrival_at_day),
table([
- 'day' => __('Date'),
- 'count' => __('Count'),
+ 'day' => __('title.date'),
+ 'count' => __('general.count'),
'sum' => __('Sum'),
], $planned_arrival_at_day),
]),
div('col-md-4', [
heading(__('Arrival statistics'), 3),
BarChart::render([
- 'count' => __('arrived'),
+ 'count' => __('user.arrived'),
'sum' => __('arrived sum'),
], [
'count' => '#090',
'sum' => '#888',
], $arrival_at_day),
table([
- 'day' => __('Date'),
- 'count' => __('Count'),
+ 'day' => __('title.date'),
+ 'count' => __('general.count'),
'sum' => __('Sum'),
], $arrival_at_day),
]),
div('col-md-4', [
heading(__('Planned departure statistics'), 3),
BarChart::render([
- 'count' => __('arrived'),
+ 'count' => __('user.arrived'),
'sum' => __('arrived sum'),
], [
'count' => '#090',
'sum' => '#888',
], $planned_departure_at_day),
table([
- 'day' => __('Date'),
- 'count' => __('Count'),
+ 'day' => __('title.date'),
+ 'count' => __('general.count'),
'sum' => __('Sum'),
], $planned_departure_at_day),
]),
diff --git a/includes/pages/admin_free.php b/includes/pages/admin_free.php
index 7fd17faae..d5b5db669 100644
--- a/includes/pages/admin_free.php
+++ b/includes/pages/admin_free.php
@@ -40,7 +40,7 @@ function admin_free()
/** @var User[] $users */
$users = [];
if ($request->has('submit')) {
- $query = User::with('personalData')
+ $query = User::with(['personalData', 'contact', 'state'])
->select('users.*')
->leftJoin('shift_entries', 'users.id', 'shift_entries.user_id')
->leftJoin('users_state', 'users.id', 'users_state.user_id')
@@ -97,16 +97,18 @@ function admin_free()
$email = $usr->contact->email ?: $usr->email;
$free_users_table[] = [
- 'name' => User_Nick_render($usr) . User_Pronoun_render($usr),
+ 'name' => User_Nick_render($usr)
+ . User_Pronoun_render($usr)
+ . user_info_icon($usr),
'shift_state' => User_shift_state_render($usr),
'last_shift' => User_last_shift_render($usr),
- 'dect' => sprintf('%1$s', $usr->contact->dect),
+ 'dect' => sprintf('%1$s', htmlspecialchars((string) $usr->contact->dect)),
'email' => $usr->settings->email_human
- ? sprintf('%1$s', $email)
+ ? sprintf('%1$s', htmlspecialchars((string) $email))
: icon('eye-slash'),
'actions' =>
auth()->can('admin_user')
- ? button(page_link_to('admin_user', ['id' => $usr->id]), icon('pencil') . __('edit'), 'btn-sm')
+ ? button(url('/admin-user', ['id' => $usr->id]), icon('pencil'), 'btn-sm', '', __('form.edit'))
: '',
];
}
@@ -115,19 +117,19 @@ function admin_free()
div('row', [
div('col-md-12 form-inline', [
div('row', [
- form_text('search', __('Search'), $search, null, null, null, 'col'),
+ form_text('search', __('form.search'), $search, null, null, null, 'col'),
form_select('angeltype', __('Angeltype'), $angel_types, $angelType, '', 'col'),
- form_submit('submit', __('Search')),
+ form_submit('submit', icon('search') . __('form.search')),
]),
]),
]),
]),
table([
- 'name' => __('Name'),
- 'shift_state' => __('Next shift'),
+ 'name' => __('general.name'),
+ 'shift_state' => __('shift.next'),
'last_shift' => __('Last shift'),
- 'dect' => __('DECT'),
- 'email' => __('E-Mail'),
+ 'dect' => __('general.dect'),
+ 'email' => __('general.email'),
'actions' => '',
], $free_users_table),
]);
diff --git a/includes/pages/admin_groups.php b/includes/pages/admin_groups.php
index 5e46d5ba0..62ea115a5 100644
--- a/includes/pages/admin_groups.php
+++ b/includes/pages/admin_groups.php
@@ -21,28 +21,31 @@ function admin_groups()
$html = '';
$request = request();
/** @var Group[]|Collection $groups */
- $groups = Group::query()->orderBy('name')->get();
+ $groups = Group::with('privileges')->orderBy('name')->get();
if (!$request->has('action')) {
$groups_table = [];
foreach ($groups as $group) {
/** @var Privilege[]|Collection $privileges */
- $privileges = $group->privileges()->orderBy('name')->get();
+ $privileges = $group->privileges->sortBy('name');
$privileges_html = [];
foreach ($privileges as $privilege) {
- $privileges_html[] = $privilege['name'];
+ $privileges_html[] = htmlspecialchars($privilege['name']);
}
$groups_table[] = [
- 'name' => $group->name,
+ 'name' => htmlspecialchars($group->name),
'privileges' => join(', ', $privileges_html),
'actions' => button(
- page_link_to(
- 'admin_groups',
+ url(
+ '/admin-groups',
['action' => 'edit', 'id' => $group->id]
),
- icon('pencil') . __('edit'),
+ icon('pencil'),
+ '',
+ '',
+ __('form.edit'),
'btn-sm'
),
];
@@ -50,7 +53,7 @@ function admin_groups()
return page_with_title(admin_groups_title(), [
table([
- 'name' => __('Name'),
+ 'name' => __('general.name'),
'privileges' => __('Privileges'),
'actions' => '',
], $groups_table),
@@ -72,18 +75,18 @@ function admin_groups()
foreach ($privileges as $privilege) {
$privileges_form[] = form_checkbox(
'privileges[]',
- $privilege->description . ' (' . $privilege->name . ')',
+ htmlspecialchars($privilege->description . ' (' . $privilege->name . ')'),
$privilege->selected != '',
$privilege->id,
- 'privilege-' . $privilege->name
+ 'privilege-' . htmlspecialchars($privilege->name)
);
}
- $privileges_form[] = form_submit('submit', __('Save'));
- $html .= page_with_title(__('Edit group') . ' ' . $group->name, [
+ $privileges_form[] = form_submit('submit', icon('save') . __('form.save'));
+ $html .= page_with_title(__('Edit group') . ' ' . htmlspecialchars($group->name), [
form(
$privileges_form,
- page_link_to('admin_groups', ['action' => 'save', 'id' => $group->id])
+ url('/admin-groups', ['action' => 'save', 'id' => $group->id])
),
]);
} else {
@@ -118,7 +121,7 @@ function admin_groups()
'Group privileges of group ' . $group->name
. ' edited: ' . join(', ', $privilege_names)
);
- throw_redirect(page_link_to('admin_groups'));
+ throw_redirect(url('/admin-groups'));
} else {
return error('No Group found.', true);
}
diff --git a/includes/pages/admin_rooms.php b/includes/pages/admin_rooms.php
deleted file mode 100644
index e69de29bb..000000000
diff --git a/includes/pages/admin_shifts.php b/includes/pages/admin_shifts.php
index c4fc29bc7..f435cec2f 100644
--- a/includes/pages/admin_shifts.php
+++ b/includes/pages/admin_shifts.php
@@ -1,15 +1,11 @@
get();
- $room_array = $rooms->pluck('name', 'id')->toArray();
+ $locations = Location::orderBy('name')->get();
+ $location_array = $locations->pluck('name', 'id')->toArray();
// Load angeltypes
/** @var AngelType[] $types */
@@ -85,14 +81,14 @@ function admin_shifts()
// Auswahl der sichtbaren Locations fΓΌr die Schichten
if (
- $request->has('rid')
- && preg_match('/^\d+$/', $request->input('rid'))
- && isset($room_array[$request->input('rid')])
+ $request->has('lid')
+ && preg_match('/^\d+$/', $request->input('lid'))
+ && isset($location_array[$request->input('lid')])
) {
- $rid = $request->input('rid');
+ $lid = $request->input('lid');
} else {
$valid = false;
- $rid = $rooms->first()->id;
+ $lid = $locations->first()?->id ?? 0;
error(__('Please select a location.'));
}
@@ -139,6 +135,29 @@ function admin_shifts()
'trim',
explode(',', $request->input('change_hours'))
);
+ // Fehlende Minutenangaben ergΓ€nzen, 24 Uhr -> 00 Uhr
+ array_walk($change_hours, function (&$value) use ($valid) {
+ // Add minutes
+ if (!preg_match('/^(\d{1,2}):\d{2}$/', $value)) {
+ $value .= ':00';
+ }
+ // Add 0 before low hours
+ if (preg_match('/^\d:\d{2}$/', $value)) {
+ $value = '0' . $value;
+ }
+ // Fix 24:00
+ if ($value == '24:00') {
+ $value = '00:00';
+ }
+ });
+ // Ensure valid time in change hours
+ foreach ($change_hours as $change_hour) {
+ if (!preg_match('/^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/', $change_hour)) {
+ $valid = false;
+ error(sprintf(__('Please validate the change hour %s. It should be between 00:00 and 24:00.'), $change_hour));
+ }
+ }
+ $change_hours = array_unique($change_hours);
} else {
$valid = false;
error(__('Please split the shift-change hours by colons.'));
@@ -152,7 +171,9 @@ function admin_shifts()
}
if ($request->has('angelmode')) {
- if ($request->input('angelmode') == 'location') {
+ if ($request->input('angelmode') == 'shift_type') {
+ $angelmode = 'shift_type';
+ } elseif ($request->input('angelmode') == 'location') {
$angelmode = 'location';
} elseif ($request->input('angelmode') == 'manually') {
foreach ($types as $type) {
@@ -163,15 +184,23 @@ function admin_shifts()
error(sprintf(__('Please check the needed angels for team %s.'), $type->name));
}
}
-
- if (array_sum($needed_angel_types) == 0) {
- $valid = false;
- error(__('There are 0 angels needed. Please enter the amounts of needed angels.'));
- }
} else {
$valid = false;
error(__('Please select a mode for needed angels.'));
}
+
+ if (
+ $angelmode == 'manually' && array_sum($needed_angel_types) == 0
+ || $angelmode == 'location' && !NeededAngelType::whereLocationId($lid)
+ ->where('count', '>', '0')
+ ->count()
+ || $angelmode == 'shift_type' && !NeededAngelType::whereShiftTypeId($shifttype_id)
+ ->where('count', '>', '0')
+ ->count()
+ ) {
+ $valid = false;
+ error(__('There are 0 angels needed. Please enter the amounts of needed angels.'));
+ }
} else {
$valid = false;
error(__('Please select needed angels.'));
@@ -184,8 +213,12 @@ function admin_shifts()
// Alle Eingaben in Ordnung
if ($valid) {
- if ($angelmode == 'location') {
- $needed_angel_types = NeededAngelType::whereRoomId($rid)
+ if ($angelmode == 'shift_type') {
+ $needed_angel_types = NeededAngelType::whereShiftTypeId($shifttype_id)
+ ->pluck('count', 'angel_type_id')
+ ->toArray() + $needed_angel_types;
+ } elseif ($angelmode == 'location') {
+ $needed_angel_types = NeededAngelType::whereLocationId($lid)
->pluck('count', 'angel_type_id')
->toArray() + $needed_angel_types;
}
@@ -195,7 +228,7 @@ function admin_shifts()
$shifts[] = [
'start' => $start,
'end' => $end,
- 'room_id' => $rid,
+ 'location_id' => $lid,
'title' => $title,
'shift_type_id' => $shifttype_id,
'description' => $description,
@@ -215,7 +248,7 @@ function admin_shifts()
$shifts[] = [
'start' => $shift_start,
'end' => $shift_end,
- 'room_id' => $rid,
+ 'location_id' => $lid,
'title' => $title,
'shift_type_id' => $shifttype_id,
'description' => $description,
@@ -224,13 +257,6 @@ function admin_shifts()
$shift_start = $shift_end;
} while ($shift_end < $end);
} elseif ($mode == 'variable') {
- // Fehlende Minutenangaben ergΓ€nzen
- array_walk($change_hours, function (&$value) {
- if (!preg_match('/^\d{1,2}:\d{2}$/', $value)) {
- $value .= ':00';
- }
- });
-
// Alle Tage durchgehen
$end_day = Carbon::createFromDatetime($end->format('Y-m-d') . ' 00:00');
$day = Carbon::createFromDatetime($start->format('Y-m-d') . ' 00:00');
@@ -238,10 +264,10 @@ function admin_shifts()
// Alle Schichtwechselstunden durchgehen
for ($i = 0; $i < count($change_hours); $i++) {
$start_hour = $change_hours[$i];
- if ($i < count($change_hours) - 1) {
+ if (isset($change_hours[$i + 1])) {
// Normales Intervall zwischen zwei Schichtwechselstunden
$end_hour = $change_hours[$i + 1];
- } elseif ($shift_over_midnight) {
+ } elseif ($shift_over_midnight && $day != $end_day) {
// Letzte Schichtwechselstunde: Wenn eine 24h Abdeckung gewΓΌnscht ist,
// hier die erste Schichtwechselstunde als Ende einsetzen
$end_hour = $change_hours[0];
@@ -283,7 +309,7 @@ function admin_shifts()
$shifts[] = [
'start' => $interval_start,
'end' => $interval_end,
- 'room_id' => $rid,
+ 'location_id' => $lid,
'title' => $title,
'shift_type_id' => $shifttype_id,
'description' => $description,
@@ -300,17 +326,27 @@ function admin_shifts()
$shifts_table = [];
foreach ($shifts as $shift) {
+ $shiftType = $shifttypes_source->find($shift['shift_type_id']);
+ $location = $locations->find($shift['location_id']);
+
+ /** @var Carbon $start */
+ $start = $shift['start'];
+ /** @var Carbon $end */
+ $end = $shift['end'];
$shifts_table_entry = [
'timeslot' =>
icon('clock-history') . ' '
- . $shift['start']->format(__('Y-m-d H:i'))
+ . $start->format(__('general.datetime'))
. ' - '
- . $shift['end']->format(__('H:i'))
- . '
'
- . Room_name_render(Room::find($shift['room_id'])),
+ . ''
+ . $end->format(__('H:i'))
+ . ''
+ . ', ' . round($end->copy()->diffInMinutes($start) / 60, 2) . 'h'
+ . '
'
+ . location_name_render($location),
'title' =>
- ShiftType_name_render(ShiftType::find($shifttype_id))
- . ($shift['title'] ? '
' . $shift['title'] : ''),
+ htmlspecialchars($shiftType->name)
+ . ($shift['title'] ? '
' . htmlspecialchars($shift['title']) : ''),
'needed_angels' => '',
];
foreach ($types as $type) {
@@ -326,9 +362,9 @@ function admin_shifts()
$session->set('admin_shifts_shifts', $shifts);
$session->set('admin_shifts_types', $needed_angel_types);
- $hidden_types = '';
+ $previousEntries = [];
foreach ($needed_angel_types as $type_id => $count) {
- $hidden_types .= form_hidden('angeltype_count_' . $type_id, $count);
+ $previousEntries['angeltype_count_' . $type_id] = $count;
}
// Number of Shifts that will be created (if over 100 its danger-red)
@@ -338,28 +374,38 @@ function admin_shifts()
$shiftsCreationHint = '' . $shiftsCreationHint . '';
}
- return page_with_title(__('Preview'), [
+ // Save as previous state to be able to reuse it
+ $previousEntries += [
+ 'shifttype_id' => $shifttype_id,
+ 'description' => $description,
+ 'title' => $title,
+ 'lid' => $lid,
+ 'start' => $request->input('start'),
+ 'end' => $request->input('end'),
+ 'mode' => $mode,
+ 'length' => $length,
+ 'change_hours' => implode(', ', $change_hours),
+ 'angelmode' => $angelmode,
+ 'shift_over_midnight' => $shift_over_midnight ? 'true' : 'false',
+ ];
+ $session->set('admin_shifts_previous', $previousEntries);
+
+ $hidden_types = '';
+ foreach ($previousEntries as $name => $value) {
+ $hidden_types .= form_hidden($name, $value);
+ }
+
+ return page_with_title(__('form.preview'), [
form([
$hidden_types,
- form_hidden('shifttype_id', $shifttype_id),
- form_hidden('description', $description),
- form_hidden('title', $title),
- form_hidden('rid', $rid),
- form_hidden('start', $start->format('Y-m-d H:i')),
- form_hidden('end', $end->format('Y-m-d H:i')),
- form_hidden('mode', $mode),
- form_hidden('length', $length),
- form_hidden('change_hours', implode(', ', $change_hours)),
- form_hidden('angelmode', $angelmode),
- form_hidden('shift_over_midnight', $shift_over_midnight ? 'true' : 'false'),
- form_submit('back', icon('chevron-left') . __('back')),
+ form_submit('back', icon('chevron-left') . __('general.back')),
$shiftsCreationHint,
table([
'timeslot' => __('Time and location'),
'title' => __('Type and title'),
'needed_angels' => __('Needed angels'),
], $shifts_table),
- form_submit('submit', icon('save') . __('Save')),
+ form_submit('submit', icon('save') . __('form.save')),
]),
]);
}
@@ -368,7 +414,7 @@ function admin_shifts()
!is_array($session->get('admin_shifts_shifts'))
|| !is_array($session->get('admin_shifts_types'))
) {
- throw_redirect(page_link_to('admin_shifts'));
+ throw_redirect(url('/admin-shifts'));
}
$transactionId = Str::uuid();
@@ -379,15 +425,6 @@ function admin_shifts()
$shift->createdBy()->associate(auth()->user());
$shift->save();
- engelsystem_log(
- 'Shift created: ' . $shifttypes[$shift->shift_type_id]
- . ' with title ' . $shift->title
- . ' with description ' . $shift->description
- . ' from ' . $shift->start->format('Y-m-d H:i')
- . ' to ' . $shift->end->format('Y-m-d H:i')
- . ', transaction: ' . $transactionId
- );
-
$needed_angel_types_info = [];
foreach ($session->get('admin_shifts_types', []) as $type_id => $count) {
$angel_type_source = AngelType::find($type_id);
@@ -401,26 +438,37 @@ function admin_shifts()
$needed_angel_types_info[] = $angel_type_source->name . ': ' . $count;
}
}
- engelsystem_log('Shift needs following angel types: ' . join(', ', $needed_angel_types_info));
+
+ engelsystem_log(
+ 'Shift created: ' . $shifttypes[$shift->shift_type_id]
+ . ' (' . $shift->id . ')'
+ . ' with title ' . $shift->title
+ . ' and description ' . $shift->description
+ . ' from ' . $shift->start->format('Y-m-d H:i')
+ . ' to ' . $shift->end->format('Y-m-d H:i')
+ . ' in ' . $shift->location->name
+ . ' with angel types: ' . join(', ', $needed_angel_types_info)
+ . ', transaction: ' . $transactionId
+ );
}
success('Shifts created.');
- throw_redirect(page_link_to('admin_shifts'));
+ throw_redirect(url('/admin-shifts'));
} else {
$session->remove('admin_shifts_shifts');
$session->remove('admin_shifts_types');
}
- $rid = null;
- if ($request->has('rid')) {
- $rid = $request->input('rid');
+ $lid = null;
+ if ($request->has('lid')) {
+ $lid = $request->input('lid');
}
$angel_types = '';
foreach ($types as $type) {
$angel_types .= ''
. form_spinner(
'angeltype_count_' . $type->id,
- $type->name,
+ htmlspecialchars($type->name),
$needed_angel_types[$type->id],
[
'radio-name' => 'angelmode',
@@ -430,20 +478,36 @@ function admin_shifts()
. '
';
}
+ $link = button(url('/user-shifts'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ $reset = '';
+ if ($session->has('admin_shifts_previous')) {
+ $reset = form_submit(
+ 'back',
+ icon('arrow-counterclockwise'),
+ '',
+ false,
+ 'link',
+ __('Reset to previous state')
+ );
+ foreach ($session->get('admin_shifts_previous', []) as $name => $value) {
+ $reset .= form_hidden($name, $value);
+ }
+ }
+
return page_with_title(
- admin_shifts_title() . ' ' . sprintf(
+ $link . ' ' . admin_shifts_title() . ' ' . sprintf(
'%s',
- page_link_to('admin_shifts_history'),
+ url('/admin/shifts/history'),
icon('clock-history')
- ),
+ ) . form([$reset], '', 'display:inline'),
[
msg(),
form([
div('row', [
div('col-md-6 col-xl-5', [
form_select('shifttype_id', __('Shifttype'), $shifttypes, $shifttype_id),
- form_text('title', __('Title'), $title),
- form_select('rid', __('Room'), $room_array, $rid),
+ form_text('title', __('title.title'), $title),
+ form_select('lid', __('Location'), $location_array, $lid),
]),
div('col-md-6 col-xl-7', [
form_textarea('description', __('Additional description'), $description),
@@ -454,10 +518,22 @@ function admin_shifts()
div('col-md-6 col-xl-5', [
div('row', [
div('col-lg-6', [
- form_datetime('start', __('Start'), $start),
+ form_datetime(
+ 'start',
+ __('shifts.start'),
+ $request->has('start')
+ ? Carbon::createFromDatetime($request->input('start'))
+ : $start
+ ),
]),
div('col-lg-6', [
- form_datetime('end', __('End'), $end),
+ form_datetime(
+ 'end',
+ __('shifts.end'),
+ $request->has('end')
+ ? Carbon::createFromDatetime($request->input('end'))
+ : $end
+ ),
]),
]),
form_info(__('Mode')),
@@ -488,7 +564,7 @@ function admin_shifts()
'change_hours',
__('Shift change hours'),
$request->has('change_hours')
- ? $request->input('change_hours')
+ ? ($change_hours ? implode(', ', $change_hours) : $request->input('change_hours'))
: '00, 04, 08, 10, 12, 14, 16, 18, 20, 22',
false,
null,
@@ -509,7 +585,13 @@ function admin_shifts()
form_info(__('Needed angels')),
form_radio(
'angelmode',
- __('Take needed angels from room settings'),
+ __('Copy needed angels from shift type settings'),
+ $angelmode == 'shift_type',
+ 'shift_type'
+ ),
+ form_radio(
+ 'angelmode',
+ __('Copy needed angels from location settings'),
$angelmode == 'location',
'location'
),
@@ -524,104 +606,8 @@ function admin_shifts()
]),
]),
]),
- form_submit('preview', icon('search') . __('Preview')),
+ form_submit('preview', icon('eye') . __('form.preview'), 'btn-info'),
]),
]
);
}
-
-function admin_shifts_history_title(): string
-{
- return __('Shifts history');
-}
-
-/**
- * Display shifts transaction history
- *
- * @return string
- */
-function admin_shifts_history(): string
-{
- if (!auth()->can('admin_shifts')) {
- throw new HttpForbidden();
- }
-
- $request = request();
- $transactionId = $request->postData('transaction_id');
- if ($request->hasPostData('delete') && $transactionId) {
- $shifts = Shift::whereTransactionId($transactionId)->get();
-
- engelsystem_log('Deleting ' . count($shifts) . ' shifts (transaction id ' . $transactionId . ')');
-
- foreach ($shifts as $shift) {
- $shift = Shift($shift);
- foreach ($shift->shiftEntries as $entry) {
- event('shift.entry.deleting', [
- 'user' => $entry->user,
- 'start' => $shift->start,
- 'end' => $shift->end,
- 'name' => $shift->shiftType->name,
- 'title' => $shift->title,
- 'type' => $entry->angelType->name,
- 'room' => $shift->room,
- 'freeloaded' => $entry->freeloaded,
- ]);
- }
-
- $shift->delete();
-
- engelsystem_log(
- 'Deleted shift ' . $shift->title . ' / ' . $shift->shiftType->name
- . ' from ' . $shift->start->format('Y-m-d H:i')
- . ' to ' . $shift->end->format('Y-m-d H:i')
- );
- }
-
- success(sprintf(__('%s shifts deleted.'), count($shifts)));
- throw_redirect(page_link_to('admin_shifts_history'));
- }
-
- $schedules = Schedule::all()->pluck('name', 'id')->toArray();
- $shiftsData = Db::select('
- SELECT
- s.transaction_id,
- s.title,
- schedule_shift.schedule_id,
- COUNT(s.id) AS count,
- MIN(s.start) AS start,
- MAX(s.end) AS end,
- s.created_by AS user_id,
- MAX(s.created_at) AS created_at
- FROM shifts AS s
- LEFT JOIN schedule_shift on schedule_shift.shift_id = s.id
- WHERE s.transaction_id IS NOT NULL
- GROUP BY s.transaction_id
- ORDER BY created_at DESC
- ');
-
- foreach ($shiftsData as &$shiftData) {
- $shiftData['title'] = $shiftData['schedule_id'] ? __('shifts_history.schedule', [$schedules[$shiftData['schedule_id']]]) : $shiftData['title'];
- $shiftData['user'] = User_Nick_render(User::find($shiftData['user_id']));
- $shiftData['start'] = Carbon::make($shiftData['start'])->format(__('Y-m-d H:i'));
- $shiftData['end'] = Carbon::make($shiftData['end'])->format(__('Y-m-d H:i'));
- $shiftData['created_at'] = Carbon::make($shiftData['created_at'])->format(__('Y-m-d H:i'));
- $shiftData['actions'] = form([
- form_hidden('transaction_id', $shiftData['transaction_id']),
- form_submit('delete', icon('trash') . __('delete all'), 'btn-sm', true, 'danger'),
- ]);
- }
-
- return page_with_title(admin_shifts_history_title(), [
- msg(),
- table([
- 'transaction_id' => __('ID'),
- 'title' => __('Title'),
- 'count' => __('Count'),
- 'start' => __('Start'),
- 'end' => __('End'),
- 'user' => __('User'),
- 'created_at' => __('Created'),
- 'actions' => '',
- ], $shiftsData),
- ], true);
-}
diff --git a/includes/pages/admin_user.php b/includes/pages/admin_user.php
index 93ac2f099..5ea82bb40 100644
--- a/includes/pages/admin_user.php
+++ b/includes/pages/admin_user.php
@@ -1,6 +1,7 @@
can('user.info.edit');
+ $user_edit_shirt = auth()->can('user.edit.shirt');
+ $user_edit = auth()->can('user.edit');
+ $admin_arrive = auth()->can('admin_arrive');
if (!$request->has('id')) {
throw_redirect(users_link());
@@ -40,77 +45,110 @@ function admin_user()
}
$html .= __('Here you can change the user entry. Under the item \'Arrived\' the angel is marked as present, a yes at Active means that the angel was active.');
- if ($goodie_enabled) {
+ if ($goodie_enabled && $user_edit_shirt) {
if ($goodie_tshirt) {
$html .= ' ' . __('If the angel is active, it can claim a T-shirt. If T-shirt is set to \'Yes\', the angel already got their T-shirt.');
} else {
$html .= ' ' . __('If the angel is active, it can claim a goodie. If goodie is set to \'Yes\', the angel already got their goodie.');
}
}
- $html .= '
';
+ $html .= '
';
$html .= '';
- $html .= '
';
+ $html .= '
';
- $html .= form_info('', __('Please visit the angeltypes page or the users profile to manage the users angeltypes.'));
+ $html .= __('Here you can reset the password of this angel:');
- $html .= ' ' . __('Here you can reset the password of this angel:') . '';
- $html .= '
';
+ $html .= '
';
/** @var Group $my_highest_group */
$my_highest_group = $user->groups()->orderByDesc('id')->first();
@@ -157,7 +204,7 @@ function admin_user()
&& ($my_highest_group >= $angel_highest_group || is_null($angel_highest_group))
) {
$html .= __('Here you can define the user groups of the angel:') . '';
- $html .= '
';
+ $html .= '
';
}
$html .= buttons([
- button(user_delete_link($user_source->id), icon('trash') . __('delete'), 'btn-danger'),
+ button(user_delete_link($user_source->id), icon('trash') . __('form.delete'), 'btn-danger'),
]);
$html .= '
';
@@ -236,17 +286,30 @@ function admin_user()
break;
case 'save':
- $force_active = $user->state->force_active;
$user_source = User::find($user_id);
- if (auth()->can('admin_active')) {
- $force_active = $request->input('force_active');
+
+ $changed_email = false;
+ $email = $request->postData('eemail');
+ if (($user_source->email !== $email) && User::whereEmail($email)->exists()) {
+ $html .= error(__('settings.profile.email.already-taken') . "\n", true);
+ break;
}
if ($user_source->settings->email_human) {
- $user_source->email = $request->postData('eemail');
+ $changed_email = $user_source->email !== $email;
+ $user_source->email = $email;
}
- $nickValidation = User_validate_Nick($request->postData('eNick'));
- if ($nickValidation->isValid()) {
- $user_source->name = $nickValidation->getValue();
+
+ $changed_nick = false;
+ $nick = trim((string) $request->get('eNick'));
+ $nickValid = (new Username())->validate($nick);
+ if (($user_source->name !== $nick) && User::whereName($nick)->exists()) {
+ $html .= error(__('settings.profile.nick.already-taken') . "\n", true);
+ break;
+ }
+ $old_nick = $user_source->name;
+ if ($nickValid && $user_edit) {
+ $changed_nick = ($user_source->name !== $nick) || User::whereName($nick)->exists();
+ $user_source->name = $nick;
}
$user_source->save();
@@ -254,30 +317,49 @@ function admin_user()
$user_source->personalData->first_name = $request->postData('eVorname');
$user_source->personalData->last_name = $request->postData('eName');
}
- if ($goodie_tshirt) {
+ if ($goodie_tshirt && $user_edit_shirt) {
$user_source->personalData->shirt_size = $request->postData('eSize');
}
$user_source->personalData->save();
$user_source->contact->mobile = $request->postData('eHandy');
- $user_source->contact->dect = $request->postData('eDECT');
+ if (config('enable_dect')) {
+ $user_source->contact->dect = $request->postData('eDECT');
+ }
$user_source->contact->save();
- if ($goodie_enabled) {
+ if ($goodie_enabled && $user_edit_shirt) {
$user_source->state->got_shirt = $request->postData('eTshirt');
}
- $user_source->state->active = $request->postData('eAktiv');
- $user_source->state->force_active = $force_active;
+ if ($user_info_edit) {
+ $user_source->state->user_info = $request->postData('userInfo');
+ }
+ if ($admin_arrive) {
+ $user_source->state->arrived = $request->postData('arrive');
+ }
+
+ if ($user_edit_shirt) {
+ $user_source->state->active = $request->postData('eAktiv');
+ }
+ if (auth()->can('admin_active')) {
+ $user_source->state->force_active = $request->input('force_active');
+ }
$user_source->state->save();
engelsystem_log(
- 'Updated user: ' . $user_source->name . ' (' . $user_source->id . ')'
- . ($goodie_tshirt ? ', t-shirt: ' : '' . $user_source->personalData->shirt_size)
+ 'Updated user: ' . ($changed_nick
+ ? ('nick modified form ' . $old_nick . ' to ' . $user_source->name)
+ : $user_source->name)
+ . ' (' . $user_source->id . ')'
+ . ($changed_email ? ', email modified' : '')
+ . ($goodie_tshirt ? ', t-shirt-size: ' . $user_source->personalData->shirt_size : '')
+ . ', arrived: ' . $user_source->state->arrived
. ', active: ' . $user_source->state->active
. ', force-active: ' . $user_source->state->force_active
- . ($goodie_tshirt ? ', tshirt: ' : ', goodie: ' . $user_source->state->got_shirt)
+ . ($goodie_tshirt ? ', t-shirt: ' : ', goodie: ' . $user_source->state->got_shirt)
+ . ($user_info_edit ? ', user-info: ' . $user_source->state->user_info : '')
);
- $html .= success(__('Changes where saved.') . "\n", true);
+ $html .= success(__('Changes were saved.') . "\n", true);
break;
case 'change_pw':
@@ -299,9 +381,13 @@ function admin_user()
}
}
- return page_with_title(__('Edit user'), [
+ $link = button(url('/users', ['action' => 'view', 'user_id' => $user_id]), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title(
+ $link . ' ' . __('Edit user'),
+ [
$html,
- ]);
+ ]
+ );
}
/**
diff --git a/includes/pages/guest_login.php b/includes/pages/guest_login.php
deleted file mode 100644
index 9353b4c04..000000000
--- a/includes/pages/guest_login.php
+++ /dev/null
@@ -1,542 +0,0 @@
-user();
- $tshirt_sizes = config('tshirt_sizes');
- $goodie = GoodieType::from(config('goodie_type'));
- $goodie_enabled = $goodie !== GoodieType::None;
- $goodie_tshirt = $goodie === GoodieType::Tshirt;
- $enable_user_name = config('enable_user_name');
- $enable_dect = config('enable_dect');
- $enable_planned_arrival = config('enable_planned_arrival');
- $min_password_length = config('min_password_length');
- $enable_password = config('enable_password');
- $enable_pronoun = config('enable_pronoun');
- $enable_mobile_show = config('enable_mobile_show');
- $config = config();
- $request = request();
- $session = session();
- /** @var Connection $db */
- $db = app(Database::class)->getConnection();
- $is_oauth = $session->has('oauth2_connect_provider');
-
- $msg = '';
- $nick = '';
- $lastName = '';
- $preName = '';
- $dect = '';
- $mobile = '';
- $mobile_show = false;
- $email = '';
- $pronoun = '';
- $email_shiftinfo = false;
- $email_by_human_allowed = false;
- $email_messages = false;
- $email_news = false;
- $email_goody = false;
- $tshirt_size = '';
- $password_hash = '';
- $selected_angel_types = [];
- $planned_arrival_date = null;
-
- /** @var AngelType[]|Collection $angel_types_source */
- $angel_types_source = AngelType::all();
- $angel_types = [];
- if (!empty($session->get('oauth2_groups'))) {
- /** @var OAuth2 $oauth */
- $oauth = app()->get(OAuth2::class);
- $ssoTeams = $oauth->getSsoTeams($session->get('oauth2_connect_provider'));
- foreach ($ssoTeams as $name => $team) {
- if (in_array($name, $session->get('oauth2_groups'))) {
- $selected_angel_types[] = $team['id'];
- }
- }
- }
- foreach ($angel_types_source as $angel_type) {
- if ($angel_type->hide_register) {
- continue;
- }
- $angel_types[$angel_type->id] = $angel_type->name
- . ($angel_type->restricted ? ' (' . __('Requires introduction') . ')' : '');
- if (!$angel_type->restricted) {
- $selected_angel_types[] = $angel_type->id;
- }
- }
-
- $oauth_enable_password = $session->get('oauth2_enable_password');
- if (!is_null($oauth_enable_password)) {
- $enable_password = $oauth_enable_password;
- }
-
- if (
- !auth()->can('register') // No registration permission
- // Not authenticated and
- || (!$authUser && !config('registration_enabled') && !$session->get('oauth2_allow_registration')) // Registration disabled
- || (!$authUser && !$enable_password && !$is_oauth) // Password disabled and not oauth
- ) {
- error(__('Registration is disabled.'));
-
- return page_with_title(register_title(), [
- msg(),
- ]);
- }
-
- if ($request->hasPostData('submit')) {
- $valid = true;
-
- if ($request->has('username')) {
- $nickValidation = User_validate_Nick($request->input('username'));
- $nick = $nickValidation->getValue();
-
- if (!$nickValidation->isValid()) {
- $valid = false;
- $msg .= error(sprintf(
- __('Please enter a valid nick.') . ' ' . __('Use up to 24 letters, numbers, connecting punctuations or spaces for your nickname.'),
- $nick
- ), true);
- }
- if (User::whereName($nick)->count() > 0) {
- $valid = false;
- $msg .= error(sprintf(__('Your nick "%s" already exists.'), htmlspecialchars($nick)), true);
- }
- } else {
- $valid = false;
- $msg .= error(__('Please enter a nickname.'), true);
- }
-
- if ($request->has('mobile_show') && $enable_mobile_show) {
- $mobile_show = true;
- }
-
- if ($request->has('email') && strlen(strip_request_item('email')) > 0) {
- $email = strip_request_item('email');
- if (!check_email($email)) {
- $valid = false;
- $msg .= error(__('E-mail address is not correct.'), true);
- }
- if (User::whereEmail($email)->first()) {
- $valid = false;
- $msg .= error(__('E-mail address is already used by another user.'), true);
- }
- } else {
- $valid = false;
- $msg .= error(__('Please enter your e-mail.'), true);
- }
-
- if ($request->has('email_shiftinfo')) {
- $email_shiftinfo = true;
- }
-
- if ($request->has('email_by_human_allowed')) {
- $email_by_human_allowed = true;
- }
-
- if ($request->has('email_messages')) {
- $email_messages = true;
- }
-
- if ($request->has('email_news')) {
- $email_news = true;
- }
-
- if ($request->has('email_goody')) {
- $email_goody = true;
- }
-
- if ($goodie_tshirt) {
- if ($request->has('tshirt_size') && isset($tshirt_sizes[$request->input('tshirt_size')])) {
- $tshirt_size = $request->input('tshirt_size');
- } else {
- $valid = false;
- $msg .= error(__('Please select your shirt size.'), true);
- }
- }
-
- if ($enable_password && $request->has('password') && strlen($request->postData('password')) >= $min_password_length) {
- if ($request->postData('password') != $request->postData('password2')) {
- $valid = false;
- $msg .= error(__('Your passwords don\'t match.'), true);
- }
- } elseif ($enable_password) {
- $valid = false;
- $msg .= error(sprintf(
- __('Your password is too short (please use at least %s characters).'),
- $min_password_length
- ), true);
- }
-
- if ($request->has('planned_arrival_date') && $enable_planned_arrival) {
- $tmp = parse_date('Y-m-d H:i', $request->input('planned_arrival_date') . ' 00:00');
- $result = User_validate_planned_arrival_date($tmp);
- $planned_arrival_date = $result->getValue();
- if (!$result->isValid()) {
- $valid = false;
- error(__('Please enter your planned date of arrival. It should be after the buildup start date and before teardown end date.'));
- }
- } elseif ($enable_planned_arrival) {
- $valid = false;
- error(__('Please enter your planned date of arrival. It should be after the buildup start date and before teardown end date.'));
- }
-
- $selected_angel_types = [];
- foreach (array_keys($angel_types) as $angel_type_id) {
- if ($request->has('angel_types_' . $angel_type_id)) {
- $selected_angel_types[] = $angel_type_id;
- }
- }
-
- // Trivia
- if ($enable_user_name && $request->has('lastname')) {
- $lastName = strip_request_item('lastname');
- }
- if ($enable_user_name && $request->has('prename')) {
- $preName = strip_request_item('prename');
- }
- if ($enable_pronoun && $request->has('pronoun')) {
- $pronoun = strip_request_item('pronoun');
- }
- if ($enable_dect && $request->has('dect')) {
- if (strlen(strip_request_item('dect')) <= 40) {
- $dect = strip_request_item('dect');
- } else {
- $valid = false;
- error(__('For dect numbers are only 40 digits allowed.'));
- }
- }
- if ($request->has('mobile')) {
- $mobile = strip_request_item('mobile');
- }
-
- if ($valid) {
- // Safeguard against partially created user data
- $db->beginTransaction();
-
- $user = new User([
- 'name' => $nick,
- 'password' => $password_hash,
- 'email' => $email,
- 'api_key' => '',
- 'last_login_at' => null,
- ]);
- $user->save();
-
- $contact = new Contact([
- 'dect' => $dect,
- 'mobile' => $mobile,
- ]);
- $contact->user()
- ->associate($user)
- ->save();
-
- $personalData = new PersonalData([
- 'first_name' => $preName,
- 'last_name' => $lastName,
- 'pronoun' => $pronoun,
- 'shirt_size' => $tshirt_size,
- 'planned_arrival_date' => $enable_planned_arrival ? Carbon::createFromTimestamp($planned_arrival_date) : null,
- ]);
- $personalData->user()
- ->associate($user)
- ->save();
-
- $settings = new Settings([
- 'language' => $session->get('locale'),
- 'theme' => config('theme'),
- 'email_human' => $email_by_human_allowed,
- 'email_messages' => $email_messages,
- 'email_goody' => $email_goody,
- 'email_shiftinfo' => $email_shiftinfo,
- 'email_news' => $email_news,
- 'mobile_show' => $mobile_show,
- ]);
- $settings->user()
- ->associate($user)
- ->save();
-
- $state = new State([]);
- if (config('autoarrive')) {
- $state->arrived = true;
- $state->arrival_date = new Carbon();
- }
- $state->user()
- ->associate($user)
- ->save();
-
- if ($session->has('oauth2_connect_provider') && $session->has('oauth2_user_id')) {
- $oauth = new OAuth([
- 'provider' => $session->get('oauth2_connect_provider'),
- 'identifier' => $session->get('oauth2_user_id'),
- 'access_token' => $session->get('oauth2_access_token'),
- 'refresh_token' => $session->get('oauth2_refresh_token'),
- 'expires_at' => $session->get('oauth2_expires_at'),
- ]);
- $oauth->user()
- ->associate($user)
- ->save();
-
- $session->remove('oauth2_connect_provider');
- $session->remove('oauth2_user_id');
- $session->remove('oauth2_access_token');
- $session->remove('oauth2_refresh_token');
- $session->remove('oauth2_expires_at');
- }
-
- // Assign user-group and set password
- $defaultGroup = Group::find(auth()->getDefaultRole());
- $user->groups()->attach($defaultGroup);
- if ($enable_password) {
- auth()->setPassword($user, $request->postData('password'));
- }
-
- // Assign angel-types
- $user_angel_types_info = [];
- foreach ($selected_angel_types as $selected_angel_type_id) {
- $angelType = AngelType::findOrFail($selected_angel_type_id);
- $user->userAngelTypes()->attach($angelType);
- $user_angel_types_info[] = $angelType->name;
- }
-
- // Commit complete user data
- $db->commit();
-
- engelsystem_log(
- 'User ' . User_Nick_render($user, true)
- . ' signed up as: ' . join(', ', $user_angel_types_info)
- );
- success(__('Angel registration successful!'));
-
- // User is already logged in - that means a supporter has registered an angel. Return to register page.
- if ($authUser) {
- throw_redirect(page_link_to('register'));
- }
-
- // If a welcome message is present, display it on the next page
- if ($config->get('welcome_msg')) {
- $session->set('show_welcome', true);
- }
-
- // Login the user
- if ($user->oauth->count()) {
- /** @var OAuth $provider */
- $provider = $user->oauth->first();
- throw_redirect(url('/oauth/' . $provider->provider));
- }
-
- throw_redirect(page_link_to('/'));
- }
- }
-
- $buildup_start_date = time();
- $teardown_end_date = null;
- if ($buildup = $config->get('buildup_start')) {
- /** @var Carbon $buildup */
- $buildup_start_date = $buildup->getTimestamp();
- }
-
- if ($teardown = $config->get('teardown_end')) {
- /** @var Carbon $teardown */
- $teardown_end_date = $teardown->getTimestamp();
- }
-
- $form_data = $session->get('form_data');
- $session->remove('form_data');
- if (!$nick && !empty($form_data['name'])) {
- $nick = $form_data['name'];
- }
-
- if (!$email && !empty($form_data['email'])) {
- $email = $form_data['email'];
- }
-
- if (!$preName && !empty($form_data['first_name'])) {
- $preName = $form_data['first_name'];
- }
-
- if (!$lastName && !empty($form_data['last_name'])) {
- $lastName = $form_data['last_name'];
- }
-
- return page_with_title(register_title(), [
- __('By completing this form you\'re registering as a Chaos-Angel. This script will create you an account in the angel task scheduler.'),
- form_info(entry_required() . ' = ' . __('Entry required!')),
- $msg,
- msg(),
- form([
- div('row', [
- div('col', [
- form_text(
- 'username',
- __('Nick') . ' ' . entry_required(),
- $nick,
- false,
- 24,
- 'nickname'
- ),
- form_info(
- '',
- __('Use up to 24 letters, numbers, connecting punctuations or spaces for your nickname.')
- ),
- ]),
-
- $enable_pronoun ? div('col', [
- form_text('pronoun', __('Pronoun'), $pronoun, false, 15),
- ]) : '',
- ]),
-
- $enable_user_name ? div('row', [
- div('col', [
- form_text('prename', __('First name'), $preName, false, 64, 'given-name'),
- ]),
- div('col', [
- form_text('lastname', __('Last name'), $lastName, false, 64, 'family-name'),
- ]),
- ]) : '',
-
- div('row', [
- div('col', [
- form_email(
- 'email',
- __('E-Mail') . ' ' . entry_required(),
- $email,
- false,
- 'email',
- 254
- ),
- form_checkbox(
- 'email_shiftinfo',
- __(
- 'The %s is allowed to send me an email (e.g. when my shifts change)',
- [config('app_name')]
- ),
- $email_shiftinfo
- ),
- form_checkbox(
- 'email_news',
- __('Notify me of new news'),
- $email_news
- ),
- form_checkbox(
- 'email_messages',
- __('settings.profile.email_messages'),
- $email_messages
- ),
- form_checkbox(
- 'email_by_human_allowed',
- __('Allow heaven angels to contact you by e-mail.'),
- $email_by_human_allowed
- ),
- $goodie_enabled ?
- form_checkbox(
- 'email_goody',
- __('To receive vouchers, give consent that nick, email address, worked hours and shirt size will be stored until the next similar event.')
- . (config('privacy_email') ? ' ' . __('To withdraw your approval, send an email to %1$s.', [config('privacy_email')]) : ''),
- $email_goody
- ) : '',
- ]),
-
- $enable_dect ? div('col', [
- form_text('dect', __('DECT'), $dect, false, 40, 'tel-local'),
- ]) : '',
-
- div('col', [
- form_text('mobile', __('Mobile'), $mobile, false, 40, 'tel-national'),
- $enable_mobile_show ? form_checkbox(
- 'mobile_show',
- __('Show mobile number to other users to contact me'),
- $mobile_show
- ) : '',
- ]),
- ]),
-
- div('row', [
- $enable_password ? div('col', [
- form_password('password', __('Password') . ' ' . entry_required(), 'new-password'),
- ]) : '',
-
- $enable_planned_arrival ? div('col', [
- form_date(
- 'planned_arrival_date',
- __('Planned date of arrival') . ' ' . entry_required(),
- $planned_arrival_date,
- $buildup_start_date,
- $teardown_end_date
- ),
- ]) : '',
- ]),
-
- div('row', [
- $enable_password ? div('col', [
- form_password('password2', __('Confirm password') . ' ' . entry_required(), 'new-password'),
- ]) : '',
-
- div('col', [
- $goodie_tshirt ? form_select(
- 'tshirt_size',
- __('Shirt size') . ' ' . entry_required(),
- $tshirt_sizes,
- $tshirt_size,
- __('Please select...')
- ) : '',
- ]),
- ]),
-
- div('row', [
- div('col', [
- form_checkboxes(
- 'angel_types',
- __('What do you want to do?') . sprintf(
- ' (%s)',
- url('/angeltypes/about'),
- __('Description of job types')
- ),
- $angel_types,
- $selected_angel_types
- ),
- form_info(
- '',
- __('Some angel types have to be confirmed later by a supporter at an introduction meeting. You can change your selection in the options section.')
- ),
- ]),
- ]),
-
- form_submit('submit', __('Register')),
- ]),
- ]);
-}
-
-/**
- * @return string
- */
-function entry_required()
-{
- return icon('exclamation-triangle', 'text-info');
-}
diff --git a/includes/pages/schedule/ImportSchedule.php b/includes/pages/schedule/ImportSchedule.php
index e1a940cea..fed44373c 100644
--- a/includes/pages/schedule/ImportSchedule.php
+++ b/includes/pages/schedule/ImportSchedule.php
@@ -16,7 +16,7 @@
use Engelsystem\Helpers\Uuid;
use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
-use Engelsystem\Models\Room as RoomModel;
+use Engelsystem\Models\Location;
use Engelsystem\Models\Shifts\Schedule as ScheduleUrl;
use Engelsystem\Models\Shifts\ScheduleShift;
use Engelsystem\Models\Shifts\Shift;
@@ -91,14 +91,14 @@ public function index(): Response
public function edit(Request $request): Response
{
$scheduleId = $request->getAttribute('schedule_id'); // optional
-
$schedule = ScheduleUrl::find($scheduleId);
return $this->response->withView(
'admin/schedule/edit.twig',
[
'schedule' => $schedule,
- 'shift_types' => ShiftType::all()->pluck('name', 'id'),
+ 'shift_types' => ShiftType::all()->sortBy('name')->pluck('name', 'id'),
+ 'locations' => Location::all()->sortBy('name')->pluck('name', 'id'),
]
);
}
@@ -110,13 +110,24 @@ public function save(Request $request): Response
/** @var ScheduleUrl $schedule */
$schedule = ScheduleUrl::findOrNew($scheduleId);
+ if ($request->request->has('delete')) {
+ return $this->delete($schedule);
+ }
+
+ $locationsList = Location::all()->pluck('id');
+ $locationsValidation = [];
+ foreach ($locationsList as $id) {
+ $locationsValidation['location_' . $id] = 'optional|checked';
+ }
+
$data = $this->validate($request, [
'name' => 'required',
'url' => 'required',
'shift_type' => 'required|int',
+ 'needed_from_shift_type' => 'optional|checked',
'minutes_before' => 'int',
'minutes_after' => 'int',
- ]);
+ ] + $locationsValidation);
if (!ShiftType::find($data['shift_type'])) {
throw new ErrorException('schedule.import.invalid-shift-type');
@@ -125,19 +136,35 @@ public function save(Request $request): Response
$schedule->name = $data['name'];
$schedule->url = $data['url'];
$schedule->shift_type = $data['shift_type'];
+ $schedule->needed_from_shift_type = (bool) $data['needed_from_shift_type'];
$schedule->minutes_before = $data['minutes_before'];
$schedule->minutes_after = $data['minutes_after'];
$schedule->save();
+ $schedule->activeLocations()->detach();
+
+ $for = new Collection();
+ foreach ($locationsList as $id) {
+ if (!$data['location_' . $id]) {
+ continue;
+ }
+
+ $location = Location::find($id);
+ $schedule->activeLocations()->attach($location);
+ $for[] = $location->name;
+ }
$this->log->info(
- 'Schedule {name}: Url {url}, Shift Type {shift_type}, minutes before/after {before}/{after}',
+ 'Schedule {name}: Url {url}, Shift Type {shift_type}, ({need}), '
+ . 'minutes before/after {before}/{after}, for: {locations}',
[
'name' => $schedule->name,
'url' => $schedule->name,
'shift_type' => $schedule->shift_type,
+ 'need' => $schedule->needed_from_shift_type ? 'from shift type' : 'from room',
'before' => $schedule->minutes_before,
'after' => $schedule->minutes_after,
+ 'locations' => $for->implode(', '),
]
);
@@ -146,6 +173,33 @@ public function save(Request $request): Response
return redirect('/admin/schedule/load/' . $schedule->id);
}
+ protected function delete(ScheduleUrl $schedule): Response
+ {
+ foreach ($schedule->scheduleShifts as $scheduleShift) {
+ // Only guid is needed here
+ $event = new Event(
+ $scheduleShift->guid,
+ 0,
+ new Room(''),
+ '',
+ '',
+ '',
+ Carbon::now(),
+ '',
+ '',
+ '',
+ '',
+ ''
+ );
+
+ $this->deleteEvent($event, $schedule);
+ }
+ $schedule->delete();
+
+ $this->addNotification('schedule.delete.success');
+ return redirect('/admin/schedule');
+ }
+
public function loadSchedule(Request $request): Response
{
try {
@@ -179,7 +233,7 @@ public function loadSchedule(Request $request): Response
[
'schedule_id' => $scheduleUrl->id,
'schedule' => $schedule,
- 'rooms' => [
+ 'locations' => [
'add' => $newRooms,
],
'shifts' => [
@@ -218,15 +272,15 @@ public function importSchedule(Request $request): Response
$this->log('Started schedule "{name}" import', ['name' => $scheduleUrl->name]);
foreach ($newRooms as $room) {
- $this->createRoom($room);
+ $this->createLocation($room);
}
- $rooms = $this->getAllRooms();
+ $locations = $this->getAllLocations();
foreach ($newEvents as $event) {
$this->createEvent(
$event,
$shiftType,
- $rooms
+ $locations
->where('name', $event->getRoom()->getName())
->first(),
$scheduleUrl
@@ -237,15 +291,15 @@ public function importSchedule(Request $request): Response
$this->updateEvent(
$event,
$shiftType,
- $rooms
+ $locations
->where('name', $event->getRoom()->getName())
- ->first()
+ ->first(),
+ $scheduleUrl
);
}
foreach ($deleteEvents as $event) {
- $this->fireDeleteShiftEntryEvents($event);
- $this->deleteEvent($event);
+ $this->deleteEvent($event, $scheduleUrl);
}
$scheduleUrl->touch();
@@ -255,29 +309,30 @@ public function importSchedule(Request $request): Response
return redirect($this->url, 303);
}
- protected function createRoom(Room $room): void
+ protected function createLocation(Room $room): void
{
- $roomModel = new RoomModel();
- $roomModel->name = $room->getName();
- $roomModel->save();
+ $location = new Location();
+ $location->name = $room->getName();
+ $location->save();
- $this->log('Created schedule room "{room}"', ['room' => $room->getName()]);
+ $this->log('Created schedule location "{location}"', ['location' => $room->getName()]);
}
- protected function fireDeleteShiftEntryEvents(Event $event): void
+ protected function fireDeleteShiftEntryEvents(Event $event, ScheduleUrl $schedule): void
{
$shiftEntries = $this->db
->table('shift_entries')
->select([
- 'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'rooms.id AS room_id',
+ 'shift_types.name', 'shifts.title', 'angel_types.name AS type', 'locations.id AS location_id',
'shifts.start', 'shifts.end', 'shift_entries.user_id', 'shift_entries.freeloaded',
])
->join('shifts', 'shifts.id', 'shift_entries.shift_id')
->join('schedule_shift', 'shifts.id', 'schedule_shift.shift_id')
- ->join('rooms', 'rooms.id', 'shifts.room_id')
+ ->join('locations', 'locations.id', 'shifts.location_id')
->join('angel_types', 'angel_types.id', 'shift_entries.angel_type_id')
->join('shift_types', 'shift_types.id', 'shifts.shift_type_id')
->where('schedule_shift.guid', $event->getGuid())
+ ->where('schedule_shift.schedule_id', $schedule->id)
->get();
foreach ($shiftEntries as $shiftEntry) {
@@ -288,13 +343,13 @@ protected function fireDeleteShiftEntryEvents(Event $event): void
'name' => $shiftEntry->name,
'title' => $shiftEntry->title,
'type' => $shiftEntry->type,
- 'room' => RoomModel::find($shiftEntry->room_id),
+ 'location' => Location::find($shiftEntry->location_id),
'freeloaded' => $shiftEntry->freeloaded,
]);
}
}
- protected function createEvent(Event $event, int $shiftTypeId, RoomModel $room, ScheduleUrl $scheduleUrl): void
+ protected function createEvent(Event $event, int $shiftTypeId, Location $location, ScheduleUrl $scheduleUrl): void
{
$user = auth()->user();
$eventTimeZone = Carbon::now()->timezone;
@@ -304,7 +359,7 @@ protected function createEvent(Event $event, int $shiftTypeId, RoomModel $room,
$shift->shift_type_id = $shiftTypeId;
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
- $shift->room()->associate($room);
+ $shift->location()->associate($location);
$shift->url = $event->getUrl() ?? '';
$shift->transaction_id = Uuid::uuidBy($scheduleUrl->id, '5c4ed01e');
$shift->createdBy()->associate($user);
@@ -316,68 +371,82 @@ protected function createEvent(Event $event, int $shiftTypeId, RoomModel $room,
$scheduleShift->save();
$this->log(
- 'Created schedule shift "{shift}" in "{room}" ({from} {to}, {guid})',
+ 'Created schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
[
- 'shift' => $shift->title,
- 'room' => $shift->room->name,
- 'from' => $shift->start->format(DateTimeInterface::RFC3339),
- 'to' => $shift->end->format(DateTimeInterface::RFC3339),
- 'guid' => $scheduleShift->guid,
+ 'shift' => $shift->title,
+ 'location' => $shift->location->name,
+ 'from' => $shift->start->format(DateTimeInterface::RFC3339),
+ 'to' => $shift->end->format(DateTimeInterface::RFC3339),
+ 'guid' => $scheduleShift->guid,
]
);
}
- protected function updateEvent(Event $event, int $shiftTypeId, RoomModel $room): void
+ protected function updateEvent(Event $event, int $shiftTypeId, Location $location, ScheduleUrl $schedule): void
{
$user = auth()->user();
$eventTimeZone = Carbon::now()->timezone;
/** @var ScheduleShift $scheduleShift */
- $scheduleShift = ScheduleShift::whereGuid($event->getGuid())->first();
+ $scheduleShift = ScheduleShift::whereGuid($event->getGuid())->where('schedule_id', $schedule->id)->first();
$shift = $scheduleShift->shift;
+ $oldShift = Shift::find($shift->id);
$shift->title = $event->getTitle();
$shift->shift_type_id = $shiftTypeId;
$shift->start = $event->getDate()->copy()->timezone($eventTimeZone);
$shift->end = $event->getEndDate()->copy()->timezone($eventTimeZone);
- $shift->room()->associate($room);
+ $shift->location()->associate($location);
$shift->url = $event->getUrl() ?? '';
$shift->updatedBy()->associate($user);
$shift->save();
+ $this->fireUpdateShiftUpdateEvent($oldShift, $shift);
+
$this->log(
- 'Updated schedule shift "{shift}" in "{room}" ({from} {to}, {guid})',
+ 'Updated schedule shift "{shift}" in "{location}" ({from} {to}, {guid})',
[
- 'shift' => $shift->title,
- 'room' => $shift->room->name,
- 'from' => $shift->start->format(DateTimeInterface::RFC3339),
- 'to' => $shift->end->format(DateTimeInterface::RFC3339),
- 'guid' => $scheduleShift->guid,
+ 'shift' => $shift->title,
+ 'location' => $shift->location->name,
+ 'from' => $shift->start->format(DateTimeInterface::RFC3339),
+ 'to' => $shift->end->format(DateTimeInterface::RFC3339),
+ 'guid' => $scheduleShift->guid,
]
);
}
- protected function deleteEvent(Event $event): void
+ protected function deleteEvent(Event $event, ScheduleUrl $schedule): void
{
/** @var ScheduleShift $scheduleShift */
- $scheduleShift = ScheduleShift::whereGuid($event->getGuid())->first();
+ $scheduleShift = ScheduleShift::whereGuid($event->getGuid())->where('schedule_id', $schedule->id)->first();
$shift = $scheduleShift->shift;
$shift->delete();
+ $scheduleShift->delete();
+
+ $this->fireDeleteShiftEntryEvents($event, $schedule);
$this->log(
- 'Deleted schedule shift "{shift}" in {room} ({from} {to}, {guid})',
+ 'Deleted schedule shift "{shift}" in {location} ({from} {to}, {guid})',
[
- 'shift' => $shift->title,
- 'room' => $shift->room->name,
- 'from' => $shift->start->format(DateTimeInterface::RFC3339),
- 'to' => $shift->end->format(DateTimeInterface::RFC3339),
- 'guid' => $scheduleShift->guid,
+ 'shift' => $shift->title,
+ 'location' => $shift->location->name,
+ 'from' => $shift->start->format(DateTimeInterface::RFC3339),
+ 'to' => $shift->end->format(DateTimeInterface::RFC3339),
+ 'guid' => $scheduleShift->guid,
]
);
}
+ protected function fireUpdateShiftUpdateEvent(Shift $oldShift, Shift $newShift): void
+ {
+ event('shift.updating', [
+ 'shift' => $newShift,
+ 'oldShift' => $oldShift,
+ ]);
+ }
+
/**
* @param Request $request
- * @return Event[]|Room[]|RoomModel[]
+ * @return Event[]|Room[]|Location[]
* @throws ErrorException
*/
protected function getScheduleData(Request $request)
@@ -420,10 +489,10 @@ protected function getScheduleData(Request $request)
protected function newRooms(array $scheduleRooms): array
{
$newRooms = [];
- $allRooms = $this->getAllRooms();
+ $allLocations = $this->getAllLocations();
foreach ($scheduleRooms as $room) {
- if ($allRooms->where('name', $room->getName())->count()) {
+ if ($allLocations->where('name', $room->getName())->count()) {
continue;
}
@@ -456,11 +525,15 @@ protected function shiftsDiff(
$scheduleEvents = [];
/** @var Event[] $deleteEvents */
$deleteEvents = [];
- $rooms = $this->getAllRooms();
+ $locations = $this->getAllLocations();
$eventTimeZone = Carbon::now()->timezone;
foreach ($schedule->getDay() as $day) {
foreach ($day->getRoom() as $room) {
+ if (!$scheduleUrl->activeLocations->where('name', $room->getName())->count()) {
+ continue;
+ }
+
foreach ($room->getEvent() as $event) {
$scheduleEvents[$event->getGuid()] = $event;
@@ -477,19 +550,18 @@ protected function shiftsDiff(
$scheduleEventsGuidList = array_keys($scheduleEvents);
$existingShifts = $this->getScheduleShiftsByGuid($scheduleUrl, $scheduleEventsGuidList);
- foreach ($existingShifts as $shift) {
- $guid = $shift->guid;
- /** @var Shift $shift */
- $shift = Shift::with('room')->find($shift->shift_id);
+ foreach ($existingShifts as $scheduleShift) {
+ $guid = $scheduleShift->guid;
+ $shift = $scheduleShift->shift;
$event = $scheduleEvents[$guid];
- $room = $rooms->where('name', $event->getRoom()->getName())->first();
+ $location = $locations->where('name', $event->getRoom()->getName())->first();
if (
$shift->title != $event->getTitle()
|| $shift->shift_type_id != $shiftType
|| $shift->start != $event->getDate()
|| $shift->end != $event->getEndDate()
- || $shift->room_id != ($room->id ?? '')
+ || $shift->location_id != ($location->id ?? '')
|| $shift->url != ($event->getUrl() ?? '')
) {
$changeEvents[$guid] = $event;
@@ -503,8 +575,8 @@ protected function shiftsDiff(
}
$scheduleShifts = $this->getScheduleShiftsWhereNotGuid($scheduleUrl, $scheduleEventsGuidList);
- foreach ($scheduleShifts as $shift) {
- $event = $this->eventFromScheduleShift($shift);
+ foreach ($scheduleShifts as $scheduleShift) {
+ $event = $this->eventFromScheduleShift($scheduleShift);
$deleteEvents[$event->getGuid()] = $event;
}
@@ -513,14 +585,13 @@ protected function shiftsDiff(
protected function eventFromScheduleShift(ScheduleShift $scheduleShift): Event
{
- /** @var Shift $shift */
- $shift = Shift::with('room')->find($scheduleShift->shift_id);
+ $shift = $scheduleShift->shift;
$duration = $shift->start->diff($shift->end);
return new Event(
$scheduleShift->guid,
0,
- new Room($shift->room->name),
+ new Room($shift->location->name),
$shift->title,
'',
'n/a',
@@ -534,11 +605,11 @@ protected function eventFromScheduleShift(ScheduleShift $scheduleShift): Event
}
/**
- * @return RoomModel[]|Collection
+ * @return Location[]|Collection
*/
- protected function getAllRooms(): Collection
+ protected function getAllLocations(): Collection
{
- return RoomModel::all();
+ return Location::all();
}
/**
@@ -548,7 +619,7 @@ protected function getAllRooms(): Collection
*/
protected function getScheduleShiftsByGuid(ScheduleUrl $scheduleUrl, array $events)
{
- return ScheduleShift::query()
+ return ScheduleShift::with('shift.location')
->whereIn('guid', $events)
->where('schedule_id', $scheduleUrl->id)
->get();
@@ -561,7 +632,7 @@ protected function getScheduleShiftsByGuid(ScheduleUrl $scheduleUrl, array $even
*/
protected function getScheduleShiftsWhereNotGuid(ScheduleUrl $scheduleUrl, array $events)
{
- return ScheduleShift::query()
+ return ScheduleShift::with('shift.location')
->whereNotIn('guid', $events)
->where('schedule_id', $scheduleUrl->id)
->get();
diff --git a/includes/pages/user_myshifts.php b/includes/pages/user_myshifts.php
index 0dbc8823d..06461f387 100644
--- a/includes/pages/user_myshifts.php
+++ b/includes/pages/user_myshifts.php
@@ -8,7 +8,7 @@
*/
function myshifts_title()
{
- return __('My shifts');
+ return __('profile.my-shifts');
}
/**
@@ -35,23 +35,24 @@ function user_myshifts()
$shifts_user = User::find($shift_entry_id);
if ($request->has('reset')) {
if ($request->input('reset') == 'ack') {
- User_reset_api_key($user);
+ auth()->resetApiKey($user);
+ engelsystem_log(sprintf('API key resetted (%s).', User_Nick_render($user, true)));
success(__('Key changed.'));
- throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
+ throw_redirect(url('/users', ['action' => 'view', 'user_id' => $shifts_user->id]));
}
return page_with_title(__('Reset API key'), [
error(
__('If you reset the key, the url to your iCal- and JSON-export and your atom/rss feed changes! You have to update it in every application using one of these exports.'),
true
),
- button(page_link_to('user_myshifts', ['reset' => 'ack']), __('Continue'), 'btn-danger'),
+ button(url('/user-myshifts', ['reset' => 'ack']), __('Continue'), 'btn-danger'),
]);
} elseif ($request->has('edit') && preg_match('/^\d+$/', $request->input('edit'))) {
$shift_entry_id = $request->input('edit');
/** @var ShiftEntry $shiftEntry */
$shiftEntry = ShiftEntry::where('id', $shift_entry_id)
->where('user_id', $shifts_user->id)
- ->with(['shift', 'shift.shiftType', 'shift.room', 'user'])
+ ->with(['shift', 'shift.shiftType', 'shift.location', 'user'])
->first();
if (!empty($shiftEntry)) {
$shift = $shiftEntry->shift;
@@ -90,14 +91,14 @@ function user_myshifts()
. '. Freeloaded: ' . ($freeloaded ? 'YES Comment: ' . $freeloaded_comment : 'NO')
);
success(__('Shift saved.'));
- throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
+ throw_redirect(url('/users', ['action' => 'view', 'user_id' => $shifts_user->id]));
}
}
return ShiftEntry_edit_view(
$shifts_user,
- $shift->start->format(__('Y-m-d H:i')) . ', ' . shift_length($shift),
- $shift->room->name,
+ $shift->start->format(__('general.datetime')) . ', ' . shift_length($shift),
+ $shift->location->name,
$shift->shiftType->name,
$shiftEntry->angelType->name,
$shiftEntry->user_comment,
@@ -106,10 +107,10 @@ function user_myshifts()
auth()->can('user_shifts_admin')
);
} else {
- throw_redirect(page_link_to('user_myshifts'));
+ throw_redirect(url('/user-myshifts'));
}
}
- throw_redirect(page_link_to('users', ['action' => 'view', 'user_id' => $shifts_user->id]));
+ throw_redirect(url('/users', ['action' => 'view', 'user_id' => $shifts_user->id]));
return '';
}
diff --git a/includes/pages/user_shifts.php b/includes/pages/user_shifts.php
index c471dc76a..5f584630e 100644
--- a/includes/pages/user_shifts.php
+++ b/includes/pages/user_shifts.php
@@ -3,7 +3,9 @@
use Engelsystem\Database\Db;
use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\AngelType;
-use Engelsystem\Models\Room;
+use Engelsystem\Models\Location;
+use Engelsystem\Models\Shifts\NeededAngelType;
+use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\UserAngelType;
use Engelsystem\ShiftsFilter;
use Illuminate\Database\Eloquent\Builder;
@@ -32,7 +34,7 @@ function user_shifts()
$request = request();
if (auth()->user()->isFreeloader()) {
- throw_redirect(page_link_to('user_myshifts'));
+ throw_redirect(url('/user-myshifts'));
}
if ($request->has('edit_shift')) {
@@ -105,23 +107,42 @@ function update_ShiftsFilter(ShiftsFilter $shiftsFilter, $user_shifts_admin, $da
{
$shiftsFilter->setUserShiftsAdmin($user_shifts_admin);
$shiftsFilter->setFilled(check_request_int_array('filled', $shiftsFilter->getFilled()));
- $shiftsFilter->setRooms(check_request_int_array('rooms', $shiftsFilter->getRooms()));
+ $shiftsFilter->setLocations(check_request_int_array('locations', $shiftsFilter->getLocations()));
$shiftsFilter->setTypes(check_request_int_array('types', $shiftsFilter->getTypes()));
update_ShiftsFilter_timerange($shiftsFilter, $days);
}
/**
- * @return Room[]|Collection
+ * @return Location[]|Collection
*/
-function load_rooms()
+function load_locations(bool $onlyWithActiveShifts = false)
{
- $rooms = Room::orderBy('name')->get();
- if ($rooms->isEmpty()) {
- error(__('The administration has not configured any rooms yet.'));
- throw_redirect(page_link_to('/'));
+ $locations = Location::orderBy('name');
+
+ if ($onlyWithActiveShifts) {
+ $locationIdsFromAngelType = NeededAngelType::query()
+ ->whereNotNull('location_id')
+ ->select('location_id');
+
+ $locationIdsFromShift = Shift::query()
+ ->leftJoin('needed_angel_types', 'shifts.id', 'needed_angel_types.shift_id')
+ ->leftJoin('needed_angel_types AS nast', 'shifts.shift_type_id', 'nast.shift_type_id')
+ ->whereNotNull('needed_angel_types.id')
+ ->orWhereNotNull('nast.id')
+ ->select('shifts.location_id');
+
+ $locations->whereIn('id', $locationIdsFromAngelType)
+ ->orWhereIn('id', $locationIdsFromShift);
}
- return $rooms;
+ $locations = $locations->get();
+
+ if ($locations->isEmpty()) {
+ error(__('The administration has not configured any locations yet.'));
+ throw_redirect(url('/'));
+ }
+
+ return $locations;
}
/**
@@ -143,7 +164,7 @@ function load_days()
error(__('The administration has not configured any shifts yet.'));
// Do not try to redirect to the current page
if (config('home_site') != 'user_shifts') {
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
}
return $days;
@@ -155,10 +176,11 @@ function load_days()
function load_types()
{
$user = auth()->user();
+ $isShico = auth()->can('admin_shifts');
if (!AngelType::count()) {
error(__('The administration has not configured any angeltypes yet - or you are not subscribed to any angeltype.'));
- throw_redirect(page_link_to('/'));
+ throw_redirect(url('/'));
}
$types = Db::select(
@@ -178,8 +200,11 @@ function load_types()
ON (
`user_angel_type`.`angel_type_id`=`angel_types`.`id`
AND `user_angel_type`.`user_id`=?
- )
- ORDER BY `angel_types`.`name`
+ )'
+ . ($isShico ? '' :
+ 'WHERE angel_types.hide_on_shift_view = 0
+ OR user_angel_type.user_id IS NOT NULL ') .
+ 'ORDER BY `angel_types`.`name`
',
[
$user->id,
@@ -210,9 +235,9 @@ function view_user_shifts()
$session = session();
$days = load_days();
- $rooms = load_rooms();
+ $locations = load_locations(true);
$types = load_types();
- $ownTypes = [];
+ $ownAngelTypes = [];
/** @var EloquentCollection|UserAngelType[] $userAngelTypes */
$userAngelTypes = UserAngelType::whereUserId($user->id)
@@ -223,12 +248,12 @@ function view_user_shifts()
})
->get();
foreach ($userAngelTypes as $type) {
- $ownTypes[] = $type->angel_type_id;
+ $ownAngelTypes[] = $type->angel_type_id;
}
if (!$session->has('shifts-filter')) {
- $room_ids = $rooms->pluck('id')->toArray();
- $shiftsFilter = new ShiftsFilter(auth()->can('user_shifts_admin'), $room_ids, $ownTypes);
+ $location_ids = $locations->pluck('id')->toArray();
+ $shiftsFilter = new ShiftsFilter(auth()->can('user_shifts_admin'), $location_ids, $ownAngelTypes);
$session->set('shifts-filter', $shiftsFilter->sessionExport());
}
@@ -240,7 +265,7 @@ function view_user_shifts()
$shiftCalendarRenderer = shiftCalendarRendererByShiftFilter($shiftsFilter);
if (empty($user->api_key)) {
- User_reset_api_key($user, false);
+ auth()->resetApiKey($user);
}
$filled = [
@@ -258,24 +283,28 @@ function view_user_shifts()
$end_day = date('Y-m-d', $shiftsFilter->getEndTime());
$end_time = '23:59';
+ $canSignUpForShifts = true;
if (config('signup_requires_arrival') && !$user->state->arrived) {
+ $canSignUpForShifts = false;
info(render_user_arrived_hint());
}
$formattedDays = collect($days)->map(function ($value) {
- return Carbon::make($value)->format(__('Y-m-d'));
+ return dateWithEventDay(Carbon::make($value)->format('Y-m-d'));
})->toArray();
+ $link = button(url('/admin-shifts'), icon('plus-lg'), 'add');
+
return page([
div('col-md-12', [
- msg(),
view(__DIR__ . '/../../resources/views/pages/user-shifts.html', [
'title' => shifts_title(),
- 'room_select' => make_select(
- $rooms,
- $shiftsFilter->getRooms(),
- 'rooms',
- icon('pin-map-fill') . __('Rooms')
+ 'add_link' => auth()->can('admin_shifts') ? $link : '',
+ 'location_select' => make_select(
+ $locations,
+ $shiftsFilter->getLocations(),
+ 'locations',
+ icon('pin-map-fill') . __('Locations')
),
'start_select' => html_select_key(
'start_day',
@@ -295,14 +324,11 @@ function view_user_shifts()
$types,
$shiftsFilter->getTypes(),
'types',
- icon('person-lines-fill') . __('Angeltypes') . '1',
- [
- button(
- 'javascript:checkOwnTypes(\'selection_types\', ' . json_encode($ownTypes) . ')',
- __('Own'),
- 'd-print-none'
- ),
- ]
+ icon('person-lines-fill') . __('angeltypes.angeltypes')
+ . ' ',
+ $ownAngelTypes
),
'filled_select' => make_select(
$filled,
@@ -310,12 +336,6 @@ function view_user_shifts()
'filled',
icon('person-fill-slash') . __('Occupancy')
),
- 'task_notice' =>
- '1'
- . __('The tasks shown here are influenced by the angeltypes you joined already!')
- . ' '
- . __('Description of the jobs.')
- . '',
'shifts_table' => msg() . $shiftCalendarRenderer->render(),
'ical_text' => div('mt-3', ical_hint()),
'filter' => __('Filter'),
@@ -327,7 +347,11 @@ function view_user_shifts()
'set_last_4h' => __('last 4h'),
'set_next_4h' => __('next 4h'),
'set_next_8h' => __('next 8h'),
- 'buttons' => button(
+ 'random' => auth()->can('user_shifts') && $canSignUpForShifts ? button(
+ url('/shifts/random'),
+ icon('dice-4-fill') . __('shifts.random')
+ ) : '',
+ 'dashboard' => button(
public_dashboard_link(),
icon('speedometer2') . __('Public Dashboard')
),
@@ -351,9 +375,9 @@ function ical_hint()
return heading(__('iCal export and API') . ' ' . button_help('user/ical'), 2)
. '' . sprintf(
__('Export your own shifts. iCal format or JSON format available (please keep secret, otherwise reset the api key).'),
- page_link_to('ical', ['key' => $user->api_key]),
- page_link_to('shifts_json_export', ['key' => $user->api_key]),
- page_link_to('user_myshifts', ['reset' => 1])
+ url('/ical', ['key' => $user->api_key]),
+ url('/shifts-json-export', ['key' => $user->api_key]),
+ url('/user-myshifts', ['reset' => 1])
)
. '
';
}
-/**
- * @param array $array
- * @return array
- */
-function get_ids_from_array($array)
-{
- return $array['id'];
-}
-
/**
* @param array $items
* @param array $selected
* @param string $name
* @param string $title
- * @param array $additionalButtons
+ * @param int[] $ownSelect
* @return string
*/
-function make_select($items, $selected, $name, $title = null, $additionalButtons = [])
+function make_select($items, $selected, $name, $title = null, $ownSelect = [])
{
$html = '';
if (isset($title)) {
$html .= '' . $title . '
' . "\n";
}
- $buttons = [];
- $buttons[] = button('javascript:checkAll(\'selection_' . $name . '\', true)', __('All'), 'd-print-none');
- $buttons[] = button('javascript:checkAll(\'selection_' . $name . '\', false)', __('None'), 'd-print-none');
- $buttons = array_merge($buttons, $additionalButtons);
+ $buttons = [
+ button_checkbox_selection($name, __('All'), 'true'),
+ button_checkbox_selection($name, __('None'), 'false'),
+ ];
+ if (count($ownSelect) > 0) {
+ $buttons[] = button_checkbox_selection($name, __('Own'), json_encode($ownSelect));
+ }
$html .= buttons($buttons);
$html .= '' . "\n";
@@ -402,7 +420,7 @@ function make_select($items, $selected, $name, $title = null, $additionalButtons
$htmlItems[] = '
'
. ''
+ . '>'
. (!isset($i['enabled']) || $i['enabled'] ? '' : icon('mortarboard-fill'))
. '
';
}
diff --git a/includes/sys_form.php b/includes/sys_form.php
index 2ef208a5a..5bd63dd37 100644
--- a/includes/sys_form.php
+++ b/includes/sys_form.php
@@ -24,52 +24,28 @@ function form_hidden($name, $value)
* @param array $data_attributes
* @return string
*/
-function form_spinner(string $name, string $label, int $value, array $data_attributes = [])
+function form_spinner(string $name, string $label, int $value, array $data_attributes = [], bool $isDisabled = false)
{
$id = 'spinner-' . $name;
$attr = '';
foreach ($data_attributes as $attr_key => $attr_value) {
$attr .= ' data-' . $attr_key . '="' . $attr_value . '"';
}
+ $disabled = $isDisabled ? ' disabled' : '';
return form_element($label, '
-
-
', $id);
}
-/**
- * Render a bootstrap datepicker
- *
- * @param string $name Name of the parameter
- * @param string $label Label
- * @param int|Carbon $value Unix Timestamp
- * @param string $start_date Earliest possible date
- * @param string $end_date
- * @return string HTML
- */
-function form_date($name, $label, $value, $start_date = '', $end_date = '')
-{
- $dom_id = $name . '-date';
- $value = ($value instanceof Carbon) ? $value->getTimestamp() : $value;
- $value = is_numeric($value) ? date('Y-m-d', $value) : '';
- $start_date = is_numeric($start_date) ? date('Y-m-d', $start_date) : '';
- $end_date = is_numeric($end_date) ? date('Y-m-d', $end_date) : '';
-
- return form_element(
- $label,
- '
',
- $dom_id
- );
-}
-
/**
* Render a bootstrap datepicker
*
@@ -93,24 +69,6 @@ function form_datetime(string $name, string $label, $value)
', $dom_id, $name, htmlspecialchars($value ? $value->format('Y-m-d H:i') : '')), $dom_id);
}
-/**
- * Rendert eine Liste von Checkboxen fΓΌr ein Formular
- *
- * @param string $name Die Namen der Checkboxen werden aus name_key gebildet
- * @param string $label Die Beschriftung der Liste
- * @param array $items Array mit den einzelnen Checkboxen
- * @param array $selected Array mit den Keys, die ausgewΓ€hlt sind
- * @return string
- */
-function form_checkboxes($name, $label, $items, $selected)
-{
- $html = form_element($label, '');
- foreach ($items as $key => $item) {
- $html .= form_checkbox($name . '_' . $key, $item, in_array($key, $selected));
- }
- return $html;
-}
-
/**
* Rendert eine Checkbox
*
@@ -128,14 +86,15 @@ function form_checkbox($name, $label, $selected, $value = 'checked', $html_id =
}
return '
'
- . '
';
}
/**
- * Rendert einen Radio
+ * Renders a radio button
*
* @param string $name
* @param string $label
@@ -184,9 +143,9 @@ function form_info($label, $text = '')
* @param string $buttonType
* @return string
*/
-function form_submit($name, $label, $class = '', $wrapForm = true, $buttonType = 'primary')
+function form_submit($name, $label, $class = '', $wrapForm = true, $buttonType = 'primary', $title = '')
{
- $button = '
'
+ $button = ''
. $label
. '';
@@ -232,67 +191,6 @@ function form_text($name, $label, $value, $disabled = false, $maxlength = null,
);
}
-/**
- * Renders a text input with placeholder instead of label.
- *
- * @param string $name Input name
- * @param string $placeholder Placeholder
- * @param string $value The value
- * @param boolean $disabled Is the field enabled?
- * @return string
- */
-function form_text_placeholder($name, $placeholder, $value, $disabled = false)
-{
- $disabled = $disabled ? ' disabled="disabled"' : '';
- return form_element(
- '',
- ''
- );
-}
-
-/**
- * Rendert ein Formular-Emailfeld
- *
- * @param string $name
- * @param string $label
- * @param string $value
- * @param bool $disabled
- * @param string|null $autocomplete
- * @param int|null $maxlength
- *
- * @return string
- */
-function form_email($name, $label, $value, $disabled = false, $autocomplete = null, $maxlength = null)
-{
- $disabled = $disabled ? ' disabled="disabled"' : '';
- $autocomplete = $autocomplete ? ' autocomplete="' . $autocomplete . '"' : '';
- $maxlength = $maxlength ? ' maxlength=' . (int) $maxlength : '';
- return form_element(
- $label,
- '',
- 'form_' . $name
- );
-}
-
-/**
- * Rendert ein Formular-Dateifeld
- *
- * @param string $name
- * @param string $label
- * @return string
- */
-function form_file($name, $label)
-{
- return form_element(
- $label,
- sprintf('', $name),
- 'form_' . $name
- );
-}
-
/**
* Rendert ein Formular-Passwortfeld
*
@@ -308,7 +206,7 @@ function form_password($name, $label, $autocomplete, $disabled = false)
return form_element(
$label,
sprintf(
- '',
+ '',
$name,
config('min_password_length'),
$autocomplete,
@@ -318,25 +216,6 @@ function form_password($name, $label, $autocomplete, $disabled = false)
);
}
-/**
- * Renders a password input with placeholder instead of label.
- *
- * @param string $name
- * @param string $placeholder
- * @param bool $disabled
- * @return string
- */
-function form_password_placeholder($name, $placeholder, $disabled = false)
-{
- $disabled = $disabled ? ' disabled="disabled"' : '';
- return form_element(
- '',
- '',
- 'form_' . $name
- );
-}
-
/**
* Rendert ein Formular-Textfeld
*
@@ -406,14 +285,14 @@ function form_element($label, $input, $for = '', $class = '')
*
* @param string[] $elements
* @param string $action
- * @param bool $inline
+ * @param string $style
* @return string
*/
-function form($elements, $action = '', $inline = false, $btnGroup = false)
+function form($elements, $action = '', $style = '', $btnGroup = false)
{
return '';
@@ -463,9 +342,13 @@ function html_select_key($dom_id, $name, $rows, $selected, $selectText = '')
}
foreach ($rows as $key => $row) {
if (($key == $selected) || ($row === $selected)) {
- $html .= '';
+ $html .= '';
} else {
- $html .= '';
+ $html .= '';
}
}
$html .= '';
diff --git a/includes/sys_menu.php b/includes/sys_menu.php
index 806694cc5..3ca5a7a2f 100644
--- a/includes/sys_menu.php
+++ b/includes/sys_menu.php
@@ -1,20 +1,9 @@
addHint(user_angeltypes_unconfirmed_hint());
$hints_renderer->addHint(render_user_departure_date_hint());
$hints_renderer->addHint(user_driver_license_required_hint());
+ $hints_renderer->addHint(user_ifsg_certificate_required_hint());
// Important hints:
$hints_renderer->addHint(render_user_freeloader_hint(), true);
- $hints_renderer->addHint(render_user_arrived_hint(), true);
+ $hints_renderer->addHint(render_user_arrived_hint(true), true);
+ $hints_renderer->addHint(render_user_pronoun_hint(), true);
+ $hints_renderer->addHint(render_user_firstname_hint(), true);
+ $hints_renderer->addHint(render_user_lastname_hint(), true);
$hints_renderer->addHint(render_user_tshirt_hint(), true);
$hints_renderer->addHint(render_user_dect_hint(), true);
+ $hints_renderer->addHint(render_user_mobile_hint(), true);
return $hints_renderer->render();
}
@@ -62,10 +56,10 @@ function make_navigation()
$page = current_page();
$menu = [];
$pages = [
- 'news' => __('News'),
- 'meetings' => [__('Meetings'), 'user_meetings'],
+ 'news' => __('news.title'),
+ 'meetings' => [__('news.title.meetings'), 'user_meetings'],
'user_shifts' => __('Shifts'),
- 'angeltypes' => __('Angeltypes'),
+ 'angeltypes' => __('angeltypes.angeltypes'),
'questions' => [__('Ask the Heaven'), 'question.add'],
];
@@ -75,23 +69,30 @@ function make_navigation()
}
$title = ((array) $options)[0];
- $menu[] = toolbar_item_link(page_link_to($menu_page), '', $title, $menu_page == $page);
+ $menu[] = toolbar_item_link(
+ url(str_replace('_', '-', $menu_page)),
+ '',
+ $title,
+ $menu_page == $page
+ );
}
- $menu = make_room_navigation($menu);
+ $menu = make_location_navigation($menu);
$admin_menu = [];
$admin_pages = [
- // path => name
- // path => [name, permission]
+ // Examples:
+ // path => name,
+ // path => [name, permission],
+
'admin_arrive' => 'Arrive angels',
'admin_active' => 'Active angels',
'users' => ['All Angels', 'admin_user'],
'admin_free' => 'Free angels',
'admin/questions' => ['Answer questions', 'question.edit'],
- 'shifttypes' => 'Shifttypes',
+ 'admin/shifttypes' => ['shifttype.shifttypes', 'shifttypes'],
'admin_shifts' => 'Create shifts',
- 'admin/rooms' => ['room.rooms', 'admin_rooms'],
+ 'admin/locations' => ['location.locations', 'admin_locations'],
'admin_groups' => 'Grouprights',
'admin/schedule' => ['schedule.import', 'schedule.import'],
'admin/logs' => ['log.log', 'admin_log'],
@@ -109,8 +110,8 @@ function make_navigation()
$title = ((array) $options)[0];
$admin_menu[] = toolbar_dropdown_item(
- page_link_to($menu_page),
- __($title),
+ url(str_replace('_', '-', $menu_page)),
+ htmlspecialchars(__($title)),
$menu_page == $page
);
}
@@ -141,31 +142,36 @@ function menu_is_allowed(string $page, $options)
}
/**
- * Adds room navigation to the given menu.
+ * Adds location navigation to the given menu.
*
* @param string[] $menu Rendered menu
* @return string[]
*/
-function make_room_navigation($menu)
+function make_location_navigation($menu)
{
- if (!auth()->can('view_rooms')) {
+ if (!auth()->can('view_locations')) {
return $menu;
}
- // Get a list of all rooms
- $rooms = Room::orderBy('name')->get();
- $room_menu = [];
- if (auth()->can('admin_rooms')) {
- $room_menu[] = toolbar_dropdown_item(page_link_to('admin/rooms'), __('Manage rooms'), false, 'list');
+ // Get a list of all locations
+ $locations = Location::orderBy('name')->get();
+ $location_menu = [];
+ if (auth()->can('admin_locations')) {
+ $location_menu[] = toolbar_dropdown_item(
+ url('/admin/locations'),
+ __('Manage locations'),
+ false,
+ 'list'
+ );
}
- if (count($room_menu) > 0) {
- $room_menu[] = toolbar_dropdown_item_divider();
+ if (count($location_menu) > 0) {
+ $location_menu[] = toolbar_dropdown_item_divider();
}
- foreach ($rooms as $room) {
- $room_menu[] = toolbar_dropdown_item(room_link($room), $room->name, false, 'pin-map-fill');
+ foreach ($locations as $location) {
+ $location_menu[] = toolbar_dropdown_item(location_link($location), $location->name, false, 'pin-map-fill');
}
- if (count($room_menu) > 0) {
- $menu[] = toolbar_dropdown(__('Rooms'), $room_menu);
+ if (count($location_menu) > 0) {
+ $menu[] = toolbar_dropdown(__('Locations'), $location_menu);
}
return $menu;
}
@@ -209,7 +215,7 @@ function admin_new_questions()
return null;
}
- return ''
+ return ''
. __('There are unanswered questions!')
. '';
}
diff --git a/includes/sys_page.php b/includes/sys_page.php
index a5eb71421..70aa7f93f 100644
--- a/includes/sys_page.php
+++ b/includes/sys_page.php
@@ -2,9 +2,7 @@
use Engelsystem\Helpers\Carbon;
use Engelsystem\Http\Exceptions\HttpTemporaryRedirect;
-use Engelsystem\Models\BaseModel;
use Engelsystem\ValidationResult;
-use Illuminate\Support\Collection;
/**
* Provide page/request helper functions
@@ -63,41 +61,6 @@ function throw_redirect($url)
throw new HttpTemporaryRedirect($url);
}
-/**
- * Echoes given output and dies.
- *
- * @param string $output String to display
- */
-function raw_output($output = '')
-{
- echo $output;
- die();
-}
-
-/**
- * Helper function for transforming list of entities into array for select boxes.
- *
- * @param array|Collection $data The data array
- * @param string $key_name name of the column to use as id/key
- * @param string $value_name name of the column to use as displayed value
- *
- * @return array|Collection
- */
-function select_array($data, $key_name, $value_name)
-{
- if ($data instanceof Collection) {
- return $data->mapWithKeys(function (BaseModel $model) use ($key_name, $value_name) {
- return [$model->{$key_name} => $model->{$value_name}];
- });
- }
-
- $return = [];
- foreach ($data as $value) {
- $return[$value[$key_name]] = $value[$value_name];
- }
- return $return;
-}
-
/**
* Returns an int[] from given request param name.
*
@@ -185,23 +148,6 @@ function strip_request_item($name, $default_value = null)
return $default_value;
}
-/**
- * Returns REQUEST value or default value (null) if not set.
- *
- * @param string $name
- * @param string|null $default_value
- * @return mixed|null
- */
-function strip_request_tags($name, $default_value = null)
-{
- $request = request();
- if ($request->has($name)) {
- return strip_tags($request->input($name));
- }
-
- return $default_value;
-}
-
/**
* Testet, ob der angegebene REQUEST Wert ein Integer ist, bzw.
* eine ID sein kΓΆnnte.
@@ -251,20 +197,3 @@ function strip_item($item)
// Only allow letters, symbols, punctuation, separators and numbers without html tags
return preg_replace('/([^\p{L}\p{S}\p{P}\p{Z}\p{N}+]+)/ui', '', strip_tags($item));
}
-
-/**
- * Validates an email address with support for IDN domain names.
- *
- * @param string $email
- * @return bool
- */
-function check_email($email)
-{
- // Convert the domain part from idn to ascii
- if (substr_count($email, '@') == 1) {
- list($name, $domain) = explode('@', $email);
- $domain = idn_to_ascii($domain, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
- $email = $name . '@' . $domain;
- }
- return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
-}
diff --git a/includes/sys_template.php b/includes/sys_template.php
index 6fa452484..362824adf 100644
--- a/includes/sys_template.php
+++ b/includes/sys_template.php
@@ -1,5 +1,6 @@
' . $text . '';
-}
-
/**
* Renders a bootstrap label with given content and class.
*
@@ -188,7 +178,7 @@ function toolbar_item_link($href, $icon, $label, $active = false)
return ''
. ''
. ($icon != '' ? ' ' : '')
- . $label
+ . htmlspecialchars($label)
. ''
. '';
}
@@ -196,11 +186,11 @@ function toolbar_item_link($href, $icon, $label, $active = false)
function toolbar_dropdown_item(string $href, string $label, bool $active, string $icon = null): string
{
return strtr(
- '{icon} {label}',
+ '{icon} {label}',
[
'{href}' => $href,
'{icon}' => $icon === null ? '' : '',
- '{label}' => $label,
+ '{label}' => htmlspecialchars($label),
'{active}' => $active ? ' active' : '',
'{aria}' => $active ? ' aria-current="page"' : '',
]
@@ -235,7 +225,7 @@ function toolbar_dropdown($label, $submenu, $active = false): string
$template,
[
'{class}' => $active ? ' active' : '',
- '{label}' => $label,
+ '{label}' => htmlspecialchars($label),
'{submenu}' => join("\n", $submenu),
]
);
@@ -338,7 +328,7 @@ function render_table($columns, $rows, $data = true)
$html .= '';
$html .= '';
foreach ($rows as $row) {
- $html .= '';
+ $html .= '
';
foreach ($columns as $key => $column) {
$value = ' ';
if (isset($row[$key])) {
@@ -362,7 +352,7 @@ function render_table($columns, $rows, $data = true)
* @param string $id
* @return string
*/
-function button($href, $label, $class = '', $id = '')
+function button($href, $label, $class = '', $id = '', $title = '')
{
if (!Str::contains(str_replace(['btn-sm', 'btn-xl'], '', $class), 'btn-')) {
$class = 'btn-secondary' . ($class ? ' ' . $class : '');
@@ -370,20 +360,22 @@ function button($href, $label, $class = '', $id = '')
$idAttribute = $id ? 'id="' . $id . '"' : '';
- return '' . $label . '';
+ return '' . $label . '';
}
/**
- * Rendert einen Knopf mit JavaScript onclick Handler
+ * Renders a button to select corresponding checkboxes
*
- * @param string $javascript
+ * @param string $name
* @param string $label
- * @param string $class
+ * @param string $value
* @return string
*/
-function button_js($javascript, $label, $class = '')
+function button_checkbox_selection($name, $label, $value)
{
- return '' . $label . '';
+ return '' . $label . '';
}
/**
@@ -395,9 +387,9 @@ function button_js($javascript, $label, $class = '')
*
* @return string
*/
-function button_icon($href, $icon, $class = '')
+function button_icon($href, $icon, $class = '', $title = '')
{
- return button($href, icon($icon), $class);
+ return button($href, icon($icon), $class, '', $title);
}
/**
@@ -426,7 +418,20 @@ function buttons($buttons = [])
* @param array $buttons
* @return string
*/
-function table_buttons($buttons = [])
+function table_buttons($buttons = [], $additionalClass = '')
+{
+ return '' . join('', $buttons) . '
';
+}
+
+function user_info_icon(User $user): string
{
- return '' . join('', $buttons) . '
';
+ if (!auth()->can('admin_arrive') || !$user->state->user_info) {
+ return '';
+ }
+ $infoIcon = ' can('user.info.show')) {
+ $infoIcon .= 'data-bs-toggle="tooltip" title="' . htmlspecialchars($user->state->user_info) . '"';
+ }
+ $infoIcon .= '>';
+ return $infoIcon;
}
diff --git a/includes/view/AngelTypes_view.php b/includes/view/AngelTypes_view.php
index 8da72751e..f01c2a6b9 100644
--- a/includes/view/AngelTypes_view.php
+++ b/includes/view/AngelTypes_view.php
@@ -26,7 +26,7 @@ function AngelType_name_render(AngelType $angeltype, $plain = false)
}
return ''
- . ($angeltype->restricted ? icon('mortarboard-fill') : '') . $angeltype->name
+ . ($angeltype->restricted ? icon('mortarboard-fill') : '') . htmlspecialchars($angeltype->name)
. '';
}
@@ -60,12 +60,15 @@ function AngelType_render_membership(AngelType $user_angeltype)
*/
function AngelType_delete_view(AngelType $angeltype)
{
- return page_with_title(sprintf(__('Delete angeltype %s'), $angeltype->name), [
+ $link = button($angeltype->id
+ ? url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id])
+ : url('/angeltypes'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title($link . ' ' . sprintf(__('Delete angeltype %s'), htmlspecialchars($angeltype->name)), [
info(sprintf(__('Do you want to delete angeltype %s?'), $angeltype->name), true),
form([
buttons([
- button(page_link_to('angeltypes'), icon('x-lg') . __('cancel')),
- form_submit('delete', icon('trash') . __('delete'), 'btn-danger', false),
+ button(url('/angeltypes'), icon('x-lg') . __('form.cancel')),
+ form_submit('delete', icon('trash'), 'btn-danger', false, 'primary', __('form.delete')),
]),
]),
], true);
@@ -80,56 +83,96 @@ function AngelType_delete_view(AngelType $angeltype)
*/
function AngelType_edit_view(AngelType $angeltype, bool $supporter_mode)
{
- return page_with_title(sprintf(__('Edit %s'), $angeltype->name), [
- buttons([
- button(page_link_to('angeltypes'), icon('person-lines-fill') . __('Angeltypes'), 'back'),
- ]),
- msg(),
- form([
- $supporter_mode
- ? form_info(__('Name'), $angeltype->name)
- : form_text('name', __('Name'), $angeltype->name),
- $supporter_mode
- ? form_info(__('Requires introduction'), $angeltype->restricted ? __('Yes') : __('No'))
- : form_checkbox('restricted', __('Requires introduction'), $angeltype->restricted),
- form_info(
- '',
- __('Angel types which require introduction can only be used by an angel if enabled by a supporter (double opt-in).')
- ),
- $supporter_mode
- ? form_info(__('No Self Sign Up allowed'), $angeltype->no_self_signup ? __('Yes') : __('No'))
- : form_checkbox('no_self_signup', __('No Self Sign Up allowed'), $angeltype->no_self_signup),
- $supporter_mode ?
+ $link = button($angeltype->id
+ ? url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id])
+ : url('/angeltypes'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title(
+ $link . ' ' . (
+ $angeltype->id ?
+ sprintf(__('Edit %s'), htmlspecialchars((string) $angeltype->name)) :
+ __('Create angeltype')
+ ),
+ [
+ $angeltype->id ?
+ buttons([
+ button(url('/angeltypes'), icon('person-lines-fill') . __('angeltypes.angeltypes'), 'back'),
+ ]) : '',
+ msg(),
+ form([
+ $supporter_mode
+ ? form_info(__('general.name'), htmlspecialchars($angeltype->name))
+ : form_text('name', __('general.name'), $angeltype->name),
+ $supporter_mode
+ ? form_info(__('angeltypes.restricted'), $angeltype->restricted ? __('Yes') : __('No'))
+ : form_checkbox(
+ 'restricted',
+ __('angeltypes.restricted') .
+ ' ',
+ $angeltype->restricted
+ ),
+ $supporter_mode
+ ? form_info(__('shift.self_signup'), $angeltype->shift_self_signup ? __('Yes') : __('No'))
+ : form_checkbox(
+ 'shift_self_signup',
+ __('shift.self_signup') .
+ ' ',
+ $angeltype->shift_self_signup
+ ),
+ $supporter_mode ?
+ form_info(
+ __('Requires driver license'),
+ $angeltype->requires_driver_license
+ ? __('Yes')
+ : __('No')
+ ) :
+ form_checkbox(
+ 'requires_driver_license',
+ __('Requires driver license'),
+ $angeltype->requires_driver_license
+ ),
+ $supporter_mode && config('ifsg_enabled') ?
+ form_info(
+ __('angeltype.ifsg.required'),
+ $angeltype->requires_ifsg_certificate
+ ? __('Yes')
+ : __('No')
+ ) :
+ form_checkbox(
+ 'requires_ifsg_certificate',
+ __('angeltype.ifsg.required'),
+ $angeltype->requires_ifsg_certificate
+ ),
+ $supporter_mode
+ ? form_info(__('Show on dashboard'), $angeltype->show_on_dashboard ? __('Yes') : __('No'))
+ : form_checkbox('show_on_dashboard', __('Show on dashboard'), $angeltype->show_on_dashboard),
+ $supporter_mode
+ ? form_info(__('Hide at Registration'), $angeltype->hide_register ? __('Yes') : __('No'))
+ : form_checkbox('hide_register', __('Hide at Registration'), $angeltype->hide_register),
+ $supporter_mode
+ ? form_info(__('angeltypes.hide_on_shift_view'), $angeltype->hide_on_shift_view ? __('Yes') : __('No'))
+ : form_checkbox(
+ 'hide_on_shift_view',
+ __('angeltypes.hide_on_shift_view') .
+ ' ',
+ $angeltype->hide_on_shift_view
+ ),
+ form_textarea('description', __('general.description'), $angeltype->description),
+ form_info('', __('Please use markdown for the description.')),
+ heading(__('Contact'), 3),
form_info(
- __('Requires driver license'),
- $angeltype->requires_driver_license
- ? __('Yes')
- : __('No')
- ) :
- form_checkbox(
- 'requires_driver_license',
- __('Requires driver license'),
- $angeltype->requires_driver_license
+ '',
+ __('Primary contact person/desk for user questions.')
),
- $supporter_mode
- ? form_info(__('Show on dashboard'), $angeltype->show_on_dashboard ? __('Yes') : __('No'))
- : form_checkbox('show_on_dashboard', __('Show on dashboard'), $angeltype->show_on_dashboard),
- $supporter_mode
- ? form_info(__('Hide at Registration'), $angeltype->hide_register ? __('Yes') : __('No'))
- : form_checkbox('hide_register', __('Hide at Registration'), $angeltype->hide_register),
- form_textarea('description', __('Description'), $angeltype->description),
- form_info('', __('Please use markdown for the description.')),
- heading(__('Contact'), 3),
- form_info(
- '',
- __('Primary contact person/desk for user questions.')
- ),
- form_text('contact_name', __('Name'), $angeltype->contact_name),
- config('enable_dect') ? form_text('contact_dect', __('DECT'), $angeltype->contact_dect) : '',
- form_text('contact_email', __('E-Mail'), $angeltype->contact_email),
- form_submit('submit', __('Save')),
- ]),
- ]);
+ form_text('contact_name', __('general.name'), $angeltype->contact_name),
+ config('enable_dect') ? form_text('contact_dect', __('general.dect'), $angeltype->contact_dect) : '',
+ form_text('contact_email', __('general.email'), $angeltype->contact_email),
+ form_submit('submit', icon('save') . __('form.save')),
+ ]),
+ ]
+ );
}
/**
@@ -151,28 +194,40 @@ function AngelType_view_buttons(
$user_driver_license,
$user
) {
- $buttons = [
- button(page_link_to('angeltypes'), icon('person-lines-fill') . __('Angeltypes'), 'back'),
- ];
-
if ($angeltype->requires_driver_license) {
$buttons[] = button(
- user_driver_license_edit_link($user),
+ url('/settings/certificates'),
icon('person-vcard') . __('my driving license')
);
}
+ if (config('isfg_enabled') && $angeltype->requires_ifsg_certificate) {
+ $buttons[] = button(
+ url('/settings/certificates'),
+ icon('card-checklist') . __('angeltype.ifsg.own')
+ );
+ }
if (is_null($user_angeltype)) {
$buttons[] = button(
- page_link_to('user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
- icon('box-arrow-in-right') . __('join'),
- 'add'
+ url('/user-angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
+ icon('box-arrow-in-right') . ($admin_angeltypes ? '' : __('Join')),
+ 'add',
+ '',
+ ($admin_angeltypes ? 'Join' : ''),
);
} else {
if ($angeltype->requires_driver_license && !$user_driver_license->wantsToDrive()) {
error(__('This angeltype requires a driver license. Please enter your driver license information!'));
}
+ if (
+ config('ifsg_enabled') && $angeltype->requires_ifsg_certificate && !(
+ $user->license->ifsg_certificate_light || $user->license->ifsg_certificate
+ )
+ ) {
+ error(__('angeltype.ifsg.required.info'));
+ }
+
if ($angeltype->restricted && !$user_angeltype->confirm_user_id) {
error(sprintf(
__('You are unconfirmed for this angeltype. Please go to the introduction for %s to get confirmed.'),
@@ -180,21 +235,30 @@ function AngelType_view_buttons(
));
}
$buttons[] = button(
- page_link_to('user_angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id]),
- icon('box-arrow-right') . __('leave')
+ url('/user-angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id]),
+ icon('box-arrow-right') . ($admin_angeltypes ? '' : __('Leave')),
+ '',
+ '',
+ ($admin_angeltypes ? __('Leave') : ''),
);
}
if ($admin_angeltypes || $supporter) {
$buttons[] = button(
- page_link_to('angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
- icon('pencil') . __('edit')
+ url('/angeltypes', ['action' => 'edit', 'angeltype_id' => $angeltype->id]),
+ icon('pencil'),
+ '',
+ '',
+ __('form.edit')
);
}
if ($admin_angeltypes) {
$buttons[] = button(
- page_link_to('angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
- icon('trash') . __('delete')
+ url('/angeltypes', ['action' => 'delete', 'angeltype_id' => $angeltype->id]),
+ icon('trash'),
+ 'btn-danger',
+ '',
+ __('form.delete')
);
}
@@ -218,7 +282,7 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
foreach ($members as $member) {
$member->name = User_Nick_render($member) . User_Pronoun_render($member);
if (config('enable_dect')) {
- $member['dect'] = $member->contact->dect;
+ $member['dect'] = htmlspecialchars((string) $member->contact->dect);
}
if ($angeltype->requires_driver_license) {
$member['wants_to_drive'] = icon_bool($member->license->wantsToDrive());
@@ -229,23 +293,29 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
$member['has_license_12t_truck'] = icon_bool($member->license->drive_12t);
$member['has_license_forklift'] = icon_bool($member->license->drive_forklift);
}
+ if ($angeltype->requires_ifsg_certificate && config('ifsg_enabled')) {
+ $member['ifsg_certificate'] = icon_bool($member->license->ifsg_certificate);
+ if (config('ifsg_light_enabled')) {
+ $member['ifsg_certificate_light'] = icon_bool($member->license->ifsg_certificate_light);
+ }
+ }
if ($angeltype->restricted && empty($member->pivot->confirm_user_id)) {
$member['actions'] = table_buttons([
button(
- page_link_to(
- 'user_angeltypes',
+ url(
+ '/user-angeltypes',
['action' => 'confirm', 'user_angeltype_id' => $member->pivot->id]
),
- __('confirm'),
+ __('Confirm'),
'btn-sm'
),
button(
- page_link_to(
- 'user_angeltypes',
+ url(
+ '/user-angeltypes',
['action' => 'delete', 'user_angeltype_id' => $member->pivot->id]
),
- __('deny'),
+ __('Deny'),
'btn-sm'
),
]);
@@ -254,13 +324,15 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
if ($admin_angeltypes) {
$member['actions'] = table_buttons([
button(
- page_link_to('user_angeltypes', [
+ url('/user-angeltypes', [
'action' => 'update',
'user_angeltype_id' => $member->pivot->id,
'supporter' => 0,
]),
- icon('person-fill-down') . __('Remove supporter rights'),
- 'btn-sm'
+ icon('person-fill-down'),
+ 'btn-sm',
+ '',
+ __('Remove supporter rights'),
),
]);
} else {
@@ -272,22 +344,26 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
$member['actions'] = table_buttons([
$admin_angeltypes ?
button(
- page_link_to('user_angeltypes', [
+ url('/user-angeltypes', [
'action' => 'update',
'user_angeltype_id' => $member->pivot->id,
'supporter' => 1,
]),
- icon('person-fill-up') . __('Add supporter rights'),
- 'btn-sm'
+ icon('person-fill-up'),
+ 'btn-sm',
+ '',
+ __('Add supporter rights'),
) :
'',
button(
- page_link_to('user_angeltypes', [
+ url('/user-angeltypes', [
'action' => 'delete',
'user_angeltype_id' => $member->pivot->id,
]),
- icon('trash') . __('remove'),
- 'btn-sm'
+ icon('trash'),
+ 'btn-sm btn-danger',
+ '',
+ __('Remove'),
),
]);
}
@@ -313,27 +389,34 @@ function AngelType_view_members(AngelType $angeltype, $members, $admin_user_ange
function AngelType_view_table_headers(AngelType $angeltype, $supporter, $admin_angeltypes)
{
$headers = [
- 'name' => __('Nick'),
- 'dect' => __('DECT'),
- 'actions' => '',
+ 'name' => __('general.nick'),
];
+
+ if (config('enable_dect')) {
+ $headers['dect'] = __('general.dect');
+ }
+
if ($angeltype->requires_driver_license && ($supporter || $admin_angeltypes)) {
- $headers = [
- 'name' => __('Nick'),
- 'dect' => __('DECT'),
+ $headers = array_merge($headers, [
'wants_to_drive' => __('Driver'),
'has_car' => __('Has car'),
- 'has_license_car' => __('Car'),
- 'has_license_3_5t_transporter' => __('3,5t Transporter'),
- 'has_license_7_5t_truck' => __('7,5t Truck'),
- 'has_license_12t_truck' => __('12t Truck'),
- 'has_license_forklift' => __('Forklift'),
- 'actions' => '',
- ];
+ 'has_license_car' => __('settings.certificates.drive_car'),
+ 'has_license_3_5t_transporter' => __('settings.certificates.drive_3_5t'),
+ 'has_license_7_5t_truck' => __('settings.certificates.drive_7_5t'),
+ 'has_license_12t_truck' => __('settings.certificates.drive_12t'),
+ 'has_license_forklift' => __('settings.certificates.drive_forklift'),
+ ]);
}
- if (!config('enable_dect')) {
- unset($headers['dect']);
+
+ if (config('ifsg_enabled') && $angeltype->requires_ifsg_certificate && ($supporter || $admin_angeltypes)) {
+ if (config('ifsg_light_enabled')) {
+ $headers['ifsg_certificate_light'] = __('ifsg.certificate_light');
+ }
+ $headers['ifsg_certificate'] = __('ifsg.certificate');
}
+
+ $headers['actions'] = '';
+
return $headers;
}
@@ -366,24 +449,29 @@ function AngelType_view(
ShiftCalendarRenderer $shiftCalendarRenderer,
$tab
) {
- return page_with_title(sprintf(__('Team %s'), $angeltype->name), [
- AngelType_view_buttons($angeltype, $user_angeltype, $admin_angeltypes, $supporter, $user_driver_license, $user),
- msg(),
- tabs([
- __('Info') => AngelType_view_info(
- $angeltype,
- $members,
- $admin_user_angeltypes,
- $admin_angeltypes,
- $supporter
- ),
- __('Shifts') => AngelType_view_shifts(
- $angeltype,
- $shiftsFilterRenderer,
- $shiftCalendarRenderer
- ),
- ], $tab),
- ], true);
+ $link = button(url('/angeltypes'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title(
+ $link . ' ' . sprintf(__('Team %s'), htmlspecialchars($angeltype->name)),
+ [
+ AngelType_view_buttons($angeltype, $user_angeltype, $admin_angeltypes, $supporter, $user_driver_license, $user),
+ msg(),
+ tabs([
+ __('Info') => AngelType_view_info(
+ $angeltype,
+ $members,
+ $admin_user_angeltypes,
+ $admin_angeltypes,
+ $supporter
+ ),
+ __('Shifts') => AngelType_view_shifts(
+ $angeltype,
+ $shiftsFilterRenderer,
+ $shiftCalendarRenderer
+ ),
+ ], $tab),
+ ],
+ true
+ );
}
/**
@@ -394,7 +482,7 @@ function AngelType_view(
*/
function AngelType_view_shifts(AngelType $angeltype, $shiftsFilterRenderer, $shiftCalendarRenderer)
{
- $shifts = $shiftsFilterRenderer->render(page_link_to('angeltypes', [
+ $shifts = $shiftsFilterRenderer->render(url('/angeltypes', [
'action' => 'view',
'angeltype_id' => $angeltype->id,
]), ['type' => $angeltype->id]);
@@ -423,10 +511,10 @@ function AngelType_view_info(
$info[] = AngelTypes_render_contact_info($angeltype);
}
- $info[] = '' . __('Description') . '
';
+ $info[] = '' . __('general.description') . '
';
$parsedown = new Parsedown();
if ($angeltype->description != '') {
- $info[] = $parsedown->parse($angeltype->description);
+ $info[] = $parsedown->parse(htmlspecialchars($angeltype->description));
}
list($supporters, $members_confirmed, $members_unconfirmed) = AngelType_view_members(
@@ -462,11 +550,11 @@ function AngelType_view_info(
if ($admin_user_angeltypes) {
$info[] = buttons([
button(
- page_link_to(
- 'user_angeltypes',
+ url(
+ '/user-angeltypes',
['action' => 'add', 'angeltype_id' => $angeltype->id]
),
- __('Add'),
+ icon('plus-lg') . __('Add'),
'add'
),
]);
@@ -477,12 +565,12 @@ function AngelType_view_info(
$info[] = '' . __('Unconfirmed') . '
';
$info[] = buttons([
button(
- page_link_to('user_angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype->id]),
- icon('check-lg') . __('confirm all')
+ url('/user-angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype->id]),
+ icon('check-lg') . __('Confirm all')
),
button(
- page_link_to('user_angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype->id]),
- icon('trash') . __('deny all')
+ url('/user-angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype->id]),
+ icon('trash') . __('Deny all')
),
]);
$info[] = table($table_headers, $members_unconfirmed);
@@ -500,9 +588,20 @@ function AngelType_view_info(
function AngelTypes_render_contact_info(AngelType $angeltype)
{
$info = [
- __('Name') => [$angeltype->contact_name, $angeltype->contact_name],
- __('DECT') => config('enable_dect') ? [sprintf('%1$s', $angeltype->contact_dect), $angeltype->contact_dect] : null,
- __('E-Mail') => [sprintf('%1$s', $angeltype->contact_email), $angeltype->contact_email],
+ __('general.name') => [
+ htmlspecialchars($angeltype->contact_name),
+ htmlspecialchars($angeltype->contact_name),
+ ],
+ __('general.dect') => config('enable_dect')
+ ? [
+ sprintf('%1$s', htmlspecialchars($angeltype->contact_dect)),
+ htmlspecialchars($angeltype->contact_dect),
+ ]
+ : null,
+ __('general.email') => [
+ sprintf('%1$s', htmlspecialchars($angeltype->contact_email)),
+ htmlspecialchars($angeltype->contact_email),
+ ],
];
$contactInfo = [];
foreach ($info as $name => $data) {
@@ -523,20 +622,22 @@ function AngelTypes_render_contact_info(AngelType $angeltype)
*/
function AngelTypes_list_view($angeltypes, bool $admin_angeltypes)
{
- return page_with_title(angeltypes_title(), [
- msg(),
- buttons([
- $admin_angeltypes
- ? button(page_link_to('angeltypes', ['action' => 'edit']), __('New angeltype'), 'add')
- : '',
- button(url('/angeltypes/about'), __('angeltypes.about')),
- ]),
- table([
- 'name' => __('Name'),
- 'is_restricted' => icon('mortarboard-fill') . __('Requires introduction'),
- 'no_self_signup_allowed' => icon('pencil-square') . __('Self Sign Up Allowed'),
- 'membership' => __('Membership'),
- 'actions' => '',
- ], $angeltypes),
- ], true);
+ $link = button(url('/angeltypes', ['action' => 'edit']), icon('plus-lg'), 'add');
+ return page_with_title(
+ angeltypes_title() . ' ' . ($admin_angeltypes ? $link : ''),
+ [
+ msg(),
+ buttons([
+ button(url('/angeltypes/about'), __('angeltypes.about')),
+ ]),
+ table([
+ 'name' => __('general.name'),
+ 'is_restricted' => icon('mortarboard-fill') . __('angeltypes.restricted'),
+ 'shift_self_signup_allowed' => icon('pencil-square') . __('shift.self_signup.allowed'),
+ 'membership' => __('Membership'),
+ 'actions' => '',
+ ], $angeltypes),
+ ],
+ true,
+ );
}
diff --git a/includes/view/EventConfig_view.php b/includes/view/EventConfig_view.php
index 296c0e0a3..7a9c026de 100644
--- a/includes/view/EventConfig_view.php
+++ b/includes/view/EventConfig_view.php
@@ -42,7 +42,7 @@ function EventConfig_edit_view(
]),
div('row', [
div('col-md-6', [
- form_submit('submit', __('Save')),
+ form_submit('submit', icon('save') . __('form.save')),
]),
]),
]),
diff --git a/includes/view/Locations_view.php b/includes/view/Locations_view.php
new file mode 100644
index 000000000..6e9b3536a
--- /dev/null
+++ b/includes/view/Locations_view.php
@@ -0,0 +1,117 @@
+user();
+
+ $assignNotice = '';
+ if (config('signup_requires_arrival') && !$user->state->arrived) {
+ $assignNotice = info(render_user_arrived_hint(), true);
+ }
+
+ $description = '';
+ if ($location->description) {
+ $description = '' . __('general.description') . '
';
+ $parsedown = new Parsedown();
+ $description .= $parsedown->parse(htmlspecialchars($location->description));
+ }
+
+ $neededAngelTypes = '';
+ if (auth()->can('admin_shifts') && $location->neededAngelTypes->isNotEmpty()) {
+ $neededAngelTypes .= '' . __('location.required_angels') . '
';
+ foreach ($location->neededAngelTypes as $neededAngelType) {
+ if ($neededAngelType->count) {
+ $neededAngelTypes .= '- ' . $neededAngelType->angelType->name
+ . ': '
+ . $neededAngelType->count
+ . '
';
+ }
+ }
+ $neededAngelTypes .= '
';
+ }
+
+ $dect = '';
+ if (config('enable_dect') && $location->dect) {
+ $dect = heading(__('Contact'), 3)
+ . description([__('general.dect') => sprintf(
+ '%1$s',
+ htmlspecialchars($location->dect)
+ )]);
+ }
+
+ $tabs = [];
+ if ($location->map_url) {
+ $tabs[__('location.map_url')] = sprintf(
+ ''
+ . ''
+ . '
',
+ htmlspecialchars($location->map_url)
+ );
+ }
+
+ $tabs[__('Shifts')] = div('first', [
+ $shiftsFilterRenderer->render(url('/locations', [
+ 'action' => 'view',
+ 'location_id' => $location->id,
+ ]), ['locations' => [$location->id]]),
+ $shiftCalendarRenderer->render(),
+ ]);
+
+ $selected_tab = 0;
+ $request = request();
+ if ($request->has('shifts_filter_day')) {
+ $selected_tab = count($tabs) - 1;
+ }
+
+ $link = button(url('/admin/locations'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title(
+ (auth()->can('admin_locations') ? $link . ' ' : '') .
+ icon('pin-map-fill') . htmlspecialchars($location->name),
+ [
+ $assignNotice,
+ auth()->can('admin_locations') ? buttons([
+ button(
+ url('/admin/locations/edit/' . $location->id),
+ icon('pencil'),
+ '',
+ '',
+ __('form.edit')
+ ),
+ ]) : '',
+ $dect,
+ $description,
+ $neededAngelTypes,
+ tabs($tabs, $selected_tab),
+ ],
+ true
+ );
+}
+
+/**
+ *
+ * @param Location $location
+ * @return string
+ */
+function location_name_render(Location $location)
+{
+ if (auth()->can('view_locations')) {
+ return ''
+ . icon('pin-map-fill') . htmlspecialchars($location->name)
+ . '';
+ }
+
+ return icon('pin-map-fill') . htmlspecialchars($location->name);
+}
diff --git a/includes/view/PublicDashboard_view.php b/includes/view/PublicDashboard_view.php
index 29837176a..c40448f46 100644
--- a/includes/view/PublicDashboard_view.php
+++ b/includes/view/PublicDashboard_view.php
@@ -1,5 +1,6 @@
isNotEmpty()) {
- $first_news = $important_news->first();
+ if ($highlighted_news->isNotEmpty()) {
+ $first_news = $highlighted_news->first();
$news = div('alert alert-warning text-center', [
- '' . $first_news->title . '',
+ ''
+ . '' . htmlspecialchars($first_news->title) . ''
+ . '',
]);
}
@@ -43,17 +46,25 @@ function public_dashboard_view($stats, $free_shifts, $important_news)
]);
}
+ $stats = [
+ stats(__('Angels needed in the next 3 hrs'), $stats['needed-3-hours']),
+ stats(__('Angels needed for nightshifts'), $stats['needed-night']),
+ stats(__('Angels currently working'), $stats['angels-working'], 'default'),
+ stats(__('Hours to be worked'), $stats['hours-to-work'], 'default'),
+ ];
+
+ $dayOfEvent = DayOfEvent::get();
+
+ if (config('enable_show_day_of_event') && $dayOfEvent !== null) {
+ $stats[] = stats(__('dashboard.day'), $dayOfEvent, 'default');
+ }
+
$isFiltered = request()->get('filtered');
- $filter = collect(session()->get('shifts-filter'))->only(['rooms', 'types'])->toArray();
+ $filter = collect(session()->get('shifts-filter'))->only(['locations', 'types'])->toArray();
return page([
div('wrapper', [
div('public-dashboard', [
- div('first row', [
- stats(__('Angels needed in the next 3 hrs'), $stats['needed-3-hours']),
- stats(__('Angels needed for nightshifts'), $stats['needed-night']),
- stats(__('Angels currently working'), $stats['angels-working'], 'default'),
- stats(__('Hours to be worked'), $stats['hours-to-work'], 'default'),
- ], 'statistics'),
+ div('first row', $stats, 'statistics'),
$news,
$needed_angels,
], 'public-dashboard'),
@@ -84,17 +95,17 @@ function public_dashboard_shift_render($shift)
$panel_body = icon('clock-history') . $shift['start'] . ' - ' . $shift['end'];
$panel_body .= ' (' . $shift['duration'] . ' h)';
- $panel_body .= '
' . icon('list-task') . $shift['shifttype_name'];
+ $panel_body .= '
' . icon('list-task') . htmlspecialchars($shift['shifttype_name']);
if (!empty($shift['title'])) {
- $panel_body .= ' (' . $shift['title'] . ')';
+ $panel_body .= ' (' . htmlspecialchars($shift['title']) . ')';
}
- $panel_body .= '
' . icon('pin-map-fill') . $shift['room_name'];
+ $panel_body .= '
' . icon('pin-map-fill') . htmlspecialchars($shift['location_name']);
foreach ($shift['needed_angels'] as $needed_angels) {
$panel_body .= '
' . icon('person')
. ''
- . $needed_angels['need'] . ' × ' . $needed_angels['angeltype_name']
+ . $needed_angels['need'] . ' × ' . htmlspecialchars($needed_angels['angeltype_name'])
. '';
}
diff --git a/includes/view/Rooms_view.php b/includes/view/Rooms_view.php
deleted file mode 100644
index f1ba4c4c5..000000000
--- a/includes/view/Rooms_view.php
+++ /dev/null
@@ -1,86 +0,0 @@
-user();
-
- $assignNotice = '';
- if (config('signup_requires_arrival') && !$user->state->arrived) {
- $assignNotice = info(render_user_arrived_hint(), true);
- }
-
- $description = '';
- if ($room->description) {
- $description = '' . __('Description') . '
';
- $parsedown = new Parsedown();
- $description .= $parsedown->parse($room->description);
- }
-
- $dect = '';
- if (config('enable_dect') && $room->dect) {
- $dect = heading(__('Contact'), 3)
- . description([__('DECT') => sprintf('%1$s', $room->dect)]);
- }
-
- $tabs = [];
- if ($room->map_url) {
- $tabs[__('Map')] = sprintf(
- ''
- . ''
- . '
',
- $room->map_url
- );
- }
-
- $tabs[__('Shifts')] = div('first', [
- $shiftsFilterRenderer->render(page_link_to('rooms', [
- 'action' => 'view',
- 'room_id' => $room->id,
- ]), ['rooms' => [$room->id]]),
- $shiftCalendarRenderer->render(),
- ]);
-
- $selected_tab = 0;
- $request = request();
- if ($request->has('shifts_filter_day')) {
- $selected_tab = count($tabs) - 1;
- }
-
- return page_with_title(icon('pin-map-fill') . $room->name, [
- $assignNotice,
- auth()->can('admin_rooms') ? buttons([
- button(
- page_link_to('admin/rooms/edit/' . $room->id),
- icon('pencil') . __('edit')
- ),
- ]) : '',
- $dect,
- $description,
- tabs($tabs, $selected_tab),
- ], true);
-}
-
-/**
- *
- * @param Room $room
- * @return string
- */
-function Room_name_render(Room $room)
-{
- if (auth()->can('view_rooms')) {
- return '' . icon('pin-map-fill') . $room->name . '';
- }
-
- return icon('pin-map-fill') . $room->name;
-}
diff --git a/includes/view/ShiftCalendarRenderer.php b/includes/view/ShiftCalendarRenderer.php
index d910bed31..c62051de4 100644
--- a/includes/view/ShiftCalendarRenderer.php
+++ b/includes/view/ShiftCalendarRenderer.php
@@ -2,6 +2,7 @@
namespace Engelsystem;
+use Engelsystem\Helpers\Carbon;
use Engelsystem\Models\Shifts\Shift;
use Engelsystem\Models\Shifts\ShiftEntry;
use Illuminate\Support\Collection;
@@ -61,28 +62,28 @@ public function __construct($shifts, private $needed_angeltypes, private $shift_
}
/**
- * Assigns the shifts to different lanes per room if they collide
+ * Assigns the shifts to different lanes per location if they collide
*
* @param Shift[] $shifts The shifts to assign
- * @return array Returns an array that assigns a room_id to an array of ShiftCalendarLane containing the shifts
+ * @return array Returns an array that assigns a location_id to an array of ShiftCalendarLane containing the shifts
*/
private function assignShiftsToLanes($shifts)
{
- // array that assigns a room id to a list of lanes (per room)
+ // array that assigns a location id to a list of lanes (per location)
$lanes = [];
foreach ($shifts as $shift) {
- $room = $shift->room;
- $header = Room_name_render($room);
- if (!isset($lanes[$room->id])) {
- // initialize room with one lane
- $lanes[$room->id] = [
+ $location = $shift->location;
+ $header = location_name_render($location);
+ if (!isset($lanes[$location->id])) {
+ // initialize location with one lane
+ $lanes[$location->id] = [
new ShiftCalendarLane($header),
];
}
- // Try to add the shift to the existing lanes for this room
+ // Try to add the shift to the existing lanes for this location
$shift_added = false;
- foreach ($lanes[$room->id] as $lane) {
+ foreach ($lanes[$location->id] as $lane) {
/** @var ShiftCalendarLane $lane */
if ($lane->shiftFits($shift)) {
$lane->addShift($shift);
@@ -90,11 +91,11 @@ private function assignShiftsToLanes($shifts)
break;
}
}
- // If all lanes for this room are busy, create a new lane and add shift to it
+ // If all lanes for this location are busy, create a new lane and add shift to it
if (!$shift_added) {
$newLane = new ShiftCalendarLane($header);
$newLane->addShift($shift);
- $lanes[$room->id][] = $newLane;
+ $lanes[$location->id][] = $newLane;
}
}
@@ -153,8 +154,8 @@ public function render()
private function renderShiftLanes()
{
$html = '';
- foreach ($this->lanes as $room_lanes) {
- foreach ($room_lanes as $lane) {
+ foreach ($this->lanes as $location_lanes) {
+ foreach ($location_lanes as $lane) {
$html .= $this->renderLane($lane);
}
}
@@ -212,20 +213,21 @@ private function renderLane(ShiftCalendarLane $lane)
*/
private function renderTick($time, $label = false)
{
+ $time = Carbon::createFromTimestamp($time);
$class = $label ? 'tick bg-' . theme_type() : 'tick ';
- if ($time % (24 * 60 * 60) == 23 * 60 * 60) {
+ if ($time->isStartOfDay()) {
if (!$label) {
return div($class . ' day');
}
return div($class . ' day', [
- date(__('m-d'), $time) . '
' . date(__('H:i'), $time),
+ $time->format(__('m-d')) . '
' . $time->format(__('H:i')),
]);
- } elseif ($time % (60 * 60) == 0) {
+ } elseif ($time->isStartOfHour()) {
if (!$label) {
return div($class . ' hour');
}
return div($class . ' hour', [
- date(__('m-d'), $time) . '
' . date(__('H:i'), $time),
+ $time->format(__('m-d')) . '
' . $time->format(__('H:i')),
]);
}
return div($class);
@@ -242,7 +244,7 @@ private function renderTimeLane()
$time_slot = [
div('header ' . $bg, [
- __('Time'),
+ __('log.time'),
]),
];
for ($block = 0; $block < $this->getBlocksPerSlot(); $block++) {
@@ -312,7 +314,7 @@ private function renderLegend()
badge(__('Help needed'), 'danger'),
badge(__('Other angeltype needed / collides with my shifts'), 'warning'),
badge(__('Shift is full'), 'success'),
- badge(__('Shift running/ended or user not arrived/allowed'), 'secondary'),
+ badge(__('Shift is running/ended or you have not arrived'), 'secondary'),
]);
}
}
diff --git a/includes/view/ShiftCalendarShiftRenderer.php b/includes/view/ShiftCalendarShiftRenderer.php
index 3ab89147c..4a20e7224 100644
--- a/includes/view/ShiftCalendarShiftRenderer.php
+++ b/includes/view/ShiftCalendarShiftRenderer.php
@@ -29,7 +29,7 @@ public function render(Shift $shift, $needed_angeltypes, $shift_entries, $user)
{
$info_text = '';
if ($shift->title != '') {
- $info_text = icon('info-circle') . $shift->title . '
';
+ $info_text = icon('info-circle') . htmlspecialchars($shift->title) . '
';
}
list($shift_signup_state, $shifts_row) = $this->renderShiftNeededAngeltypes(
$shift,
@@ -43,8 +43,6 @@ public function render(Shift $shift, $needed_angeltypes, $shift_entries, $user)
$blocks = ceil(($shift->end->timestamp - $shift->start->timestamp) / ShiftCalendarRenderer::SECONDS_PER_ROW);
$blocks = max(1, $blocks);
- $room = $shift->room;
-
return [
$blocks,
div(
@@ -57,7 +55,7 @@ public function render(Shift $shift, $needed_angeltypes, $shift_entries, $user)
$this->renderShiftHead($shift, $class, $shift_signup_state->getFreeEntries()),
div('card-body ' . $this->classBg(), [
$info_text,
- Room_name_render($room),
+ location_name_render($shift->location),
]),
$shifts_row,
]
@@ -192,14 +190,14 @@ private function renderShiftNeededAngeltype(Shift $shift, $shift_entries, $angel
// No link and add a text hint, when the shift ended
ShiftSignupStatus::NOT_ARRIVED => $inner_text . ' (' . __('please arrive for signup') . ')',
ShiftSignupStatus::NOT_YET => $inner_text . ' (' . __('not yet') . ')',
- ShiftSignupStatus::ANGELTYPE => $angeltype->restricted
- // User has to be confirmed on the angeltype first
+ ShiftSignupStatus::ANGELTYPE => $angeltype->restricted || !$angeltype->shift_self_signup
+ // User has to be confirmed on the angeltype first or can't sign up by themselves
? $inner_text . icon('mortarboard-fill')
// Add link to join the angeltype first
: $inner_text . '
'
. button(
- page_link_to('user_angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
- sprintf(__('Become %s'), $angeltype->name),
+ url('/user-angeltypes', ['action' => 'add', 'angeltype_id' => $angeltype->id]),
+ sprintf(__('Become %s'), htmlspecialchars($angeltype->name)),
'btn-sm'
),
// Shift collides or user is already signed up: No signup allowed
@@ -249,20 +247,24 @@ private function renderShiftHead(Shift $shift, $class, $needed_angeltypes_count)
if (auth()->can('admin_shifts')) {
$header_buttons = '' . table_buttons([
button(
- page_link_to('user_shifts', ['edit_shift' => $shift->id]),
+ url('/user-shifts', ['edit_shift' => $shift->id]),
icon('pencil'),
- 'btn-' . $class . ' btn-sm border-light text-white'
+ 'btn-' . $class . ' btn-sm border-light text-white',
+ '',
+ __('form.edit')
),
button(
- page_link_to('user_shifts', ['delete_shift' => $shift->id]),
+ url('/user-shifts', ['delete_shift' => $shift->id]),
icon('trash'),
- 'btn-' . $class . ' btn-sm border-light text-white'
+ 'btn-' . $class . ' btn-sm border-light text-white',
+ '',
+ __('form.delete')
),
]) . '
';
}
$shift_heading = $shift->start->format('H:i') . ' ‐ '
. $shift->end->format('H:i') . ' — '
- . $shift->shiftType->name;
+ . htmlspecialchars($shift->shiftType->name);
if ($needed_angeltypes_count > 0) {
$shift_heading = '' . $needed_angeltypes_count . ' ' . $shift_heading;
diff --git a/includes/view/ShiftEntry_view.php b/includes/view/ShiftEntry_view.php
index 31242b46c..4420b414b 100644
--- a/includes/view/ShiftEntry_view.php
+++ b/includes/view/ShiftEntry_view.php
@@ -1,7 +1,7 @@
displayName,
$shift->shiftType->name,
- $shift->start->format(__('Y-m-d H:i')),
- $shift->end->format(__('Y-m-d H:i')),
+ $shift->start->format(__('general.datetime')),
+ $shift->end->format(__('general.datetime')),
$angeltype->name
), true),
form([
buttons([
- button(user_link($signoff_user->id), icon('x-lg') . __('cancel')),
- form_submit('delete', icon('trash') . __('sign off'), 'btn-danger', false),
+ button(user_link($signoff_user->id), icon('x-lg') . __('form.cancel')),
+ form_submit('delete', icon('trash'), 'btn-danger', false, 'primary', __('Sign off')),
]),
]),
]);
@@ -49,15 +49,22 @@ function ShiftEntry_delete_view(Shift $shift, AngelType $angeltype, User $signof
info(sprintf(
__('Do you want to sign off from your shift %s from %s to %s as %s?'),
$shift->shiftType->name,
- $shift->start->format(__('Y-m-d H:i')),
- $shift->end->format(__('Y-m-d H:i')),
+ $shift->start->format(__('general.datetime')),
+ $shift->end->format(__('general.datetime')),
$angeltype->name
), true),
form([
buttons([
- button(user_link($signoff_user->id), icon('x-lg') . __('cancel')),
- form_submit('delete', icon('trash') . __('delete'), 'btn-danger', false),
+ button(user_link($signoff_user->id), icon('x-lg') . __('form.cancel')),
+ form_submit(
+ 'delete',
+ icon('trash'),
+ 'btn-danger',
+ false,
+ 'danger',
+ __('Sign off')
+ ),
]),
]),
]);
@@ -75,7 +82,7 @@ function ShiftEntry_delete_title()
* Admin puts user into shift.
*
* @param Shift $shift
- * @param Room $room
+ * @param Location $location
* @param AngelType $angeltype
* @param array $angeltypes_select
* @param User $signup_user
@@ -84,23 +91,23 @@ function ShiftEntry_delete_title()
*/
function ShiftEntry_create_view_admin(
Shift $shift,
- Room $room,
+ Location $location,
AngelType $angeltype,
$angeltypes_select,
$signup_user,
$users_select
) {
- $start = $shift->start->format(__('Y-m-d H:i'));
+ $start = $shift->start->format(__('general.datetime'));
return page_with_title(
- ShiftEntry_create_title() . ': ' . $shift->shiftType->name
+ ShiftEntry_create_title() . ': ' . htmlspecialchars($shift->shiftType->name)
. ' %c',
[
- Shift_view_header($shift, $room),
+ Shift_view_header($shift, $location),
info(__('Do you want to sign up the following user for this shift?'), true),
form([
form_select('angeltype_id', __('Angeltype'), $angeltypes_select, $angeltype->id),
- form_select('user_id', __('User'), $users_select, $signup_user->id),
- form_submit('submit', icon('check-lg') . __('Save')),
+ form_select('user_id', __('general.user'), $users_select, $signup_user->id),
+ form_submit('submit', icon('save') . __('form.save')),
]),
]
);
@@ -110,27 +117,32 @@ function ShiftEntry_create_view_admin(
* Supporter puts user into shift.
*
* @param Shift $shift
- * @param Room $room
+ * @param Location $location
* @param AngelType $angeltype
* @param User $signup_user
* @param array $users_select
* @return string
*/
-function ShiftEntry_create_view_supporter(Shift $shift, Room $room, AngelType $angeltype, $signup_user, $users_select)
-{
- $start = $shift->start->format(__('Y-m-d H:i'));
+function ShiftEntry_create_view_supporter(
+ Shift $shift,
+ Location $location,
+ AngelType $angeltype,
+ $signup_user,
+ $users_select
+) {
+ $start = $shift->start->format(__('general.datetime'));
return page_with_title(
- ShiftEntry_create_title() . ': ' . $shift->shiftType->name
+ ShiftEntry_create_title() . ': ' . htmlspecialchars($shift->shiftType->name)
. ' %c',
[
- Shift_view_header($shift, $room),
+ Shift_view_header($shift, $location),
info(sprintf(
__('Do you want to sign up the following user for this shift as %s?'),
$angeltype->name
), true),
form([
- form_select('user_id', __('User'), $users_select, $signup_user->id),
- form_submit('submit', icon('check-lg') . __('Save')),
+ form_select('user_id', __('general.user'), $users_select, $signup_user->id),
+ form_submit('submit', icon('save') . __('form.save')),
]),
]
);
@@ -140,23 +152,23 @@ function ShiftEntry_create_view_supporter(Shift $shift, Room $room, AngelType $a
* User joining a shift.
*
* @param Shift $shift
- * @param Room $room
+ * @param Location $location
* @param AngelType $angeltype
* @param string $comment
* @return string
*/
-function ShiftEntry_create_view_user(Shift $shift, Room $room, AngelType $angeltype, $comment)
+function ShiftEntry_create_view_user(Shift $shift, Location $location, AngelType $angeltype, $comment)
{
- $start = $shift->start->format(__('Y-m-d H:i'));
+ $start = $shift->start->format(__('general.datetime'));
return page_with_title(
- ShiftEntry_create_title() . ': ' . $shift->shiftType->name
+ ShiftEntry_create_title() . ': ' . htmlspecialchars($shift->shiftType->name)
. ' %c',
[
- Shift_view_header($shift, $room),
+ Shift_view_header($shift, $location),
info(sprintf(__('Do you want to sign up for this shift as %s?'), $angeltype->name), true),
form([
form_textarea('comment', __('Comment (for your eyes only):'), $comment),
- form_submit('submit', icon('check-lg') . __('Save')),
+ form_submit('submit', icon('save') . __('form.save')),
]),
]
);
@@ -213,17 +225,27 @@ function ShiftEntry_edit_view(
$comment = '';
}
- return page_with_title(__('Edit shift entry'), [
- msg(),
- form([
- form_info(__('Angel:'), User_Nick_render($angel)),
- form_info(__('Date, Duration:'), $date),
- form_info(__('Location:'), $location),
- form_info(__('Title:'), $title),
- form_info(__('Type:'), $type),
- $comment,
- join('', $freeload_form),
- form_submit('submit', __('Save')),
- ]),
- ]);
+ $link = button(
+ url('/users', ['action' => 'view', 'user_id' => $angel->id]),
+ icon('chevron-left'),
+ 'btn-sm',
+ '',
+ __('general.back'),
+ );
+ return page_with_title(
+ $link . ' ' . __('Edit shift entry'),
+ [
+ msg(),
+ form([
+ form_info(__('Angel:'), User_Nick_render($angel)),
+ form_info(__('Date, Duration:'), $date),
+ form_info(__('Location:'), htmlspecialchars($location)),
+ form_info(__('Title:'), htmlspecialchars($title)),
+ form_info(__('Type:'), htmlspecialchars($type)),
+ $comment,
+ join('', $freeload_form),
+ form_submit('submit', icon('save') . __('form.save')),
+ ]),
+ ]
+ );
}
diff --git a/includes/view/ShiftTypes_view.php b/includes/view/ShiftTypes_view.php
deleted file mode 100644
index 4f2a7b071..000000000
--- a/includes/view/ShiftTypes_view.php
+++ /dev/null
@@ -1,127 +0,0 @@
-can('shifttypes')) {
- return '' . $shifttype->name . '';
- }
- return $shifttype->name;
-}
-
-/**
- * @param ShiftType $shifttype
- * @return string
- */
-function ShiftType_delete_view(ShiftType $shifttype)
-{
- return page_with_title(sprintf(__('Delete shifttype %s'), $shifttype->name), [
- info(sprintf(__('Do you want to delete shifttype %s?'), $shifttype->name), true),
- form([
- buttons([
- button(page_link_to('shifttypes'), icon('x-lg') . __('cancel')),
- form_submit(
- 'delete',
- icon('trash') . __('delete'),
- 'btn-danger',
- false
- ),
- ]),
- ]),
- ], true);
-}
-
-/**
- * @param string $name
- * @param string $description
- * @param int $shifttype_id
- * @return string
- */
-function ShiftType_edit_view($name, $description, $shifttype_id)
-{
- return page_with_title($shifttype_id ? __('Edit shifttype') : __('Create shifttype'), [
- msg(),
- buttons([
- button(page_link_to('shifttypes'), shifttypes_title(), 'back'),
- ]),
- form([
- form_text('name', __('Name'), $name),
- form_textarea('description', __('Description'), $description),
- form_info('', __('Please use markdown for the description.')),
- form_submit('submit', __('Save')),
- ]),
- ], true);
-}
-
-/**
- * @param ShiftType $shifttype
- * @return string
- */
-function ShiftType_view(ShiftType $shifttype)
-{
- $parsedown = new Parsedown();
- $title = $shifttype->name;
- return page_with_title($title, [
- msg(),
- buttons([
- button(page_link_to('shifttypes'), shifttypes_title(), 'back'),
- button(
- page_link_to('shifttypes', ['action' => 'edit', 'shifttype_id' => $shifttype->id]),
- icon('pencil') . __('edit')
- ),
- button(
- page_link_to('shifttypes', ['action' => 'delete', 'shifttype_id' => $shifttype->id]),
- icon('trash') . __('delete'),
- ),
- ]),
- heading(__('Description'), 2),
- $parsedown->parse($shifttype->description),
- ], true);
-}
-
-/**
- * @param ShiftType[]|array[]|Collection $shifttypes
- * @return string
- */
-function ShiftTypes_list_view($shifttypes)
-{
- foreach ($shifttypes as $shifttype) {
- $shifttype->name = ''
- . $shifttype->name
- . '';
- $shifttype->actions = table_buttons([
- button(
- page_link_to(
- 'shifttypes',
- ['action' => 'edit', 'shifttype_id' => $shifttype->id]
- ),
- icon('pencil') . __('edit'),
- 'btn-sm'
- ),
- button(
- page_link_to('shifttypes', ['action' => 'delete', 'shifttype_id' => $shifttype->id]),
- icon('trash') . __('delete'),
- 'btn-sm'
- ),
- ]);
- }
-
- return page_with_title(shifttypes_title(), [
- msg(),
- buttons([
- button(page_link_to('shifttypes', ['action' => 'edit']), __('New shifttype'), 'add'),
- ]),
- table([
- 'name' => __('Name'),
- 'actions' => '',
- ], $shifttypes),
- ], true);
-}
diff --git a/includes/view/ShiftsFilterRenderer.php b/includes/view/ShiftsFilterRenderer.php
index 531580033..ac08917c4 100644
--- a/includes/view/ShiftsFilterRenderer.php
+++ b/includes/view/ShiftsFilterRenderer.php
@@ -49,7 +49,7 @@ public function render($page_link, $dashboardFilter = [])
$toolbar = [];
if ($this->daySelectionEnabled && !empty($this->days)) {
$selected_day = date('Y-m-d', $this->shiftsFilter->getStartTime());
- $selected_day_formatted = date(__('Y-m-d'), $this->shiftsFilter->getStartTime());
+ $selected_day_formatted = dateWithEventDay($selected_day);
$day_dropdown_items = [];
foreach ($this->days as $value => $day) {
$link = $page_link . '&shifts_filter_day=' . $value;
@@ -87,14 +87,4 @@ public function enableDaySelection($days)
$this->daySelectionEnabled = true;
$this->days = $days;
}
-
- /**
- * Should the filter display a day selection.
- *
- * @return bool
- */
- public function isDaySelectionEnabled()
- {
- return $this->daySelectionEnabled;
- }
}
diff --git a/includes/view/Shifts_view.php b/includes/view/Shifts_view.php
index 4da951672..dc76ada7b 100644
--- a/includes/view/Shifts_view.php
+++ b/includes/view/Shifts_view.php
@@ -1,7 +1,7 @@
' . __('Title') . '',
+ '' . __('title.title') . '
',
''
. ($shift->url != ''
- ? '' . $shift->title . ''
- : $shift->title)
+ ? '' . htmlspecialchars($shift->title) . ''
+ : htmlspecialchars($shift->title))
. '
',
]),
div('col-sm-3 col-xs-6', [
- '' . __('Start') . '
',
+ '' . __('shifts.start') . '
',
'',
- icon('calendar-event') . $shift->start->format(__('Y-m-d')),
+ icon('calendar-event') . $shift->start->format(__('general.date')),
'
',
icon('clock') . $shift->start->format('H:i'),
'
',
]),
div('col-sm-3 col-xs-6', [
- '' . __('End') . '
',
+ '' . __('shifts.end') . '
',
'',
- icon('calendar-event') . $shift->end->format(__('Y-m-d')),
+ icon('calendar-event') . $shift->end->format(__('general.date')),
'
',
icon('clock') . $shift->end->format('H:i'),
'
',
]),
div('col-sm-3 col-xs-6', [
'' . __('Location') . '
',
- '' . Room_name_render($room) . '
',
+ '' . location_name_render($location) . '
',
]),
]);
}
@@ -61,17 +61,23 @@ function Shift_editor_info_render(Shift $shift)
if (!empty($shift->created_by)) {
$info[] = sprintf(
icon('plus-lg') . __('created at %s by %s'),
- $shift->created_at->format(__('Y-m-d H:i')),
+ $shift->created_at->format(__('general.datetime')),
User_Nick_render($shift->createdBy)
);
}
if (!empty($shift->updated_by)) {
$info[] = sprintf(
icon('pencil') . __('edited at %s by %s'),
- $shift->updated_at->format(__('Y-m-d H:i')),
+ $shift->updated_at->format(__('general.datetime')),
User_Nick_render($shift->updatedBy)
);
}
+ if ($shift->transaction_id) {
+ $info[] = sprintf(
+ icon('clock-history') . __('History ID: %s'),
+ $shift->transaction_id
+ );
+ }
return join('
', $info);
}
@@ -88,20 +94,17 @@ function Shift_signup_button_render(Shift $shift, AngelType $angeltype)
->first();
if (
- isset($angeltype->shift_signup_state)
- && (
- $angeltype->shift_signup_state->isSignupAllowed()
- || auth()->user()->isAngelTypeSupporter($angeltype)
- || auth()->can('admin_user_angeltypes')
- )
+ $angeltype->shift_signup_state?->isSignupAllowed()
+ || auth()->user()->isAngelTypeSupporter($angeltype)
+ || auth()->can('admin_user_angeltypes')
) {
return button(shift_entry_create_link($shift, $angeltype), __('Sign up'));
} elseif (empty($user_angeltype)) {
return button(
- page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
+ url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
sprintf(
__('Become %s'),
- $angeltype->name
+ htmlspecialchars($angeltype->name)
)
);
}
@@ -112,16 +115,21 @@ function Shift_signup_button_render(Shift $shift, AngelType $angeltype)
/**
* @param Shift $shift
* @param ShiftType $shifttype
- * @param Room $room
+ * @param Location $location
* @param AngelType[]|Collection $angeltypes_source
* @param ShiftSignupState $shift_signup_state
* @return string
*/
-function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_source, ShiftSignupState $shift_signup_state)
-{
+function Shift_view(
+ Shift $shift,
+ ShiftType $shifttype,
+ Location $location,
+ $angeltypes_source,
+ ShiftSignupState $shift_signup_state
+) {
$shift_admin = auth()->can('admin_shifts');
$user_shift_admin = auth()->can('user_shifts_admin');
- $admin_rooms = auth()->can('admin_rooms');
+ $admin_locations = auth()->can('admin_locations');
$admin_shifttypes = auth()->can('shifttypes');
$parsedown = new Parsedown();
@@ -164,32 +172,42 @@ function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_
if (config('signup_advance_hours') && $shift->start->timestamp > time() + config('signup_advance_hours') * 3600) {
$content[] = info(sprintf(
__('This shift is in the far future and becomes available for signup at %s.'),
- date(__('Y-m-d H:i'), $shift->start->timestamp - config('signup_advance_hours') * 3600)
+ date(__('general.datetime'), $shift->start->timestamp - config('signup_advance_hours') * 3600)
), true);
}
$buttons = [];
- if ($shift_admin || $admin_shifttypes || $admin_rooms) {
+ if ($shift_admin || $admin_shifttypes || $admin_locations) {
$buttons = [
- $shift_admin ? button(shift_edit_link($shift), icon('pencil') . __('edit')) : '',
- $shift_admin ? button(shift_delete_link($shift), icon('trash') . __('delete')) : '',
- $admin_shifttypes ? button(shifttype_link($shifttype), $shifttype->name) : '',
- $admin_rooms ? button(room_link($room), icon('pin-map-fill') . $room->name) : '',
+ $shift_admin ? button(shift_edit_link($shift), icon('pencil'), '', '', __('form.edit')) : '',
+ $shift_admin ? button(shift_delete_link($shift), icon('trash'), 'btn-danger', '', __('form.delete')) : '',
+ $admin_shifttypes
+ ? button(url('/admin/shifttypes/' . $shifttype->id), htmlspecialchars($shifttype->name))
+ : '',
+ $admin_locations
+ ? button(
+ location_link($location),
+ icon('pin-map-fill') . htmlspecialchars($location->name)
+ )
+ : '',
];
}
- $buttons[] = button(user_link(auth()->user()->id), ' ' . __('My shifts'));
+ $buttons[] = button(
+ user_link(auth()->user()->id),
+ ' ' . __('profile.my-shifts')
+ );
$content[] = buttons($buttons);
- $content[] = Shift_view_header($shift, $room);
+ $content[] = Shift_view_header($shift, $location);
$content[] = div('row', [
div('col-sm-6', [
'' . __('Needed angels') . '
',
'' . $needed_angels . '
',
]),
div('col-sm-6', [
- '' . __('Description') . '
',
- $parsedown->parse($shifttype->description),
- $parsedown->parse($shift->description),
+ '' . __('general.description') . '
',
+ $parsedown->parse(htmlspecialchars($shifttype->description)),
+ $parsedown->parse(htmlspecialchars($shift->description)),
]),
]);
@@ -197,10 +215,13 @@ function Shift_view(Shift $shift, ShiftType $shifttype, Room $room, $angeltypes_
$content[] = Shift_editor_info_render($shift);
}
- $start = $shift->start->format(__('Y-m-d H:i'));
+ $start = $shift->start->format(__('general.datetime'));
+ $link = button(url('/user-shifts'), icon('chevron-left'), 'btn-sm', '', __('general.back'));
return page_with_title(
- $shift->shiftType->name . ' %c',
+ $link . ' '
+ . htmlspecialchars($shift->shiftType->name)
+ . ' %c',
$content
);
}
@@ -273,14 +294,15 @@ function Shift_view_render_shift_entry(ShiftEntry $shift_entry, $user_shift_admi
$entry .= ' ';
if ($user_shift_admin || $isUser) {
$entry .= button_icon(
- page_link_to('user_myshifts', ['edit' => $shift_entry->id, 'id' => $shift_entry->user_id]),
+ url('/user-myshifts', ['edit' => $shift_entry->id, 'id' => $shift_entry->user_id]),
'pencil',
- 'btn-sm'
+ 'btn-sm',
+ __('form.edit')
);
}
$angeltype = $shift_entry->angelType;
$disabled = Shift_signout_allowed($shift, $angeltype, $shift_entry->user_id) ? '' : ' btn-disabled';
- $entry .= button_icon(shift_entry_delete_link($shift_entry), 'trash', 'btn-sm' . $disabled);
+ $entry .= button_icon(shift_entry_delete_link($shift_entry), 'trash', 'btn-sm btn-danger' . $disabled, __('form.delete'));
$entry .= '
';
}
return $entry;
diff --git a/includes/view/UserAngelTypes_view.php b/includes/view/UserAngelTypes_view.php
index e50e1f045..aa9162567 100644
--- a/includes/view/UserAngelTypes_view.php
+++ b/includes/view/UserAngelTypes_view.php
@@ -25,12 +25,12 @@ function UserAngelType_update_view(UserAngelType $user_angeltype, User $user, An
form([
buttons([
button(
- page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
- icon('x-lg') . __('cancel')
+ url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
+ icon('x-lg') . __('form.cancel')
),
- form_submit('submit', icon('check-lg') . __('yes'), 'btn-primary', false),
+ form_submit('submit', icon('check-lg') . __('Yes'), 'btn-primary', false),
]),
- ], page_link_to('user_angeltypes', [
+ ], url('/user-angeltypes', [
'action' => 'update',
'user_angeltype_id' => $user_angeltype->id,
'supporter' => ($supporter ? '1' : '0'),
@@ -50,15 +50,15 @@ function UserAngelTypes_delete_all_view(AngelType $angeltype)
form([
buttons([
button(
- page_link_to(
- 'angeltypes',
+ url(
+ '/angeltypes',
['action' => 'view', 'angeltype_id' => $angeltype->id]
),
- icon('x-lg') . __('cancel')
+ icon('x-lg') . __('form.cancel')
),
- form_submit('deny_all', icon('check-lg') . __('yes'), 'btn-primary', false),
+ form_submit('deny_all', icon('check-lg') . __('Yes'), 'btn-primary', false),
]),
- ], page_link_to('user_angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype->id])),
+ ], url('/user-angeltypes', ['action' => 'delete_all', 'angeltype_id' => $angeltype->id])),
]);
}
@@ -73,10 +73,10 @@ function UserAngelTypes_confirm_all_view(AngelType $angeltype)
info(sprintf(__('Do you really want to confirm all users for %s?'), $angeltype->name), true),
form([
buttons([
- button(angeltype_link($angeltype->id), icon('x-lg') . __('cancel')),
- form_submit('confirm_all', icon('check-lg') . __('yes'), 'btn-primary', false),
+ button(angeltype_link($angeltype->id), icon('x-lg') . __('form.cancel')),
+ form_submit('confirm_all', icon('check-lg') . __('Yes'), 'btn-primary', false),
]),
- ], page_link_to('user_angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype->id])),
+ ], url('/user-angeltypes', ['action' => 'confirm_all', 'angeltype_id' => $angeltype->id])),
]);
}
@@ -97,10 +97,10 @@ function UserAngelType_confirm_view(UserAngelType $user_angeltype, User $user, A
), true),
form([
buttons([
- button(angeltype_link($angeltype->id), icon('x-lg') . __('cancel')),
- form_submit('confirm_user', icon('check-lg') . __('yes'), 'btn-primary', false),
+ button(angeltype_link($angeltype->id), icon('x-lg') . __('form.cancel')),
+ form_submit('confirm_user', icon('check-lg') . __('Yes'), 'btn-primary', false),
]),
- ], page_link_to('user_angeltypes', ['action' => 'confirm', 'user_angeltype_id' => $user_angeltype->id])),
+ ], url('/user-angeltypes', ['action' => 'confirm', 'user_angeltype_id' => $user_angeltype->id])),
]);
}
@@ -121,10 +121,10 @@ function UserAngelType_delete_view(UserAngelType $user_angeltype, User $user, An
), true),
form([
buttons([
- button(angeltype_link($angeltype->id), icon('x-lg') . __('cancel')),
- form_submit('delete', icon('check-lg') . __('yes'), 'btn-primary', false),
+ button(angeltype_link($angeltype->id), icon('x-lg') . __('form.cancel')),
+ form_submit('delete', icon('check-lg') . __('Yes'), 'btn-primary', false),
]),
- ], page_link_to('user_angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id])),
+ ], url('/user-angeltypes', ['action' => 'delete', 'user_angeltype_id' => $user_angeltype->id])),
], true);
}
@@ -138,23 +138,22 @@ function UserAngelType_add_view(AngelType $angeltype, $users_source, $user_id)
{
$users = [];
foreach ($users_source as $user_source) {
- $users[$user_source->id] = User_Nick_render($user_source);
+ $users[$user_source->id] = $user_source->displayName;
}
-
- return page_with_title(__('Add user to angeltype'), [
+ $link = button(
+ url('/angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
+ icon('chevron-left'),
+ 'btn-sm',
+ '',
+ __('general.back')
+ );
+ return page_with_title($link . ' ' . __('Add user to angeltype'), [
msg(),
- buttons([
- button(
- page_link_to('angeltypes', ['action' => 'view', 'angeltype_id' => $angeltype->id]),
- __('back'),
- 'back'
- ),
- ]),
form([
- form_info(__('Angeltype'), $angeltype->name),
+ form_info(__('Angeltype'), htmlspecialchars($angeltype->name)),
form_checkbox('auto_confirm_user', __('Confirm user'), true),
- form_select('user_id', __('User'), $users, $user_id),
- form_submit('submit', __('Add')),
+ form_select('user_id', __('general.user'), $users, $user_id),
+ form_submit('submit', icon('plus-lg') . __('Add')),
]),
]);
}
@@ -166,21 +165,22 @@ function UserAngelType_add_view(AngelType $angeltype, $users_source, $user_id)
*/
function UserAngelType_join_view($user, AngelType $angeltype)
{
- return page_with_title(sprintf(__('Become a %s'), $angeltype->name), [
+ $isOther = $user->id != auth()->user()->id;
+ return page_with_title(sprintf(__('Become a %s'), htmlspecialchars($angeltype->name)), [
msg(),
info(sprintf(
- __('Do you really want to add %s to %s?'),
+ $isOther ? __('Do you really want to add %s to %s?') : __('Do you want to become a %2$s?'),
$user->displayName,
$angeltype->name
), true),
form([
auth()->can('admin_user_angeltypes') ? form_checkbox('auto_confirm_user', __('Confirm user'), true) : '',
buttons([
- button(angeltype_link($angeltype->id), icon('x-lg') . __('cancel')),
- form_submit('submit', icon('check-lg') . __('save'), 'btn-primary', false),
+ button(angeltype_link($angeltype->id), icon('x-lg') . __('form.cancel')),
+ form_submit('submit', icon('save') . __('form.save'), 'btn-primary', false),
]),
- ], page_link_to(
- 'user_angeltypes',
+ ], url(
+ '/user-angeltypes',
['action' => 'add', 'angeltype_id' => $angeltype->id, 'user_id' => $user->id]
)),
]);
diff --git a/includes/view/UserDriverLicenses_view.php b/includes/view/UserDriverLicenses_view.php
deleted file mode 100644
index b3bb24f85..000000000
--- a/includes/view/UserDriverLicenses_view.php
+++ /dev/null
@@ -1,73 +0,0 @@
-id), __('Back to profile'), 'back'),
- ]),
- msg(),
- form([
- form_info(__('Privacy'), __('Your driving license information is only visible for supporters and admins.')),
- form_checkbox('wants_to_drive', __('I am willing to drive a car for the event'), $user_driver_license->wantsToDrive()),
- div('m-3', [
- form_checkbox(
- 'has_car',
- __('I have my own car with me and am willing to use it for the event (You\'ll get reimbursed for fuel)'),
- $user_driver_license->has_car
- ),
- heading(__('Driver license'), 3),
- form_checkbox('has_license_car', __('Car'), $user_driver_license->drive_car),
- form_checkbox(
- 'has_license_3_5t_transporter',
- __('Transporter 3,5t'),
- $user_driver_license->drive_3_5t
- ),
- form_checkbox(
- 'has_license_7_5t_truck',
- __('Truck 7,5t'),
- $user_driver_license->drive_7_5t
- ),
- form_checkbox(
- 'has_license_12t_truck',
- __('Truck 12t'),
- $user_driver_license->drive_12t
- ),
- form_checkbox(
- 'has_license_forklift',
- __('Forklift'),
- $user_driver_license->drive_forklift
- ),
- ], 'driving_license'),
- form_submit('submit', __('Save')),
- ]),
- '
-
- ',
- ], true);
-}
diff --git a/includes/view/UserHintsRenderer.php b/includes/view/UserHintsRenderer.php
index 55c655959..4a06686f6 100644
--- a/includes/view/UserHintsRenderer.php
+++ b/includes/view/UserHintsRenderer.php
@@ -20,9 +20,9 @@ public function addHint($hint, $important = false)
if (!empty($hint)) {
if ($important) {
$this->important = true;
- $this->hints[] = error($hint, true);
+ $this->hints[] = error($hint, true, true);
} else {
- $this->hints[] = info($hint, true);
+ $this->hints[] = info($hint, true, true);
}
}
}
diff --git a/includes/view/User_view.php b/includes/view/User_view.php
index aa6e5b793..c64221879 100644
--- a/includes/view/User_view.php
+++ b/includes/view/User_view.php
@@ -19,18 +19,16 @@
*/
function User_delete_view($user)
{
- return page_with_title(sprintf(__('Delete %s'), User_Nick_render($user)), [
+ $link = button(user_edit_link($user->id), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title($link . ' ' . sprintf(__('Delete %s'), User_Nick_render($user)), [
msg(),
- buttons([
- button(user_edit_link($user->id), icon('chevron-left') . __('back')),
- ]),
error(
__('Do you really want to delete the user including all his shifts and every other piece of his data?'),
true
),
form([
form_password('password', __('Your password'), 'current-password'),
- form_submit('submit', __('Delete')),
+ form_submit('submit', __('form.delete')),
]),
]);
}
@@ -43,25 +41,26 @@ function User_delete_view($user)
*/
function User_edit_vouchers_view($user)
{
- return page_with_title(sprintf(__('%s\'s vouchers'), User_Nick_render($user)), [
- msg(),
- buttons([
- button(user_link($user->id), icon('chevron-left') . __('back')),
- ]),
- info(sprintf(
- $user->state->force_active
- ? __('Angel can receive another %d vouchers and is FA.')
- : __('Angel can receive another %d vouchers.'),
- User_get_eligable_voucher_count($user)
- ), true),
- form(
- [
- form_spinner('vouchers', __('Number of vouchers given out'), $user->state->got_voucher),
- form_submit('submit', __('Save')),
- ],
- page_link_to('users', ['action' => 'edit_vouchers', 'user_id' => $user->id])
- ),
- ]);
+ $link = button(user_link($user->id), icon('chevron-left'), 'btn-sm', '', __('general.back'));
+ return page_with_title(
+ $link . ' ' . sprintf(__('%s\'s vouchers'), User_Nick_render($user)),
+ [
+ msg(),
+ info(sprintf(
+ $user->state->force_active
+ ? __('Angel can receive another %d vouchers and is FA.')
+ : __('Angel can receive another %d vouchers.'),
+ User_get_eligable_voucher_count($user)
+ ), true),
+ form(
+ [
+ form_spinner('vouchers', __('Number of vouchers given out'), $user->state->got_voucher),
+ form_submit('submit', icon('save') . __('form.save')),
+ ],
+ url('/users', ['action' => 'edit_vouchers', 'user_id' => $user->id])
+ ),
+ ]
+ );
}
/**
@@ -91,10 +90,12 @@ function Users_view(
$usersList = [];
foreach ($users as $user) {
$u = [];
- $u['name'] = User_Nick_render($user) . User_Pronoun_render($user);
- $u['first_name'] = $user->personalData->first_name;
- $u['last_name'] = $user->personalData->last_name;
- $u['dect'] = sprintf('%1$s', $user->contact->dect);
+ $u['name'] = User_Nick_render($user)
+ . User_Pronoun_render($user)
+ . user_info_icon($user);
+ $u['first_name'] = htmlspecialchars((string) $user->personalData->first_name);
+ $u['last_name'] = htmlspecialchars((string) $user->personalData->last_name);
+ $u['dect'] = sprintf('%1$s', htmlspecialchars((string) $user->contact->dect));
$u['arrived'] = icon_bool($user->state->arrived);
if (config('enable_voucher')) {
$u['got_voucher'] = $user->state->got_voucher;
@@ -109,12 +110,21 @@ function Users_view(
}
}
$u['arrival_date'] = $user->personalData->planned_arrival_date
- ? $user->personalData->planned_arrival_date->format(__('Y-m-d')) : '';
+ ? $user->personalData->planned_arrival_date->format(__('general.date')) : '';
$u['departure_date'] = $user->personalData->planned_departure_date
- ? $user->personalData->planned_departure_date->format(__('Y-m-d')) : '';
- $u['last_login_at'] = $user->last_login_at ? $user->last_login_at->format(__('m/d/Y h:i a')) : '';
+ ? $user->personalData->planned_departure_date->format(__('general.date')) : '';
+ $u['last_login_at'] = $user->last_login_at ? $user->last_login_at->format(__('general.datetime')) : '';
$u['actions'] = table_buttons([
- button_icon(page_link_to('admin_user', ['id' => $user->id]), 'pencil', 'btn-sm'),
+ button(
+ url(
+ '/admin-user',
+ ['id' => $user->id]
+ ),
+ icon('pencil'),
+ 'btn-sm',
+ '',
+ __('form.edit')
+ ),
]);
$usersList[] = $u;
}
@@ -132,21 +142,21 @@ function Users_view(
$user_table_headers = [];
if (!config('display_full_name')) {
- $user_table_headers['name'] = Users_table_header_link('name', __('Nick'), $order_by);
+ $user_table_headers['name'] = Users_table_header_link('name', __('general.nick'), $order_by);
}
if (config('enable_user_name')) {
- $user_table_headers['first_name'] = Users_table_header_link('first_name', __('Prename'), $order_by);
- $user_table_headers['last_name'] = Users_table_header_link('last_name', __('Name'), $order_by);
+ $user_table_headers['first_name'] = Users_table_header_link('first_name', __('settings.profile.firstname'), $order_by);
+ $user_table_headers['last_name'] = Users_table_header_link('last_name', __('settings.profile.lastname'), $order_by);
}
if (config('enable_dect')) {
- $user_table_headers['dect'] = Users_table_header_link('dect', __('DECT'), $order_by);
+ $user_table_headers['dect'] = Users_table_header_link('dect', __('general.dect'), $order_by);
}
$user_table_headers['arrived'] = Users_table_header_link('arrived', __('Arrived'), $order_by);
if (config('enable_voucher')) {
$user_table_headers['got_voucher'] = Users_table_header_link('got_voucher', __('Voucher'), $order_by);
}
$user_table_headers['freeloads'] = Users_table_header_link('freeloads', __('Freeloads'), $order_by);
- $user_table_headers['active'] = Users_table_header_link('active', __('Active'), $order_by);
+ $user_table_headers['active'] = Users_table_header_link('active', __('user.active'), $order_by);
$user_table_headers['force_active'] = Users_table_header_link('force_active', __('Forced'), $order_by);
if ($goodie_enabled) {
if ($goodie_tshirt) {
@@ -173,11 +183,9 @@ function Users_view(
unset($user_table_headers[$key]);
}
- return page_with_title(__('All users'), [
+ $link = button(url('/register'), icon('plus-lg'), 'add');
+ return page_with_title(__('All users') . ' ' . $link, [
msg(),
- buttons([
- button(page_link_to('register'), icon('plus-lg') . __('New user')),
- ]),
table($user_table_headers, $usersList),
]);
}
@@ -191,7 +199,7 @@ function Users_view(
function Users_table_header_link($column, $label, $order_by)
{
return ''
. $label . ($order_by == $column ? ' ' : '')
. '';
@@ -209,7 +217,7 @@ function User_shift_state_render($user)
$upcoming_shifts = ShiftEntries_upcoming_for_user($user);
if ($upcoming_shifts->isEmpty()) {
- return '' . __('Free') . '';
+ return '' . __('free') . '';
}
/** @var ShiftEntry $nextShiftEntry */
@@ -217,8 +225,8 @@ function User_shift_state_render($user)
$start = $nextShiftEntry->shift->start;
$end = $nextShiftEntry->shift->end;
- $startFormat = $start->format(__('Y-m-d H:i'));
- $endFormat = $end->format(__('Y-m-d H:i'));
+ $startFormat = $start->format(__('general.datetime'));
+ $endFormat = $end->format(__('general.datetime'));
$startTimestamp = $start->timestamp;
$endTimestamp = $end->timestamp;
@@ -260,7 +268,7 @@ function User_last_shift_render($user)
$lastShiftEntry = $last_shifts->first();
$end = $lastShiftEntry->shift->end;
- return ''
+ return ''
. __('Shift ended %c')
. '';
}
@@ -272,8 +280,8 @@ function User_last_shift_render($user)
function User_view_shiftentries($needed_angel_type)
{
$shift_info = '
' . $needed_angel_type['name'] . ': ';
+ . url('/angeltypes', ['action' => 'view', 'angeltype_id' => $needed_angel_type['id']])
+ . '">' . htmlspecialchars($needed_angel_type['name']) . ': ';
$shift_entries = [];
foreach ($needed_angel_type['users'] as $user_shift) {
@@ -299,9 +307,9 @@ function User_view_shiftentries($needed_angel_type)
*/
function User_view_myshift(Shift $shift, $user_source, $its_me)
{
- $shift_info = '' . $shift->shiftType->name . '';
+ $shift_info = '' . htmlspecialchars($shift->shiftType->name) . '';
if ($shift->title) {
- $shift_info .= '
' . $shift->title . '';
+ $shift_info .= '
' . htmlspecialchars($shift->title) . '';
}
foreach ($shift->needed_angeltypes as $needed_angel_type) {
$shift_info .= User_view_shiftentries($needed_angel_type);
@@ -309,18 +317,21 @@ function User_view_myshift(Shift $shift, $user_source, $its_me)
$myshift = [
'date' => icon('calendar-event')
- . $shift->start->format(__('Y-m-d')) . '
'
+ . $shift->start->format(__('general.date')) . '
'
. icon('clock-history') . $shift->start->format('H:i')
. ' - '
. $shift->end->format(__('H:i')),
'duration' => sprintf('%.2f', ($shift->end->timestamp - $shift->start->timestamp) / 3600) . ' h',
- 'room' => Room_name_render($shift->room),
+ 'location' => location_name_render($shift->location),
'shift_info' => $shift_info,
'comment' => '',
+ 'start' => $shift->start,
+ 'end' => $shift->end,
+ 'freeloaded' => $shift->freeloaded,
];
if ($its_me) {
- $myshift['comment'] = $shift->user_comment;
+ $myshift['comment'] = htmlspecialchars($shift->user_comment);
}
if ($shift->freeloaded) {
@@ -329,31 +340,37 @@ function User_view_myshift(Shift $shift, $user_source, $its_me)
. '';
if (auth()->can('user_shifts_admin')) {
$myshift['comment'] .= '
'
- . '' . __('Freeloaded') . ': ' . $shift->freeloaded_comment . '
';
+ . ''
+ . __('Freeloaded') . ': ' . htmlspecialchars($shift->freeloaded_comment)
+ . '
';
} else {
$myshift['comment'] .= '
' . __('Freeloaded') . '
';
}
}
$myshift['actions'] = [
- button(shift_link($shift), icon('eye') . __('view'), 'btn-sm'),
+ button(shift_link($shift), icon('eye'), 'btn-sm btn-info', '', __('View')),
];
if ($its_me || auth()->can('user_shifts_admin')) {
$myshift['actions'][] = button(
- page_link_to('user_myshifts', ['edit' => $shift->shift_entry_id, 'id' => $user_source->id]),
- icon('pencil') . __('edit'),
- 'btn-sm'
+ url('/user-myshifts', ['edit' => $shift->shift_entry_id, 'id' => $user_source->id]),
+ icon('pencil'),
+ 'btn-sm',
+ '',
+ __('form.edit')
);
}
if (Shift_signout_allowed($shift, (new AngelType())->forceFill(['id' => $shift->angel_type_id]), $user_source->id)) {
$myshift['actions'][] = button(
shift_entry_delete_link($shift),
- icon('trash') . __('sign off'),
- 'btn-sm'
+ icon('trash'),
+ 'btn-sm btn-danger',
+ '',
+ __('Sign off')
);
}
- $myshift['actions'] = table_buttons($myshift['actions']);
+ $myshift['actions'] = '' . table_buttons($myshift['actions']) . '
';
return $myshift;
}
@@ -388,35 +405,48 @@ function User_view_myshifts(
foreach ($shifts as $shift) {
$key = $shift->start->timestamp . '-shift-' . $shift->shift_entry_id . $shift->id;
$myshifts_table[$key] = User_view_myshift($shift, $user_source, $its_me);
-
if (!$shift->freeloaded) {
$timeSum += ($shift->end->timestamp - $shift->start->timestamp);
}
}
- if ($its_me || $admin_user_worklog_privilege) {
- foreach ($user_worklogs as $worklog) {
- $key = $worklog->worked_at->timestamp . '-worklog-' . $worklog->id;
- $myshifts_table[$key] = User_view_worklog($worklog, $admin_user_worklog_privilege);
- $timeSum += $worklog->hours * 3600;
- }
+ foreach ($user_worklogs as $worklog) {
+ $key = $worklog->worked_at->timestamp . '-worklog-' . $worklog->id;
+ $myshifts_table[$key] = User_view_worklog($worklog, $admin_user_worklog_privilege);
+ $timeSum += $worklog->hours * 3600;
}
if (count($myshifts_table) > 0) {
ksort($myshifts_table);
+ $myshifts_table = array_values($myshifts_table);
+ foreach ($myshifts_table as $i => &$shift) {
+ $before = $myshifts_table[$i - 1] ?? null;
+ $after = $myshifts_table[$i + 1] ?? null;
+ if ($shift['freeloaded']) {
+ $shift['row-class'] = 'border border-danger border-2';
+ } elseif (Carbon::now() > $shift['start'] && Carbon::now() < $shift['end']) {
+ $shift['row-class'] = 'border border-info border-2';
+ } elseif ($after && Carbon::now() > $shift['end'] && Carbon::now() < $after['start']) {
+ $shift['row-class'] = 'border-bottom border-info';
+ } elseif (!$before && Carbon::now() < $shift['start']) {
+ $shift['row-class'] = 'border-top-info';
+ } elseif (!$after && Carbon::now() > $shift['end']) {
+ $shift['row-class'] = 'border-bottom border-info';
+ }
+ }
$myshifts_table[] = [
'date' => '' . __('Sum:') . '',
'duration' => '' . sprintf('%.2f', round($timeSum / 3600, 2)) . ' h',
- 'room' => '',
+ 'location' => '',
'shift_info' => '',
'comment' => '',
'actions' => '',
];
- if ($goodie_enabled && ($its_me || $tshirt_admin)) {
+ if ($goodie_enabled && ($its_me || $tshirt_admin || auth()->can('admin_user'))) {
$myshifts_table[] = [
- 'date' => '' . ($goodie_tshirt ? __('Your t-shirt score') : __('Your goodie score')) . '™:',
+ 'date' => '' . ($goodie_tshirt ? __('T-shirt score') : __('Goodie score')) . '™:',
'duration' => '' . $tshirt_score . '',
- 'room' => '',
+ 'location' => '',
'shift_info' => '',
'comment' => '',
'actions' => '',
@@ -437,32 +467,39 @@ function User_view_worklog(Worklog $worklog, $admin_user_worklog_privilege)
{
$actions = '';
if ($admin_user_worklog_privilege) {
- $actions = table_buttons([
+ $actions = '' . table_buttons([
button(
url('/admin/user/' . $worklog->user->id . '/worklog/' . $worklog->id),
- icon('pencil') . __('edit'),
- 'btn-sm'
+ icon('pencil'),
+ 'btn-sm',
+ '',
+ __('form.edit')
),
button(
url('/admin/user/' . $worklog->user->id . '/worklog/' . $worklog->id . '/delete'),
- icon('trash') . __('delete'),
- 'btn-sm'
+ icon('trash'),
+ 'btn-sm btn-danger',
+ '',
+ __('form.delete')
),
- ]);
+ ]) . '
';
}
return [
- 'date' => icon('calendar-event') . date(__('Y-m-d'), $worklog->worked_at->timestamp),
+ 'date' => icon('calendar-event') . date(__('general.date'), $worklog->worked_at->timestamp),
'duration' => sprintf('%.2f', $worklog->hours) . ' h',
- 'room' => '',
+ 'location' => '',
'shift_info' => __('Work log entry'),
- 'comment' => $worklog->comment . '
'
+ 'comment' => htmlspecialchars($worklog->comment) . '
'
. sprintf(
__('Added by %s at %s'),
User_Nick_render($worklog->creator),
- $worklog->created_at->format(__('Y-m-d H:i'))
+ $worklog->created_at->format(__('general.datetime'))
),
'actions' => $actions,
+ 'start' => $worklog->worked_at,
+ 'end' => $worklog->worked_at,
+ 'freeloaded' => false,
];
}
@@ -501,11 +538,10 @@ function User_view(
$goodie_tshirt = $goodie === GoodieType::Tshirt;
$auth = auth();
$nightShiftsConfig = config('night_shifts');
- $user_name = htmlspecialchars(
- $user_source->personalData->first_name
- ) . ' ' . htmlspecialchars($user_source->personalData->last_name);
+ $user_name = htmlspecialchars((string) $user_source->personalData->first_name) . ' '
+ . htmlspecialchars((string) $user_source->personalData->last_name);
$myshifts_table = '';
- if ($its_me || $admin_user_privilege) {
+ if ($its_me || $admin_user_privilege || $tshirt_admin) {
$my_shifts = User_view_myshifts(
$shifts,
$user_source,
@@ -516,16 +552,19 @@ function User_view(
$admin_user_worklog_privilege
);
if (count($my_shifts) > 0) {
- $myshifts_table = table([
- 'date' => __('Day & time'),
+ $myshifts_table = div('table-responsive', table([
+ 'date' => __('Day & Time'),
'duration' => __('Duration'),
- 'room' => __('Location'),
- 'shift_info' => __('Name & workmates'),
- 'comment' => __('Comment'),
- 'actions' => __('Action'),
- ], $my_shifts);
+ 'location' => __('Location'),
+ 'shift_info' => __('Name & Workmates'),
+ 'comment' => __('worklog.comment'),
+ 'actions' => __('general.actions'),
+ ], $my_shifts));
} elseif ($user_source->state->force_active) {
- $myshifts_table = success(__('You have done enough.'), true);
+ $myshifts_table = success(
+ ($its_me ? __('You have done enough.') : (__('%s has done enough.', [$user_source->name]))),
+ true
+ );
}
}
@@ -534,6 +573,11 @@ function User_view(
$needs_drivers_license = $needs_drivers_license || $angeltype->requires_driver_license;
}
+ $needs_ifsg_certificate = false;
+ foreach ($user_angeltypes as $angeltype) {
+ $needs_ifsg_certificate = $needs_ifsg_certificate || $angeltype->requires_ifsg_certificate;
+ }
+
return page_with_title(
' '
. (
@@ -542,34 +586,31 @@ function User_view(
: ''
)
. htmlspecialchars($user_source->name)
- . (config('enable_user_name') ? ' ' . $user_name . '' : ''),
+ . (config('enable_user_name') ? ' ' . $user_name . '' : '')
+ . user_info_icon($user_source),
[
msg(),
div('row', [
div('col-md-12', [
- buttons([
+ table_buttons([
$auth->can('user.edit.shirt') && $goodie_enabled ? button(
url('/admin/user/' . $user_source->id . '/goodie'),
icon('person') . ($goodie_tshirt ? __('Shirt') : __('Goodie'))
) : '',
$admin_user_privilege ? button(
- page_link_to('admin_user', ['id' => $user_source->id]),
- icon('pencil') . __('edit')
- ) : '',
- $admin_user_privilege || ($its_me && $needs_drivers_license) ? button(
- user_driver_license_edit_link($user_source),
- icon('person-vcard') . __('driving license')
+ url('/admin-user', ['id' => $user_source->id]),
+ icon('pencil') . __('form.edit'),
) : '',
(($admin_user_privilege || $auth->can('admin_arrive')) && !$user_source->state->arrived) ?
form([
form_hidden('action', 'arrived'),
form_hidden('user', $user_source->id),
- form_submit('submit', __('arrived'), '', false),
- ], page_link_to('admin_arrive'), true) : '',
+ form_submit('submit', icon('house') . __('user.arrive'), '', false),
+ ], url('/admin-arrive'), 'float:left') : '',
($admin_user_privilege || $auth->can('voucher.edit')) && config('enable_voucher') ?
button(
- page_link_to(
- 'users',
+ url(
+ '/users',
['action' => 'edit_vouchers', 'user_id' => $user_source->id]
),
icon('valentine') . __('Vouchers')
@@ -579,27 +620,29 @@ function User_view(
url('/admin/user/' . $user_source->id . '/worklog'),
icon('clock-history') . __('worklog.add')
) : '',
- $its_me ? button(
- page_link_to('settings/profile'),
- icon('person-fill-gear') . __('Settings')
- ) : '',
- ($its_me && $auth->can('ical')) ? button(
- page_link_to('ical', ['key' => $user_source->api_key]),
+ ], 'mb-2'),
+ $its_me ? table_buttons([
+ button(
+ url('/settings/profile'),
+ icon('person-fill-gear') . __('settings.settings')
+ ),
+ $auth->can('ical') ? button(
+ url('/ical', ['key' => $user_source->api_key]),
icon('calendar-week') . __('iCal Export')
) : '',
- ($its_me && $auth->can('shifts_json_export')) ? button(
- page_link_to('shifts_json_export', ['key' => $user_source->api_key]),
+ $auth->can('shifts_json_export') ? button(
+ url('/shifts-json-export', ['key' => $user_source->api_key]),
icon('braces') . __('JSON Export')
) : '',
- ($its_me && (
- $auth->can('shifts_json_export')
- || $auth->can('ical')
- || $auth->can('atom')
- )) ? button(
- page_link_to('user_myshifts', ['reset' => 1]),
- icon('arrow-repeat') . __('Reset API key')
- ) : '',
- ]),
+ (
+ $auth->can('shifts_json_export')
+ || $auth->can('ical')
+ || $auth->can('atom')
+ ) ? button(
+ url('/user-myshifts', ['reset' => 1]),
+ icon('arrow-repeat') . __('Reset API key')
+ ) : '',
+ ], 'mb-2') : '',
]),
]),
div('row user-info', [
@@ -607,8 +650,8 @@ function User_view(
config('enable_dect') && $user_source->contact->dect ?
heading(
icon('phone')
- . ' '
- . $user_source->contact->dect
+ . ' '
+ . htmlspecialchars($user_source->contact->dect)
. ''
)
: '',
@@ -616,15 +659,15 @@ function User_view(
$user_source->settings->mobile_show ?
heading(
icon('phone')
- . ' '
- . $user_source->contact->mobile
+ . ' '
+ . htmlspecialchars($user_source->contact->mobile)
. ''
)
: ''
: '',
$auth->can('user_messages') ?
heading(
- ''
+ ''
. icon('envelope')
. ''
)
@@ -638,18 +681,20 @@ function User_view(
($its_me || $admin_user_privilege) ? '' . __('Shifts') . '
' : '',
$myshifts_table,
($its_me && $nightShiftsConfig['enabled'] && $goodie_enabled) ? info(
- icon('info-circle') . sprintf(
- __('Your night shifts between %d and %d am count twice.'),
+ sprintf(
+ icon('info-circle') . __('Your night shifts between %d and %d am count twice for the %s score.'),
$nightShiftsConfig['start'],
- $nightShiftsConfig['end']
+ $nightShiftsConfig['end'],
+ ($goodie_tshirt ? __('T-shirt') : __('goodie'))
),
+ true,
true
) : '',
$its_me && count($shifts) == 0
? error(sprintf(
__('Go to the shifts table to sign yourself up for some shifts.'),
- page_link_to('user_shifts')
- ), true)
+ url('/user-shifts')
+ ), true, true)
: '',
$its_me ? ical_hint() : '',
]
@@ -673,7 +718,7 @@ function User_view_state($admin_user_privilege, $freeloader, $user_source)
}
return div('col-md-2', [
- heading(__('User state'), 4),
+ heading(__('State'), 4),
join('
', $state),
]);
}
@@ -691,7 +736,7 @@ function User_view_state_user($user_source)
];
if ($user_source->state->arrived) {
- $state[] = '' . icon('house') . __('Arrived') . '';
+ $state[] = '' . icon('house') . __('user.arrived') . '';
} else {
$state[] = '' . __('Not arrived') . '';
}
@@ -724,24 +769,24 @@ function User_view_state_admin($freeloader, $user_source)
$state[] = '' . icon('house')
. sprintf(
__('Arrived at %s'),
- $user_source->state->arrival_date ? $user_source->state->arrival_date->format(__('Y-m-d')) : ''
+ $user_source->state->arrival_date ? $user_source->state->arrival_date->format(__('general.date')) : ''
)
. '';
if ($user_source->state->force_active) {
- $state[] = '' . __('Active (forced)') . '';
+ $state[] = '' . __('user.force_active') . '';
} elseif ($user_source->state->active) {
- $state[] = '' . __('Active') . '';
+ $state[] = '' . __('user.active') . '';
}
if ($user_source->state->got_shirt && $goodie_enabled) {
- $state[] = '' . ($goodie_tshirt ? __('T-Shirt') : __('Goodie')) . '';
+ $state[] = '' . ($goodie_tshirt ? __('T-shirt') : __('Goodie')) . '';
}
} else {
$arrivalDate = $user_source->personalData->planned_arrival_date;
$state[] = ''
. ($arrivalDate ? sprintf(
__('Not arrived (Planned: %s)'),
- $arrivalDate->format(__('Y-m-d'))
+ $arrivalDate->format(__('general.date'))
) : __('Not arrived'))
. '';
}
@@ -779,11 +824,11 @@ function User_angeltypes_render($user_angeltypes)
$class = 'text-warning';
}
$output[] = ''
- . ($angeltype->pivot->supporter ? icon('patch-check') : '') . $angeltype->name
+ . ($angeltype->pivot->supporter ? icon('patch-check') : '') . htmlspecialchars($angeltype->name)
. '';
}
return div('col-md-2', [
- heading(__('Angeltypes'), 4),
+ heading(__('angeltypes.angeltypes'), 4),
join('
', $output),
]);
}
@@ -796,7 +841,7 @@ function User_groups_render($user_groups)
{
$output = [];
foreach ($user_groups as $group) {
- $output[] = __($group->name);
+ $output[] = __(htmlspecialchars($group->name));
}
return div('col-md-2', [
@@ -816,9 +861,11 @@ function User_oauth_render(User $user)
$output = [];
foreach ($user->oauth as $oauth) {
$output[] = __(
- isset($config[$oauth->provider]['name'])
- ? $config[$oauth->provider]['name']
- : Str::ucfirst($oauth->provider)
+ htmlspecialchars(
+ isset($config[$oauth->provider]['name'])
+ ? $config[$oauth->provider]['name']
+ : Str::ucfirst($oauth->provider)
+ )
);
}
@@ -879,9 +926,9 @@ function User_Pronoun_render(User $user): string
*/
function render_profile_link($text, $user_id = null, $class = '')
{
- $profile_link = page_link_to('settings/profile');
+ $profile_link = url('/settings/profile');
if (!is_null($user_id)) {
- $profile_link = page_link_to('users', ['action' => 'view', 'user_id' => $user_id]);
+ $profile_link = url('/users', ['action' => 'view', 'user_id' => $user_id]);
}
return sprintf(
@@ -921,17 +968,22 @@ function render_user_freeloader_hint()
}
/**
- * Hinweis fΓΌr Engel, die noch nicht angekommen sind
+ * hint for angels, which are not arrived yet
*
* @return string|null
*/
-function render_user_arrived_hint()
+function render_user_arrived_hint(bool $is_sys_menu = false)
{
- if (!auth()->user()->state->arrived) {
+ $user = auth()->user();
+ $user_arrival_date = $user->personalData->planned_arrival_date;
+ $is_before_arrival_date = $is_sys_menu && $user_arrival_date && Carbon::now() < $user_arrival_date;
+ if (config('signup_requires_arrival') && !$user->state->arrived && !$is_before_arrival_date) {
/** @var Carbon $buildup */
$buildup = config('buildup_start');
if (!empty($buildup) && $buildup->lessThan(new Carbon())) {
- return __('You are not marked as arrived. Please go to heaven\'s desk, get your angel badge and/or tell them that you arrived already.');
+ return $user->state->user_info
+ ? ($is_sys_menu ? null : __('user_info.not_arrived_hint'))
+ : __('You are not marked as arrived. Please go to heaven, get your angel badge and/or tell them that you arrived already.');
}
}
@@ -945,9 +997,13 @@ function render_user_tshirt_hint()
{
$goodie = GoodieType::from(config('goodie_type'));
$goodie_tshirt = $goodie === GoodieType::Tshirt;
- if ($goodie_tshirt && !auth()->user()->personalData->shirt_size) {
- $text = __('You need to specify a tshirt size in your settings!');
- return render_profile_link($text, null, 'text-danger');
+ if (
+ $goodie_tshirt
+ && config('required_user_fields')['tshirt_size']
+ && !auth()->user()->personalData->shirt_size
+ ) {
+ $text = __('tshirt.required.hint');
+ return render_profile_link($text);
}
return null;
@@ -959,9 +1015,68 @@ function render_user_tshirt_hint()
function render_user_dect_hint()
{
$user = auth()->user();
- if ($user->state->arrived && config('enable_dect') && !$user->contact->dect) {
- $text = __('You need to specify a DECT phone number in your settings! If you don\'t have a DECT phone, just enter \'-\'.');
- return render_profile_link($text, null, 'text-danger');
+ if (
+ (config('required_user_fields')['dect'] || $user->state->arrived)
+ && config('enable_dect') && !$user->contact->dect
+ ) {
+ $text = __('dect.required.hint');
+ return render_profile_link($text);
+ }
+
+ return null;
+}
+
+/**
+ * @return string|null
+ */
+function render_user_pronoun_hint()
+{
+ $user = auth()->user();
+ if (config('required_user_fields')['pronoun'] && config('enable_pronoun') && !$user->personalData->pronoun) {
+ $text = __('pronoun.required.hint');
+ return render_profile_link($text);
+ }
+
+ return null;
+}
+
+/**
+ * @return string|null
+ */
+function render_user_firstname_hint()
+{
+ $user = auth()->user();
+ if (config('required_user_fields')['firstname'] && config('enable_user_name') && !$user->personalData->first_name) {
+ $text = __('firstname.required.hint');
+ return render_profile_link($text);
+ }
+
+ return null;
+}
+
+/**
+ * @return string|null
+ */
+function render_user_lastname_hint()
+{
+ $user = auth()->user();
+ if (config('required_user_fields')['lastname'] && config('enable_user_name') && !$user->personalData->last_name) {
+ $text = __('lastname.required.hint');
+ return render_profile_link($text);
+ }
+
+ return null;
+}
+
+/**
+ * @return string|null
+ */
+function render_user_mobile_hint()
+{
+ $user = auth()->user();
+ if (config('required_user_fields')['mobile'] && !$user->contact->mobile) {
+ $text = __('mobile.required.hint');
+ return render_profile_link($text);
}
return null;
diff --git a/package.json b/package.json
index 93e4e4066..f77f7e324 100644
--- a/package.json
+++ b/package.json
@@ -32,11 +32,11 @@
"babel-loader": "^9.1.2",
"css-loader": "^6.7.3",
"css-minimizer-webpack-plugin": "^4.2.2",
- "editorconfig-checker": "^5.0.1",
- "eslint": "^8.33.0",
- "eslint-plugin-editorconfig": "^4.0.2",
+ "editorconfig-checker": "^5.1.1",
+ "eslint": "^8.44.0",
+ "eslint-plugin-editorconfig": "^4.0.3",
"mini-css-extract-plugin": "^2.7.2",
- "postcss": "^8.4.21",
+ "postcss": "^8.4.31",
"postcss-loader": "^7.0.2",
"prettier": "^2.8.3",
"resolve-url-loader": "^5.0.0",
@@ -47,5 +47,8 @@
"webpack": "^5.76.0",
"webpack-cli": "^5.0.1",
"webpack-manifest-plugin": "^5.0.0"
+ },
+ "resolutions": {
+ "semver": "7.5.3"
}
}
diff --git a/resources/api/openapi.yml b/resources/api/openapi.yml
new file mode 100644
index 000000000..5669114e1
--- /dev/null
+++ b/resources/api/openapi.yml
@@ -0,0 +1,700 @@
+openapi: 3.0.3
+
+info:
+ version: 0.0.1-beta
+ title: Engelsystem
+ description: >
+ This API is as stable as a **beta** version might be.
+ It could burst into flames and morph into a monster at any second!
+ (But we try to keep it somewhat consistent, at least during events).
+ contact:
+ name: GitHub Issues
+ url: https://github.com/engelsystem/engelsystem/issues
+ license:
+ name: GPL 2.0
+ # identifier: GPL-2.0
+
+servers:
+ - url: /api/v0-beta
+ description: This server
+ - url: http://localhost:5080/api/v0-beta
+ description: Your local dev instance
+
+tags:
+ - name: api
+ description: API related
+ - name: angeltype
+ description: Angeltypes
+ - name: event
+ description: Event information
+ - name: location
+ description: Event locations
+ - name: news
+ description: News and meeting announcements
+ - name: shift
+ description: Event shifts
+ - name: user
+ description: User information
+
+security:
+ - bearer-auth: [ ]
+ - api-key-header: [ ]
+
+components:
+ securitySchemes:
+ bearer-auth:
+ type: http
+ scheme: bearer
+ bearerFormat: API key from settings
+ api-key-header:
+ type: apiKey
+ name: x-api-key
+ in: header
+
+ responses:
+ UnauthorizedError: # 401
+ description: Access token is missing or invalid
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ ForbiddenError: # 403
+ description: The client is not allowed to access
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ NotFoundError: # 404
+ description: This resource can not be found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+ NotImplementedError: # 405
+ description: This endpoint or method is not implemented
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Error'
+
+ schemas:
+ AngelType:
+ type: object
+ properties:
+ id:
+ type: integer
+ example: 42
+ name:
+ type: string
+ example: Angel
+ description:
+ type: string
+ example: Meta-Group of all registered Angels
+ url:
+ type: string
+ example: https://example.com/angeltype/42
+ description: Link to the page of the given angeltype.
+ required:
+ - id
+ - name
+ - description
+ - url
+ UserAngelType:
+ allOf:
+ - $ref: '#/components/schemas/AngelType'
+ - type: object
+ properties:
+ confirmed:
+ type: boolean
+ example: true
+ description: >
+ If the user is confirmed
+ (either by the angeltype not requiring confirmation, being a supporter or being confirmed by one).
+ supporter:
+ type: boolean
+ example: false
+ description: If the user is a supporter of the angeltype.
+ required:
+ - confirmed
+ - supporter
+ News:
+ type: object
+ properties:
+ id:
+ type: integer
+ example: 42
+ title:
+ type: string
+ example: First helper introduction
+ text:
+ type: string
+ example: |
+ The first introduction meeting takes place at the **Foo Hall** at 13:37.
+ Please bring your own seating as it might take some time.
+ description: |
+ The complete news text with markdown formatting.
+ Might include a `[more]` tag to be used as a separator which must be removed from the text when shown.
+ is_meeting:
+ type: boolean
+ example: true
+ description: Whether or not the news announces a meeting
+ is_pinned:
+ type: boolean
+ example: false
+ description: True if the news is pinned to the top
+ is_highlighted:
+ type: boolean
+ example: false
+ description: True if the news should be highlightet and shown on the dashboard
+ created_at:
+ $ref: '#/components/schemas/DateTime'
+ updated_at:
+ $ref: '#/components/schemas/DateTimeOptional'
+ url:
+ type: string
+ example: https://example.com/news/42
+ description: Direct link to the news page
+ required:
+ - id
+ - title
+ - text
+ - is_meeting
+ - is_pinned
+ - is_highlighted
+ - created_at
+ - updated_at
+ - url
+ Location:
+ type: object
+ properties:
+ id:
+ type: integer
+ example: 42
+ name:
+ type: string
+ example: Heaven
+ url:
+ type: string
+ example: https://example.com/location/42
+ description: Link of the location page
+ required:
+ - id
+ - name
+ - url
+ Shift:
+ type: object
+ properties:
+ id:
+ type: integer
+ example: 42
+ title:
+ type: string
+ example: Cleanup the venue
+ description:
+ type: string
+ example: You clean up the venue after the event. Its fun, we promise!
+ description: >
+ Shift description, should be added to the shift type description but might be empty.
+ Normally contains additional information for a specific shift / task.
+ starts_at:
+ $ref: '#/components/schemas/DateTime'
+ ends_at:
+ $ref: '#/components/schemas/DateTime'
+ location:
+ $ref: '#/components/schemas/Location'
+ shift_type:
+ $ref: '#/components/schemas/ShiftType'
+ created_at:
+ $ref: '#/components/schemas/DateTimeOptional'
+ updated_at:
+ $ref: '#/components/schemas/DateTimeOptional'
+ entries:
+ type: array
+ description: Can be empty (for example on Schedule import of unused room)
+ items:
+ $ref: '#/components/schemas/ShiftEntry'
+ url:
+ type: string
+ example: https://example.com/shifts/42
+ description: Direct link to the shift
+ required:
+ - id
+ - title
+ - description
+ - starts_at
+ - ends_at
+ - location
+ - shift_type
+ - created_at
+ - updated_at
+ - entries
+ - url
+ ShiftEntry:
+ type: object
+ properties:
+ users:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ type:
+ $ref: '#/components/schemas/AngelType'
+ needs:
+ type: integer
+ description: >
+ Number of users needed for the shift of the given type.
+ Will be more than users count when not full, less when overbooked
+ or 0 when only additional users with given type have been added.
+ example: 3
+ required:
+ - users
+ - type
+ - needs
+ ShiftType:
+ type: object
+ properties:
+ id:
+ type: integer
+ example: 42
+ name:
+ type: string
+ example: Build-Up
+ description:
+ type: string
+ example: This is a generic build-up shift, mostly involving heavy lifting.
+ required:
+ - id
+ - name
+ - description
+ User:
+ type: object
+ properties:
+ id:
+ type: integer
+ example: 42
+ name:
+ type: string
+ example: HelpfulUser
+ first_name:
+ type: string
+ nullable: true
+ example: Helpful
+ last_name:
+ type: string
+ nullable: true
+ example: User
+ pronoun:
+ type: string
+ nullable: true
+ example: They/Them
+ description: Should be displayed where possible to allow users to be addressed properly
+ contact:
+ type: object
+ properties:
+ dect:
+ type: string
+ nullable: true
+ example: 4242
+ description: The DECT number is a short internal number where users can be easily reached
+ mobile:
+ type: string
+ nullable: true
+ example: 1234567890
+ url:
+ type: string
+ example: https://example.com/users/42
+ description: Links to the users profile page
+ required:
+ - id
+ - name
+ - first_name
+ - last_name
+ - pronoun
+ - contact
+ - url
+ UserDetail:
+ allOf:
+ - $ref: '#/components/schemas/User'
+ - type: object
+ properties:
+ email:
+ type: string
+ example: user@example.com
+ tshirt:
+ type: string
+ nullable: true
+ example: XL
+ dates:
+ type: object
+ properties:
+ planned_arrival:
+ $ref: '#/components/schemas/DateTimeOptional'
+ planned_departure:
+ $ref: '#/components/schemas/DateTimeOptional'
+ arrival:
+ type: string
+ nullable: true
+ format: date-time
+ description: Actual arrival date, DateTime in ISO-8601 format
+ example: 2023-05-23T13:37:42.000000Z
+ required:
+ - planned_arrival
+ - planned_departure
+ - arrival
+ language:
+ type: string
+ example: en_US
+ arrived:
+ type: boolean
+ example: true
+ required:
+ - email
+ - tshirt
+ - dates
+ - language
+ - arrived
+
+ DateTime:
+ type: string
+ format: date-time
+ description: DateTime in ISO-8601 format
+ example: 2023-05-23T00:00:00.000000Z
+ DateTimeOptional:
+ type: string
+ format: date-time
+ description: DateTime in ISO-8601 format
+ example: 2023-05-23T00:00:00.000000Z
+ nullable: true
+ Error:
+ type: object
+ properties:
+ message:
+ type: string
+ EventInfo:
+ type: object
+ properties:
+ api:
+ type: string
+ description: API version for easier version detection
+ example: 1.2.3
+ spec:
+ type: string
+ description: Link to OpenAPI specification
+ example: https://galactic-help.example/api/v1.2.3/openapi
+ name:
+ type: string
+ example: 42. Galactic Conglomeration Congress
+ app_name:
+ type: string
+ example: Engelsystem
+ url:
+ type: string
+ description: URL to be used when linking to the application
+ example: https://galactic-help.example
+ timezone:
+ type: string
+ example: Europe/Berlin
+ description: Timezone of the event
+ buildup:
+ type: object
+ properties:
+ start:
+ $ref: '#/components/schemas/DateTimeOptional'
+ required:
+ - start
+ event:
+ type: object
+ properties:
+ start:
+ $ref: '#/components/schemas/DateTimeOptional'
+ end:
+ $ref: '#/components/schemas/DateTimeOptional'
+ required:
+ - start
+ - end
+ teardown:
+ type: object
+ properties:
+ end:
+ $ref: '#/components/schemas/DateTimeOptional'
+ required:
+ - end
+ required:
+ - api
+ - spec
+ - name
+ - app_name
+ - url
+ - timezone
+ - buildup
+ - event
+ - teardown
+
+paths:
+ /angeltypes:
+ get:
+ tags:
+ - angeltype
+ summary: Get a list of angeltypes
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/AngelType'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+
+ /angeltypes/{id}/shifts:
+ parameters:
+ - name: id
+ in: path
+ required: true
+ description: The angeltype identifier
+ example: 42
+ schema:
+ type: integer
+ get:
+ tags:
+ - angeltype
+ - shift
+ summary: Get all shifts of the requested angeltype
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Shift'
+
+ /news:
+ get:
+ tags:
+ - news
+ summary: Get a list of all news
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/News'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+
+ /locations:
+ get:
+ tags:
+ - location
+ summary: Get a list of locations
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Location'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+
+ /locations/{id}/shifts:
+ parameters:
+ - name: id
+ in: path
+ required: true
+ description: The locations identifier
+ example: 42
+ schema:
+ type: integer
+ get:
+ tags:
+ - location
+ - shift
+ summary: Get all shifts in the requested location
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Shift'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+ '404':
+ $ref: '#/components/responses/NotFoundError'
+
+ /users/{id}:
+ parameters:
+ - name: id
+ in: path
+ required: true
+ description: The user identifier or `self`
+ example: 42
+ schema:
+ oneOf:
+ - type: string
+ - type: integer
+ get:
+ tags:
+ - user
+ summary: Get the requesting users information
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ anyOf:
+ - $ref: '#/components/schemas/UserDetail'
+ - $ref: '#/components/schemas/User'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+ '404':
+ $ref: '#/components/responses/NotFoundError'
+
+ /users/{id}/angeltypes:
+ parameters:
+ - name: id
+ in: path
+ required: true
+ description: The user identifier or `self`
+ example: 42
+ schema:
+ oneOf:
+ - type: string
+ - type: integer
+ get:
+ tags:
+ - angeltype
+ - user
+ summary: Get the users angel types
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/UserAngelType'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+ '404':
+ $ref: '#/components/responses/NotFoundError'
+
+ /users/{id}/shifts:
+ parameters:
+ - name: id
+ in: path
+ required: true
+ description: The user identifier or `self`
+ example: 42
+ schema:
+ oneOf:
+ - type: string
+ - type: integer
+ get:
+ tags:
+ - shift
+ - user
+ summary: Get all shifts of the requested user
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/Shift'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+ '404':
+ $ref: '#/components/responses/NotFoundError'
+
+ /info:
+ get:
+ tags:
+ - event
+ summary: Get event information
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ data:
+ $ref: '#/components/schemas/EventInfo'
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+ '404':
+ $ref: '#/components/responses/NotFoundError'
+
+ /openapi:
+ get:
+ tags:
+ - api
+ summary: Get the OpenAPI definition
+ responses:
+ '200':
+ description: Ok
+ content:
+ application/json: {}
+ '401':
+ $ref: '#/components/responses/UnauthorizedError'
+ '403':
+ $ref: '#/components/responses/ForbiddenError'
+ '404':
+ $ref: '#/components/responses/NotFoundError'
diff --git a/resources/api/readme.md b/resources/api/readme.md
new file mode 100644
index 000000000..9c41daf1a
--- /dev/null
+++ b/resources/api/readme.md
@@ -0,0 +1,7 @@
+# Engelsystem API documentation
+Here you can find the OpenAPI files that describe the Engelsystem API.
+Please be aware that the API is still in Beta and might change every second (but we try to keep it consistent during events ;))
+
+## Links
+* [Engelsystem OpenApi](openapi.yml)
+* [OpenAPI format specification](https://swagger.io/specification/)
diff --git a/resources/assets/js/countdown.js b/resources/assets/js/countdown.js
index 48bfbbbaf..31fb14443 100644
--- a/resources/assets/js/countdown.js
+++ b/resources/assets/js/countdown.js
@@ -6,7 +6,7 @@ import { ready } from './ready';
ready(() => {
const lang = document.documentElement.getAttribute('lang');
- const rtf = new Intl.RelativeTimeFormat(lang, { numeric: 'auto' });
+ const rtf = new Intl.RelativeTimeFormat(lang ?? [], { numeric: 'auto' });
const timeFrames = [
[60 * 60 * 24 * 365, 'year'],
diff --git a/resources/assets/js/design.js b/resources/assets/js/design.js
new file mode 100644
index 000000000..f6dc09a3c
--- /dev/null
+++ b/resources/assets/js/design.js
@@ -0,0 +1,13 @@
+import { ready } from './ready';
+
+ready(() => {
+ [...document.getElementsByClassName('prevent-default')].forEach((element) => {
+ let preventDefault = (e) => {
+ e.preventDefault();
+ return false;
+ };
+
+ element.addEventListener('submit', preventDefault);
+ element.addEventListener('click', preventDefault);
+ });
+});
diff --git a/resources/assets/js/forms.js b/resources/assets/js/forms.js
index e6e191963..ee12c5ee1 100644
--- a/resources/assets/js/forms.js
+++ b/resources/assets/js/forms.js
@@ -4,28 +4,24 @@ import { ready } from './ready';
/**
* Sets all checkboxes to the wanted state
- *
- * @param {string} id Id of the element containing all the checkboxes
- * @param {boolean} checked True if the checkboxes should be checked
*/
-global.checkAll = (id, checked) => {
- document.querySelectorAll(`#${id} input[type="checkbox"]`).forEach((element) => {
- element.checked = checked;
- });
-};
-
-/**
- * Sets the checkboxes according to the given type
- *
- * @param {string} id The Id of the element containing all the checkboxes
- * @param {int[]} shiftsList A list of numbers
- */
-global.checkOwnTypes = (id, shiftsList) => {
- document.querySelectorAll(`#${id} input[type="checkbox"]`).forEach((element) => {
- const value = Number(element.value);
- element.checked = shiftsList.includes(value);
+ready(() => {
+ document.querySelectorAll('button.checkbox-selection').forEach((buttonElement) => {
+ buttonElement.addEventListener('click', () => {
+ document.querySelectorAll(`#${buttonElement.dataset.id} input[type="checkbox"]`).forEach((checkboxElement) => {
+ /**
+ * @type {boolean|int[]}
+ */
+ const value = JSON.parse(buttonElement.dataset.value);
+ if (typeof value === 'boolean') {
+ checkboxElement.checked = value;
+ } else {
+ checkboxElement.checked = value.includes(Number(checkboxElement.value));
+ }
+ });
+ });
});
-};
+});
ready(() => {
/**
@@ -156,7 +152,7 @@ const DISABLE_ELEMENTS = [
ready(() => {
// get all input-radio's and add for each an onChange event listener
document.querySelectorAll('input[type="radio"]').forEach((radioElement) => {
- // build selector and get all corrsponding elements for this input-radio
+ // build selector and get all corresponding elements for this input-radio
const selector = DISABLE_ELEMENTS.map(
(tagName) => `${tagName}[data-radio-name="${radioElement.name}"][data-radio-value]`
).join(',');
@@ -180,21 +176,29 @@ ready(() => {
});
ready(() => {
- document.querySelectorAll('.spinner-down').forEach((element) => {
- const inputElement = document.getElementById(element.dataset.inputId);
- if (inputElement) {
- element.addEventListener('click', () => {
- inputElement.stepDown();
- });
- }
+ const addClickHandler = (selector, onClick) => {
+ document.querySelectorAll(selector).forEach((element) => {
+ const inputElement = document.getElementById(element.dataset.inputId);
+
+ if (!inputElement || !inputElement.stepUp || !inputElement.stepDown) return;
+
+ if (inputElement.disabled || inputElement.readOnly) {
+ // The input element is disabled or read-only β disable the +/- button as well.
+ // Note that changing the "disabled" or "readonly" attributes during runtime is not yet supported.
+ element.setAttribute('disabled', 'disabled');
+ return;
+ }
+
+ element.addEventListener('click', () => onClick(inputElement));
+ });
+ };
+
+ addClickHandler('.spinner-up', (inputElement) => {
+ inputElement.stepUp();
});
- document.querySelectorAll('.spinner-up').forEach((element) => {
- const inputElement = document.getElementById(element.dataset.inputId);
- if (inputElement) {
- element.addEventListener('click', () => {
- inputElement.stepUp();
- });
- }
+
+ addClickHandler('.spinner-down', (inputElement) => {
+ inputElement.stepDown();
});
});
@@ -227,10 +231,15 @@ ready(() => {
});
});
+/**
+ * Init select dropdown choices
+ */
ready(() => {
document.querySelectorAll('select').forEach((element) => {
element.choices = new Choices(element, {
- allowHTML: false,
+ allowHTML: true,
+ shouldSort: false,
+ shouldSortItems: false,
classNames: {
containerInner: 'choices__inner form-control',
},
@@ -261,6 +270,80 @@ ready(() => {
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((element) => new bootstrap.Tooltip(element));
});
+/**
+ * Init Bootstrap Modals
+ */
+ready(() => {
+ document.querySelectorAll('.modal').forEach((element) => new bootstrap.Modal(element));
+});
+
+/**
+ * Show confirmation modal before submitting form
+ *
+ * Uses the buttons data attributes to show in the modal:
+ * - data-confirm_title: Optional title of the modal
+ * - data-confirm_submit: Body of the modal
+ *
+ * The class, title and content of the requesting button gets copied for confirmation
+ *
+ */
+ready(() => {
+ document.querySelectorAll('[data-confirm_submit_title], [data-confirm_submit_text]').forEach((element) => {
+ let modalOpen = false;
+ let oldType = element.type;
+ if (element.type !== 'submit') {
+ return;
+ }
+
+ element.type = 'button';
+ element.addEventListener('click', (event) => {
+ if (modalOpen) {
+ return;
+ }
+ event.preventDefault();
+
+ document.getElementById('confirmation-modal')?.remove();
+ document.body.insertAdjacentHTML(
+ 'beforeend',
+ `
+
+
+
+
+
+
${element.dataset.confirm_submit_text ?? ''}
+
+
+
+
+
+ `
+ );
+
+ let modal = document.getElementById('confirmation-modal');
+ modal.addEventListener('hide.bs.modal', () => {
+ modalOpen = false;
+ });
+ modal.querySelector('[data-submit]').addEventListener('click', (event) => {
+ element.type = oldType;
+ element.click();
+ });
+
+ modalOpen = true;
+ let bootstrapModal = new bootstrap.Modal(modal);
+ bootstrapModal.show();
+ });
+ });
+});
+
/**
* Show oauth buttons on welcome title click
*/
@@ -284,27 +367,48 @@ ready(() => {
* Uses DOMContentLoaded to prevent flickering
*/
ready(() => {
- const filter = document.getElementById('collapseShiftsFilterSelect');
- if (!filter || localStorage.getItem('collapseShiftsFilterSelect') !== 'hidden.bs.collapse') {
- return;
- }
+ const collapseElement = document.getElementById('collapseShiftsFilterSelect');
+ if (collapseElement) {
+ if (localStorage.getItem('collapseShiftsFilterSelect') === 'hidden.bs.collapse') {
+ collapseElement.classList.remove('show');
+ }
- filter.classList.remove('show');
+ /**
+ * @param {Event} event
+ */
+ const onChange = (event) => {
+ localStorage.setItem('collapseShiftsFilterSelect', event.type);
+ };
+
+ collapseElement.addEventListener('hidden.bs.collapse', onChange);
+ collapseElement.addEventListener('shown.bs.collapse', onChange);
+ }
});
+/**
+ * Show/hide checkboxes for User Driver-Licenses
+ */
ready(() => {
- if (typeof localStorage === 'undefined') {
- return;
- }
+ const checkboxElement = document.getElementById('wants_to_drive');
+ const drivingLicenseElement = document.getElementById('driving_license');
- /**
- * @param {Event} event
- */
- const onChange = (event) => {
- localStorage.setItem('collapseShiftsFilterSelect', event.type);
- };
+ if (checkboxElement && drivingLicenseElement) {
+ drivingLicenseElement.hidden = !checkboxElement.checked;
- document.getElementById('collapseShiftsFilterSelect')?.addEventListener('hidden.bs.collapse', onChange);
+ checkboxElement.addEventListener('click', () => {
+ drivingLicenseElement.hidden = !checkboxElement.checked;
+ });
+ }
+});
- document.getElementById('collapseShiftsFilterSelect')?.addEventListener('shown.bs.collapse', onChange);
+/**
+ * Prevent scrolling on # links in menu
+ */
+ready(() => {
+ const elements = document.querySelectorAll('.navbar a[href="#"]');
+ elements.forEach((a) => {
+ a.addEventListener('click', (e) => {
+ e.preventDefault();
+ });
+ });
});
diff --git a/resources/assets/js/ready.js b/resources/assets/js/ready.js
index d664b52cc..eabd8ffb2 100644
--- a/resources/assets/js/ready.js
+++ b/resources/assets/js/ready.js
@@ -2,9 +2,9 @@
* @param {Function} callback
*/
export const ready = (callback) => {
- if (document.readyState !== 'loading') {
- callback();
- } else {
+ if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', callback);
+ } else {
+ callback();
}
};
diff --git a/resources/assets/js/vendor.js b/resources/assets/js/vendor.js
index 38ae6b4e0..ef30ac178 100644
--- a/resources/assets/js/vendor.js
+++ b/resources/assets/js/vendor.js
@@ -3,3 +3,4 @@ window.bootstrap = require('bootstrap');
import './forms';
import './countdown';
import './dashboard';
+import './design';
diff --git a/resources/assets/themes/base.scss b/resources/assets/themes/base.scss
index 6893e4257..5abf23ede 100644
--- a/resources/assets/themes/base.scss
+++ b/resources/assets/themes/base.scss
@@ -47,6 +47,7 @@ $form-label-font-weight: $font-weight-bold;
@import '~bootstrap/scss/close';
@import '~bootstrap/scss/popover';
@import '~bootstrap/scss/tooltip';
+@import '~bootstrap/scss/modal';
@import '~bootstrap/scss/helpers';
@@ -120,6 +121,27 @@ table a > .icon-icon_angel {
margin-bottom: 0;
}
+/* making top border visible in tables */
+table .border-top {
+ border-top-width: calc(var(--bs-border-width) * 2) !important;
+}
+
+/* to only highlight the top row in info color */
+table .border-top-info {
+ border-top-width: calc(var(--bs-border-width) * 2) !important;
+ border-top-color: rgba(var(--bs-info-rgb)) !important;
+}
+
+// equal top and bottom border if highlighted
+table .border-bottom {
+ border-bottom-width: calc(var(--bs-border-width) * 2) !important;
+}
+
+/* to be able to highlight table rows */
+.table-responsive {
+ padding: 0 2px;
+}
+
.stats {
font-size: 20px;
height: 150px;
@@ -189,7 +211,7 @@ table a > .icon-icon_angel {
flex-direction: row;
flex-wrap: nowrap;
align-items: stretch;
- width: 100%;
+ width: max-content;
.lane {
background: $table-striped-bg;
@@ -321,6 +343,10 @@ h6,
}
// Cards
+.card > .card-body:first-child {
+ border-top-left-radius: var(--bs-card-border-radius);
+ border-top-right-radius: var(--bs-card-border-radius);
+}
.card-body > *:last-child {
margin-bottom: 0;
}
@@ -382,6 +408,10 @@ code {
}
}
+.btn-group .btn {
+ border-radius: inherit;
+}
+
/* Hide the arrow up/down buttons rendered by the browser in the input field */
/* Chrome, Safari, Edge, Opera */
input[type='number']::-webkit-outer-spin-button,
diff --git a/resources/assets/themes/choices.scss b/resources/assets/themes/choices.scss
index cd1bf2110..72f441f14 100644
--- a/resources/assets/themes/choices.scss
+++ b/resources/assets/themes/choices.scss
@@ -20,6 +20,10 @@ $es-choices-highlight-color: $choices-text-color !default;
padding: $input-padding-y 1.75rem $input-padding-y $input-padding-x !important;
}
+.#{$choices-selector} .#{$choices-selector}__list {
+ z-index: $zindex-sticky + 2;
+}
+
.#{$choices-selector}__list--single {
padding: 0;
}
diff --git a/resources/assets/themes/cyborg_styles.scss b/resources/assets/themes/cyborg_styles.scss
index a81b1d27f..ad56fdb9f 100644
--- a/resources/assets/themes/cyborg_styles.scss
+++ b/resources/assets/themes/cyborg_styles.scss
@@ -107,6 +107,10 @@ table,
}
}
+.list-group .form-check-input {
+ border-color: $list-group-form-check-input-border-color;
+}
+
// Navs =======================================================================
.nav-tabs,
diff --git a/resources/assets/themes/cyborg_variables.scss b/resources/assets/themes/cyborg_variables.scss
index f4d6c294e..0a18e1760 100644
--- a/resources/assets/themes/cyborg_variables.scss
+++ b/resources/assets/themes/cyborg_variables.scss
@@ -150,6 +150,9 @@ $input-border-focus: #66afe9 !default;
//** Placeholder text color
$input-color-placeholder: $gray-light !default;
+$form-check-input-border: 1px solid $input-border-color !default;
+$list-group-form-check-input-border-color: $input-border-color !default;
+
$legend-color: $text-color !default;
$legend-border-color: $gray-dark !default;
@@ -513,10 +516,11 @@ $progress-bar-info-bg: $info !default;
//
//##
+$list-group-color: $input-color !default;
//** Background color on `.list-group-item`
$list-group-bg: $gray-darker !default;
//** `.list-group-item` border color
-$list-group-border: $gray-dark !default;
+$list-group-border-color: $input-border-color !default;
//** List group border radius
$list-group-border-radius: $border-radius-base !default;
@@ -561,9 +565,7 @@ $kbd-color: #fff !default;
$kbd-bg: #333 !default;
$pre-bg: #f5f5f5 !default;
-$pre-color: $gray-dark !default;
-$pre-border-color: #ccc !default;
-$pre-scrollable-max-height: 340px !default;
+$pre-color: $body-color !default;
//== Type
//
@@ -589,4 +591,13 @@ $dl-horizontal-offset: $component-offset-horizontal !default;
//** Horizontal line color.
$hr-border: $gray-dark !default;
+//== Modal
+//
+//##
+$modal-header-border-color: $hr-border !default;
+$modal-footer-border-color: $hr-border !default;
+
+//== Base
+//
+//##
@import 'base.scss';
diff --git a/resources/assets/themes/dark.scss b/resources/assets/themes/dark.scss
index cf2d624ac..de9ddfdd6 100644
--- a/resources/assets/themes/dark.scss
+++ b/resources/assets/themes/dark.scss
@@ -4,6 +4,7 @@ $input-disabled-bg: #111;
$alert-bg-scale: 70%;
$secondary: #222;
$table-striped-bg: rgba(#fff, 0.05);
+$list-group-form-check-input-border-color: #999;
$es-choices-highlight-color: #000;
@@ -13,3 +14,7 @@ $invert-color-value: 1 !default;
input[type='time']::-webkit-calendar-picker-indicator {
filter: invert($invert-color-value);
}
+
+.modal .bg-dark .modal-header .btn-close {
+ background-color: $list-group-form-check-input-border-color;
+}
diff --git a/resources/assets/themes/theme11.scss b/resources/assets/themes/theme11.scss
index c22d23a38..05bda48b4 100644
--- a/resources/assets/themes/theme11.scss
+++ b/resources/assets/themes/theme11.scss
@@ -81,6 +81,12 @@ $headings-small-color: $gray-lighter;
color: lighten($brand-danger, 10%);
}
+// Alerts =================================================================
+
+.alert a {
+ color: #fff;
+}
+
// Forms ======================================================================
.legend {
diff --git a/resources/assets/themes/theme16.scss b/resources/assets/themes/theme16.scss
new file mode 100644
index 000000000..22cae7952
--- /dev/null
+++ b/resources/assets/themes/theme16.scss
@@ -0,0 +1,204 @@
+// cccamp23
+
+// Variables
+// --------------------------------------------------
+
+@import 'dark';
+
+//== changed Colors
+$gray-dark: #231f20;
+$gray-darker: darken($gray-dark, 30%);
+$gray: lighten($gray-dark, 30%);
+$gray-light: lighten($gray, 30%);
+$gray-lighter: lighten($gray-light, 30%);
+$dark: $gray-dark;
+
+$primary: #fb48c4;
+$secondary: #231f20;
+$success: #3fff21;
+$info: #3dbddf;
+$warning: #f6b345;
+$danger: #991a24;
+
+$text-muted: $gray-light;
+
+$btn-link-disabled-color: $gray-light;
+
+//== Typography
+
+@font-face {
+ font-family: 'Questrial';
+ src: url('theme16/Questrial-Regular.woff2') format('woff2'), url('theme16/Questrial-Regular.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Beon';
+ src: url('theme16/Beon-Regular.woff2') format('woff2'), url('theme16/Beon-Regular.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+$font-family-sans-serif: 'Questrial', Helvetica Neue, Helvetica, Arial, sans-serif;
+$font-family-serif: 'Beon', Georgia, 'Times New Roman', Times, serif;
+$headings-font-family: $font-family-serif;
+
+//== changed Forms
+
+$input-bg: $gray-darker;
+$input-bg-disabled: lighten($gray-lighter, 15%);
+$input-border-color: lighten($gray-dark, 15%);
+$input-group-addon-bg: $input-bg;
+
+$form-check-input-border: 1px solid $gray;
+
+//== changed Pagination
+
+$pagination-hover-color: $gray-lighter;
+$pagination-active-color: $gray-lighter;
+
+//== changed Form states and alerts
+
+$state-success-text: #fff;
+$state-success-bg: $success;
+$state-success-border: darken($state-success-bg, 5%);
+
+$state-info-text: #fff;
+$state-info-bg: $info;
+$state-info-border: darken($state-info-bg, 7%);
+
+$state-warning-text: #fff;
+$state-warning-bg: $warning;
+$state-warning-border: darken($state-warning-bg, 3%);
+
+$state-danger-text: #fff;
+$state-danger-bg: $danger;
+$state-danger-border: darken($state-danger-bg, 3%);
+
+$headings-small-color: $gray-light;
+
+code {
+ background-color: $state-info-bg;
+ color: $state-info-text;
+}
+
+$alert-bg-scale: 0%;
+$alert-border-scale: 0%;
+$alert-color-scale: 0%;
+
+// Navs =======================================================================
+
+$nav-tabs-link-active-border-color: $gray-dark;
+
+$nav-tabs-link-active-color: $gray-darker;
+$nav-pills-link-active-color: $gray-darker;
+
+//== Pagination
+//
+//##
+
+$pagination-color: $gray-lighter;
+$pagination-border-color: $gray-dark;
+
+$pagination-hover-color: #000;
+$pagination-hover-border-color: $gray-dark;
+
+$pagination-active-color: #000;
+$pagination-active-border-color: $gray-dark;
+
+$pagination-disabled-color: $gray-light;
+$pagination-disabled-border-color: $gray-dark;
+
+// dark
+@import 'cyborg_variables';
+@import 'cyborg_styles';
+
+// Specials ===================================================================
+
+.bg-success a,
+.bg-primary a,
+.bg-warning a,
+.bg-info a,
+.bg-light a {
+ color: $gray-darker !important;
+}
+
+.bg-body a,
+.bg-danger a,
+.bg-secondary a,
+.bg-dark a {
+ color: $state-danger-text !important;
+}
+
+.bg-primary,
+.bg-success,
+.bg-warning,
+.bg-info,
+.bg-light {
+ color: $gray-darker;
+}
+
+.bg-body,
+.bg-danger,
+.bg-secondary,
+.bg-dark {
+ color: $state-danger-text;
+}
+
+.navbar {
+ background: rgba(0, 0, 0, 0.7);
+ backdrop-filter: blur(6px);
+}
+
+.navbar-brand {
+ color: $primary;
+ font-family: $headings-font-family;
+}
+
+.nav-tabs,
+.nav-pills,
+.pager {
+ a {
+ color: $gray-lighter;
+ }
+}
+
+.alert a {
+ color: $gray-darker;
+}
+
+.alert.alert-danger,
+.alert.alert-danger a {
+ color: $gray-lighter;
+}
+
+h1,
+h3,
+h5,
+.h1,
+.h3,
+.h5 {
+ color: $primary;
+
+ &.bg-warning,
+ &.bg-info {
+ color: $primary;
+ }
+}
+
+h2,
+h4,
+h6,
+.h2,
+.h4,
+.h6 {
+ color: $success;
+
+ &.bg-warning,
+ &.bg-info {
+ color: $success;
+ }
+}
diff --git a/resources/assets/themes/theme16/Beon-Regular.woff b/resources/assets/themes/theme16/Beon-Regular.woff
new file mode 100644
index 000000000..cf81ae876
Binary files /dev/null and b/resources/assets/themes/theme16/Beon-Regular.woff differ
diff --git a/resources/assets/themes/theme16/Beon-Regular.woff2 b/resources/assets/themes/theme16/Beon-Regular.woff2
new file mode 100644
index 000000000..f3439a7e2
Binary files /dev/null and b/resources/assets/themes/theme16/Beon-Regular.woff2 differ
diff --git a/resources/assets/themes/theme16/License-OFL.txt b/resources/assets/themes/theme16/License-OFL.txt
new file mode 100644
index 000000000..79d0f2fe1
--- /dev/null
+++ b/resources/assets/themes/theme16/License-OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2011 The Questrial Project Authors (https://github.com/googlefonts/questrial)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/resources/assets/themes/theme16/Questrial-Regular.woff b/resources/assets/themes/theme16/Questrial-Regular.woff
new file mode 100644
index 000000000..687d232d6
Binary files /dev/null and b/resources/assets/themes/theme16/Questrial-Regular.woff differ
diff --git a/resources/assets/themes/theme16/Questrial-Regular.woff2 b/resources/assets/themes/theme16/Questrial-Regular.woff2
new file mode 100644
index 000000000..8e580dec6
Binary files /dev/null and b/resources/assets/themes/theme16/Questrial-Regular.woff2 differ
diff --git a/resources/assets/themes/theme17.scss b/resources/assets/themes/theme17.scss
new file mode 100644
index 000000000..8e9b1b236
--- /dev/null
+++ b/resources/assets/themes/theme17.scss
@@ -0,0 +1,200 @@
+// cccamp23
+
+// Variables
+// --------------------------------------------------
+
+@import 'dark';
+
+//== changed Colors
+$gray-dark: #231f20;
+$gray-darker: darken($gray-dark, 30%);
+$gray: lighten($gray-dark, 30%);
+$gray-light: lighten($gray, 30%);
+$gray-lighter: lighten($gray-light, 30%);
+$dark: $gray-dark;
+
+$primary: #de37ff;
+$secondary: #28ffff;
+$success: #79ff5e;
+$info: #3dbddf;
+$warning: #f6b345;
+$danger: #de4040;
+
+$text-muted: $gray-light;
+
+$btn-link-disabled-color: $gray-light;
+
+$dropdown-bg: #212529;
+$dropdown-link-hover-color: #000000;
+
+//== changed Forms
+
+$input-bg: $gray-darker;
+$input-bg-disabled: lighten($gray-lighter, 15%);
+$input-border-color: $secondary;
+$input-group-addon-bg: $input-bg;
+
+$form-check-input-border: 1px solid $gray;
+
+//== changed Pagination
+
+$pagination-hover-color: $gray-lighter;
+$pagination-active-color: $gray-lighter;
+
+//== changed Form states and alerts
+
+$state-success-text: #fff;
+$state-success-bg: $success;
+$state-success-border: darken($state-success-bg, 5%);
+
+$state-info-text: #fff;
+$state-info-bg: $info;
+$state-info-border: darken($state-info-bg, 7%);
+
+$state-warning-text: #fff;
+$state-warning-bg: $warning;
+$state-warning-border: darken($state-warning-bg, 3%);
+
+$state-danger-text: #fff;
+$state-danger-bg: $danger;
+$state-danger-border: darken($state-danger-bg, 3%);
+
+$headings-small-color: $gray-light;
+
+code {
+ background-color: $state-info-bg;
+ color: $state-info-text;
+}
+
+$alert-bg-scale: 0%;
+$alert-border-scale: 0%;
+$alert-color-scale: 0%;
+
+// Navs =======================================================================
+
+$nav-tabs-link-active-border-color: $gray-dark;
+
+$nav-tabs-link-active-color: $gray-darker;
+$nav-pills-link-active-color: $gray-darker;
+
+//== Pagination
+//
+//##
+
+$pagination-color: $gray-lighter;
+$pagination-border-color: $gray-dark;
+
+$pagination-hover-color: #000;
+$pagination-hover-border-color: $gray-dark;
+
+$pagination-active-color: #000;
+$pagination-active-border-color: $gray-dark;
+
+$pagination-disabled-color: $gray-light;
+$pagination-disabled-border-color: $gray-dark;
+
+// dark
+@import 'cyborg_variables';
+@import 'cyborg_styles';
+
+//== Typography
+
+@font-face {
+ font-family: 'VCR OCD Faux';
+ src: url('theme17/VCROCDFaux.ttf') format('truetype'), url('theme17/VCROCDFaux.woff') format('woff'),
+ url('theme17/VCROCDFaux.woff2') format('woff2');
+ font-weight: 400;
+}
+
+@font-face {
+ font-family: Gabriella;
+ src: url('theme17/GabriellaHeavy.otf') format('opentype');
+ font-weight: 400;
+}
+
+$headings-font-family: Gabriella, $font-family-sans-serif;
+$font-family-monospace: 'VCR OCD Faux', SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
+ monospace;
+
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3,
+h4,
+.h4,
+h5,
+.h5 {
+ color: $white;
+}
+
+h1,
+.h1 {
+ font-family: $headings-font-family;
+}
+
+.btn-secondary {
+ background: transparent !important;
+ border-color: $secondary !important;
+ color: $secondary !important;
+}
+
+// Specials ===================================================================
+
+.bg-success a,
+.bg-primary a,
+.bg-warning a,
+.bg-info a,
+.bg-light a {
+ color: $gray-darker !important;
+}
+
+.bg-body a,
+.bg-danger a,
+.bg-secondary a,
+.bg-dark a {
+ color: $state-danger-text !important;
+}
+
+.bg-primary,
+.bg-success,
+.bg-warning,
+.bg-info,
+.bg-light {
+ color: $gray-darker;
+}
+
+.bg-body,
+.bg-danger,
+.bg-secondary,
+.bg-dark {
+ color: $state-danger-text;
+}
+
+.navbar {
+ background: rgba(0, 0, 0, 0.7);
+ backdrop-filter: blur(6px);
+}
+
+.navbar-brand {
+ color: $primary;
+ font-family: $font-family-monospace;
+}
+
+.nav-tabs,
+.nav-pills,
+.pager {
+ a {
+ color: $gray-lighter;
+ }
+}
+
+.alert a {
+ color: $gray-darker;
+}
+
+.alert.alert-danger,
+.alert.alert-danger a {
+ color: $gray-lighter;
+}
diff --git a/resources/assets/themes/theme17/GabriellaHeavy.otf b/resources/assets/themes/theme17/GabriellaHeavy.otf
new file mode 100644
index 000000000..f28c1b317
Binary files /dev/null and b/resources/assets/themes/theme17/GabriellaHeavy.otf differ
diff --git a/resources/assets/themes/theme17/VCROCDFaux.ttf b/resources/assets/themes/theme17/VCROCDFaux.ttf
new file mode 100644
index 000000000..086259295
Binary files /dev/null and b/resources/assets/themes/theme17/VCROCDFaux.ttf differ
diff --git a/resources/assets/themes/theme17/VCROCDFaux.woff b/resources/assets/themes/theme17/VCROCDFaux.woff
new file mode 100644
index 000000000..e9f148bbd
Binary files /dev/null and b/resources/assets/themes/theme17/VCROCDFaux.woff differ
diff --git a/resources/assets/themes/theme17/VCROCDFaux.woff2 b/resources/assets/themes/theme17/VCROCDFaux.woff2
new file mode 100644
index 000000000..5c823bdf2
Binary files /dev/null and b/resources/assets/themes/theme17/VCROCDFaux.woff2 differ
diff --git a/resources/assets/themes/theme3.scss b/resources/assets/themes/theme3.scss
index 32ba04ce8..59ff00a66 100644
--- a/resources/assets/themes/theme3.scss
+++ b/resources/assets/themes/theme3.scss
@@ -45,6 +45,13 @@ $navbar-default-brand-color: #fff;
$navbar-default-brand-hover-color: $brand-primary;
$navbar-default-brand-hover-bg: #000;
+// Alerts =================================================================
+
+.alert a {
+ color: #000;
+ text-decoration: underline;
+}
+
.navbar {
.bg-info {
background-color: darken($brand-info, 30%);
diff --git a/resources/assets/themes/theme4.scss b/resources/assets/themes/theme4.scss
index 44802aec4..3ea7f587c 100644
--- a/resources/assets/themes/theme4.scss
+++ b/resources/assets/themes/theme4.scss
@@ -126,3 +126,14 @@ h6,
color: #000;
}
}
+
+// Alerts =================================================================
+
+.alert a {
+ color: #fff;
+}
+
+.alert.alert-success a,
+.alert.alert-warning a {
+ color: #000;
+}
diff --git a/resources/lang/de_DE/additional.po b/resources/lang/de_DE/additional.po
index 0e8cd7cef..eda8a898e 100644
--- a/resources/lang/de_DE/additional.po
+++ b/resources/lang/de_DE/additional.po
@@ -17,19 +17,42 @@ msgstr ""
msgid "validation.password.required"
msgstr "Bitte gib ein Passwort an."
+msgid "validation.password.length"
+msgstr "Das angegebene Passwort ist zu kurz."
+
msgid "validation.login.required"
msgstr "Bitte gib einen Loginnamen an."
+msgid "validation.pronoun.required"
+msgstr "Bitte gebe dein Pronomen an."
+
+msgid "validation.firstname.required"
+msgstr "Bitte gebe deinen Vornamen an."
+
+msgid "validation.lastname.required"
+msgstr "Bitte gebe deinen Nachnamen an."
+
+msgid "validation.mobile.required"
+msgstr "Bitte gebe deine Handynummer an."
+
+msgid "validation.dect.required"
+msgstr "Bitte gebe deine DECT-Nummer an."
+
+msgid "validation.username.required"
+msgstr "Bitte gebe deinen Nick an."
+
+msgid "validation.username.username"
+msgstr ""
+"Bitte gebe einen gΓΌltigen Nick ein: "
+"Verwende bis zu 24 Buchstaben, Zahlen oder verbindende Schriftzeichen (.-_) fΓΌr deinen Nick."
+
msgid "validation.email.required"
msgstr "Bitte gib eine E-Mail-Adresse an."
msgid "validation.email.email"
msgstr "Die E-Mail-Adresse ist nicht gΓΌltig."
-msgid "validation.password.min"
-msgstr "Dein neues Passwort ist zu kurz."
-
-msgid "validation.new_password.min"
+msgid "validation.new_password.length"
msgstr "Dein neues Passwort ist zu kurz."
msgid "validation.password.confirmed"
@@ -38,6 +61,21 @@ msgstr "Deine PasswΓΆrter stimmen nicht ΓΌberein."
msgid "validation.password_confirmation.required"
msgstr "Du musst dein Passwort bestΓ€tigen."
+msgid "validation.tshirt_size.required"
+msgstr "Bitte wΓ€hle deine T-Shirt-GrΓΆΓe aus."
+
+msgid "validation.tshirt_size.shirtSize"
+msgstr "Bitte wΓ€hle eine gΓΌltige T-Shirt-GrΓΆΓe aus."
+
+msgid "validation.planned_arrival_date.required"
+msgstr "Bitte gebe dein geplantes Ankunftsdatum an."
+
+msgid "validation.planned_arrival_date.min"
+msgstr "Das geplante Ankunftsdatum darf nicht vor Aufbaubeginn liegen."
+
+msgid "validation.planned_arrival_date.between"
+msgstr "Das geplante Ankunftsdatum muss zwischen Aufbaubeginn und Abbauende liegen."
+
msgid "schedule.edit.success"
msgstr "Das Programm wurde erfolgreich konfiguriert."
@@ -53,6 +91,9 @@ msgstr "Der Schichttyp konnte nicht gefunden werden."
msgid "schedule.import.success"
msgstr "Das Programm wurde erfolgreich importiert."
+msgid "schedule.delete.success"
+msgstr "Das Programm wurde erfolgreich gelΓΆscht."
+
msgid "shifts.filter.toggle"
msgstr "Filter verstecken/anzeigen"
@@ -80,6 +121,9 @@ msgstr "Kommentar gespeichert."
msgid "news.comment-delete.success"
msgstr "Kommentar erfolgreich gelΓΆscht."
+msgid "news.edit.duplicate"
+msgstr "Diese News wurde bereits erstellt."
+
msgid "news.edit.success"
msgstr "News erfolgreich aktualisiert."
@@ -128,6 +172,9 @@ msgstr "Der OAuth-Provider ist aufgrund eines unerwarteten Fehlers nicht in der
msgid "oauth.temporarily_unavailable"
msgstr "Der OAuth-Provider ist aufgrund Γberlastung oder Wartung temporΓ€r nicht in der Lage, die Anfrage zu erfΓΌllen"
+msgid "profile.my-shifts"
+msgstr "Meine Schichten"
+
msgid "settings.profile"
msgstr "Profil"
@@ -139,9 +186,15 @@ msgid "settings.profile.planned_departure_date.invalid"
msgstr "Bitte gib Dein geplantes Abreisedatum an, damit wir ein GefΓΌhl fΓΌr die Abbauplanung bekommen. "
"Es sollte nach dem Aufbaubeginn und vor dem Abbauende liegen."
-msgid "settings.profile.success"
+msgid "settings.success"
msgstr "Einstellungen gespeichert."
+msgid "settings.sessions.delete_success"
+msgstr "Sitzung erfolgreich gelΓΆscht."
+
+msgid "settings.api.key_reset_success"
+msgstr "API Key erfolgreich zurΓΌckgesetzt."
+
msgid "faq.delete.success"
msgstr "FAQ Eintrag erfolgreich gelΓΆscht."
@@ -166,6 +219,9 @@ msgstr "Es gibt eine neue News: %1$s"
msgid "notification.news.new.text"
msgstr "Du kannst sie dir unter %3$s anschauen."
+msgid "notification.news.updated"
+msgstr "Aktualisierte News: %s"
+
msgid "notification.messages.new"
msgstr "Neue private Nachricht von %s"
@@ -201,6 +257,12 @@ msgstr ""
"Da die gelΓΆschte Schicht bereits vergangen ist, "
"haben wir einen entsprechenden Arbeitseinsatz hinzugefΓΌgt."
+msgid "notification.shift.updated"
+msgstr "Deine Schicht wurde aktualisiert"
+
+msgid "notification.shift.no_next_found"
+msgstr "Es wurde keine verfΓΌgbare Schicht gefunden."
+
msgid "user.edit.success"
msgstr "Benutzer erfolgreich bearbeitet."
@@ -216,11 +278,26 @@ msgstr "Arbeitseinsatz erfolgreich bearbeitet."
msgid "worklog.delete.success"
msgstr "Arbeitseinsatz erfolgreich gelΓΆscht."
-msgid "room.edit.success"
-msgstr "Raum erfolgreich bearbeitet."
+msgid "location.edit.success"
+msgstr "Ort erfolgreich bearbeitet."
+
+msgid "location.delete.success"
+msgstr "Ort erfolgreich gelΓΆscht."
+
+msgid "shifttype.edit.success"
+msgstr "Schichttyp erfolgreich bearbeitet."
-msgid "room.delete.success"
-msgstr "Raum erfolgreich gelΓΆscht."
+msgid "shifttype.delete.success"
+msgstr "Schichttyp erfolgreich gelΓΆscht."
msgid "validation.name.exists"
msgstr "Der Name wird bereits verwendet."
+
+msgid "registration.disabled"
+msgstr "Die Registrierung ist deaktiviert."
+
+msgid "registration.successful"
+msgstr "Registrierung erfolgreich. Du kannst dich jetzt anmelden!"
+
+msgid "shifts.history.delete.success"
+msgstr "Schichten erfolgreich gelΓΆscht."
diff --git a/resources/lang/de_DE/default.po b/resources/lang/de_DE/default.po
index d5e96a228..26f0c534e 100644
--- a/resources/lang/de_DE/default.po
+++ b/resources/lang/de_DE/default.po
@@ -18,127 +18,86 @@ msgstr ""
"X-Poedit-SearchPath-1: src\n"
"X-Poedit-SearchPath-2: includes\n"
-#: resources/views/emails/mail.twig:1
-#, python-format
-msgid "Hi %s,"
+msgid "email.greeting"
msgstr "Hallo %s,"
-#: resources/views/emails/mail.twig:3
-#, python-format
-msgid "here is a message for you from the %s:"
+msgid "email.introduction"
msgstr "hier ist eine Nachricht aus dem %s fΓΌr Dich:"
-#: resources/views/emails/mail.twig:6
-#, python-format
-msgid ""
-"This email is autogenerated and has not been signed. You got this email "
-"because you are registered in the %s."
+msgid "email.footer"
msgstr ""
"Diese E-Mail wurde automatisch generiert und muss daher nicht unterschrieben "
"werden. Du hast diese E-Mail bekommen, weil Du im %s registriert bist."
-#: resources/views/emails/password-reset.twig:3
-#, python-format
-msgid "Please visit %s to recover your password."
-msgstr "Bitte besuche %s, um Dein Passwort zurΓΌckzusetzen"
+msgid "password.email.message"
+msgstr "Um dein Passwort zurΓΌckzusetzen, besuche %s"
+
+msgid "page.error.title"
+msgstr "Fehler %s"
-#: resources/views/errors/403.twig:3
-msgid "Forbidden"
+msgid "page.403.title"
msgstr "Nicht erlaubt"
-#: resources/views/errors/403.twig:5
-msgid "You are not allowed to access this page"
+msgid "page.403.headline"
msgstr "Du darfst diese Seite nicht aufrufen"
-#: resources/views/errors/404.twig:3 src/Middleware/LegacyMiddleware.php:82
-msgid "Page not found"
+msgid "page.404.title"
msgstr "Seite nicht gefunden"
-#: resources/views/errors/404.twig:10
-msgid "No sleep found"
+msgid "page.404.not_found"
msgstr "No sleep found"
-#: resources/views/errors/405.twig:3 resources/views/errors/405.twig:5
-msgid "405: Method not allowed"
-msgstr ""
+msgid "page.405.title"
+msgstr "405: Anfragetyp nicht erlaubt"
-#: resources/views/errors/419.twig:3
-msgid "Authentication expired"
+msgid "page.419.title"
msgstr "Autorisierung ist abgelaufen"
-#: resources/views/errors/419.twig:6
-msgid "The provided CSRF token is invalid or has expired"
+msgid "page.419.text"
msgstr "Das angegebene CSRF Token ist ungΓΌltig oder abgelaufen"
-#: resources/views/layouts/parts/footer.twig:9
-#: resources/views/layouts/parts/footer.twig:10
-#: resources/views/layouts/parts/footer.twig:15
-#: resources/views/layouts/parts/footer.twig:22
-#: resources/views/layouts/parts/footer.twig:23
-#: resources/views/pages/login.twig:25 includes/pages/admin_arrive.php:98
-#: includes/pages/admin_arrive.php:99 includes/pages/admin_arrive.php:100
-#: includes/view/EventConfig_view.php:36 includes/view/EventConfig_view.php:44
-#: includes/view/EventConfig_view.php:52 includes/view/EventConfig_view.php:60
-#: includes/view/Shifts_view.php:28 includes/view/Shifts_view.php:36
-#: includes/view/Shifts_view.php:148 includes/view/User_view.php:197
-#: includes/view/User_view.php:199
-msgid "Y-m-d"
+msgid "general.date"
msgstr "d.m.Y"
-#: resources/views/layouts/parts/footer.twig:7
-msgid "%1$s, from %2$s to %3$s"
+msgid "footer.eventinfo.name_start_end"
msgstr "%1$s, vom %2$s bis %3$s"
-#: resources/views/layouts/parts/footer.twig:13
-msgid "%1$s, starting %2$s"
+msgid "footer.eventinfo.name_start"
msgstr "%1$s, ab dem %2$s"
-#: resources/views/layouts/parts/footer.twig:21
-msgid "Event from %1$s to %2$s"
-msgstr "Event von %1$s bis %2$s"
+msgid "footer.eventinfo.start_end"
+msgstr "Event vom %1$s bis %2$s"
-#: resources/views/layouts/parts/footer.twig:34
-msgid "Bugs / Features"
+msgid "footer.issues"
msgstr "Bugs / Features"
-#: resources/views/layouts/parts/footer.twig:35
-msgid "Development Platform"
+msgid "footer.github"
msgstr "Entwicklerplattform"
-#: resources/views/layouts/parts/footer.twig:36
-#: resources/views/pages/credits.twig:3 resources/views/pages/credits.twig:7
-msgid "Credits"
+msgid "credits.title"
msgstr "Credits"
-#: resources/views/layouts/parts/navbar.twig:39
-#: resources/views/pages/login.twig:83 resources/views/pages/login.twig:87
-#: includes/pages/guest_login.php:16 includes/pages/guest_login.php:353
-msgid "Register"
+msgid "general.register"
msgstr "Registrieren"
-#: resources/views/layouts/parts/navbar.twig:43
-#: resources/views/pages/login.twig:4 resources/views/pages/login.twig:66
-#: includes/view/AngelTypes_view.php:581
-msgid "login.login"
+msgid "general.login"
msgstr "Login"
msgid "page.403.login"
msgstr "Bitte melde dich an."
-#: resources/views/macros/form.twig:17
msgid "form.submit"
msgstr "Absenden"
-#: resources/views/pages/credits.twig:17
-msgid "Source code"
+msgid "form.send_notification"
+msgstr "Benachrichtigungen versenden"
+
+msgid "credits.source"
msgstr "Quellcode"
-#: resources/views/pages/credits.twig:18
-#, python-format
-msgid "Version: _%s_"
-msgstr ""
+msgid "credits.version"
+msgstr "Version: _%s_"
-#: resources/views/pages/credits.twig:20
msgid "credits.credit"
msgstr ""
"Das ursprΓΌngliche Engelsystem wurde entwickelt von [cookie](https://github."
@@ -146,292 +105,162 @@ msgstr ""
"notrademark.de) (Maintainer) und [MyIgel](https://myigel.name) vΓΆllig "
"ΓΌberarbeitet und verbessert."
-#: resources/views/pages/credits.twig:23
msgid "credits.contributors"
msgstr ""
"Eine vollstΓ€ndige Liste der Mitwirkenden findest Du [auf GitHub](https://"
"github.com/engelsystem/engelsystem/graphs/contributors)."
-#: resources/views/pages/login.twig:10 includes/view/EventConfig_view.php:27
-#, python-format, php-format
-msgid "Welcome to the %s!"
+msgid "login.welcome"
msgstr "Willkommen beim %s!"
-#: resources/views/pages/login.twig:16 includes/view/EventConfig_view.php:34
-msgid "Buildup starts"
+msgid "event.buildup.start"
msgstr "Aufbau startet"
-#: resources/views/pages/login.twig:17 includes/view/EventConfig_view.php:42
-msgid "Event starts"
+msgid "event.starts"
msgstr "Event startet"
-#: resources/views/pages/login.twig:18 includes/view/EventConfig_view.php:50
-msgid "Event ends"
+msgid "event.ends"
msgstr "Event endet"
-#: resources/views/pages/login.twig:19 includes/view/EventConfig_view.php:58
-msgid "Teardown ends"
+msgid "event.teardown.ends"
msgstr "Abbau endet"
-#: resources/views/pages/login.twig:72
-msgid "I forgot my password"
+msgid "login.password.reset"
msgstr "Passwort vergessen"
-#: resources/views/pages/login.twig:85
-msgid "Please sign up, if you want to help us!"
+msgid "login.registration"
msgstr "Bitte registriere Dich, wenn Du helfen mΓΆchtest!"
-msgid "Registration is only available via external login."
+msgid "login.registration.external"
msgstr "Die Registrierung ist nur ΓΌber einen externen Login mΓΆglich."
-#: resources/views/pages/login.twig:90 includes/pages/guest_login.php:61
-msgid "Registration is disabled."
+msgid "login.registration.disabled"
msgstr "Registrierung ist abgeschaltet."
-#: resources/views/pages/login.twig:95
-msgid "What can I do?"
+msgid "login.do"
msgstr "Was kann ich machen?"
-#: resources/views/pages/login.twig:96
-msgid "Please read about the jobs you can do to help us."
-msgstr ""
-"Bitte informiere Dich ΓΌber die TΓ€tigkeiten bei denen Du uns helfen kannst."
+msgid "login.jobs"
+msgstr "Informiere Dich ΓΌber die TΓ€tigkeiten bei denen Du uns helfen kannst."
-#: resources/views/pages/login.twig:105
-msgid "Please note: You have to activate cookies!"
+msgid "login.cookies"
msgstr "Hinweis: Cookies mΓΌssen aktiviert sein!"
-#: resources/views/pages/password/reset-form.twig:10
-#: includes/pages/guest_login.php:312
-msgid "Password"
-msgstr "Passwort"
-
-#: resources/views/pages/password/reset-form.twig:11
-#: includes/pages/guest_login.php:315
-msgid "Confirm password"
+msgid "password.reset.confirm"
msgstr "Passwort wiederholen"
-#: resources/views/pages/password/reset-form.twig:14
-#: includes/controller/shifts_controller.php:194
-#: includes/pages/admin_questions.php:55 includes/pages/admin_rooms.php:177
-#: includes/pages/admin_shifts.php:339 includes/pages/user_messages.php:78
-#: includes/view/AngelTypes_view.php:120 includes/view/EventConfig_view.php:110
-#: includes/view/Questions_view.php:43 includes/view/ShiftEntry_view.php:93
-#: includes/view/ShiftEntry_view.php:118 includes/view/ShiftEntry_view.php:141
-#: includes/view/ShiftEntry_view.php:207 includes/view/ShiftTypes_view.php:64
-#: includes/view/UserDriverLicenses_view.php:54
-#: includes/view/User_view.php:84
-#: includes/view/User_view.php:93 includes/view/User_view.php:98
-#: includes/view/User_view.php:103 includes/view/User_view.php:154
-msgid "Save"
-msgstr "Speichern"
-
-#: resources/views/pages/password/reset-success.twig:7
-msgid "We sent you an email containing your password recovery link."
+msgid "password.recovery.success"
msgstr ""
-"Wir haben dir eine eMail mit einem Link zum Passwort-zurΓΌcksetzen geschickt."
+"Wir haben dir eine E-Mail mit einem Link zum Passwort-zurΓΌcksetzen geschickt."
-#: resources/views/pages/password/reset-success.twig:9
-msgid "Password saved."
-msgstr "Passwort gespeichert."
-
-#: resources/views/pages/password/reset.twig:5
-#: resources/views/pages/password/reset.twig:9
-msgid "Password recovery"
+msgid "password.reset.title"
msgstr "Passwort wiederherstellen"
-#: resources/views/pages/password/reset.twig:21
-msgid ""
-"We will send you an e-mail with a password recovery link. Please use the "
-"email address you used for registration."
+msgid "password.recovery.text"
msgstr ""
-"Wir werden eine eMail mit einem Link schicken, mit dem du das Passwort "
-"zurΓΌcksetzen kannst. Bitte benutze die Mailadresse, die du bei der Anmeldung "
+"Wir werden eine E-Mail mit einem Link schicken, mit dem du das Passwort "
+"zurΓΌcksetzen kannst. Bitte benutze die E-Mail-Adresse, die du bei der Anmeldung "
"verwendet hast."
-#: resources/views/pages/password/reset.twig:22
-#: includes/pages/admin_free.php:116 includes/pages/guest_login.php:280
-#: includes/view/AngelTypes_view.php:119 includes/view/AngelTypes_view.php:482
-#: includes/view/User_view.php:62
-msgid "E-Mail"
-msgstr "E-Mail"
+msgid "password.minimal_length"
+msgstr "MindestlΓ€nge %d Zeichen"
-#: resources/views/pages/password/reset.twig:25
-msgid "Recover"
+msgid "form.recover"
msgstr "Wiederherstellen"
-#: includes/controller/angeltypes_controller.php:13
-#: includes/pages/user_shifts.php:249 includes/sys_menu.php:97
-#: includes/view/AngelTypes_view.php:81 includes/view/AngelTypes_view.php:139
-#: includes/view/User_view.php:779
-msgid "Angeltypes"
-msgstr "Engeltypen"
-
-#: includes/controller/angeltypes_controller.php:89
-#, php-format
msgid "Angeltype %s deleted."
msgstr "Engeltyp %s gelΓΆscht."
-#: includes/controller/angeltypes_controller.php:94
-#: includes/view/AngelTypes_view.php:59
-#, php-format
msgid "Delete angeltype %s"
msgstr "LΓΆsche Engeltyp %s"
-#: includes/controller/angeltypes_controller.php:135
msgid "Please check the name. Maybe it already exists."
msgstr "Bitte ΓΌberprΓΌfe den Namen. Vielleicht ist er bereits vergeben."
-#: includes/controller/angeltypes_controller.php:165
-#: includes/view/AngelTypes_view.php:79
-#, php-format
+msgid "Create angeltype"
+msgstr "Engeltyp erstellen"
+
msgid "Edit %s"
msgstr "%s bearbeiten"
-#: includes/controller/angeltypes_controller.php:203
-#: includes/view/AngelTypes_view.php:346
-#, php-format
msgid "Team %s"
msgstr "Team %s"
-#: includes/controller/angeltypes_controller.php:287
-#: includes/view/User_view.php:397
-msgid "view"
-msgstr "ansehen"
-
-#: includes/controller/angeltypes_controller.php:295
-#: includes/pages/admin_free.php:97 includes/pages/admin_groups.php:44
-#: includes/pages/admin_rooms.php:27 includes/view/AngelTypes_view.php:175
-#: includes/view/ShiftTypes_view.php:91 includes/view/ShiftTypes_view.php:123
-#: includes/view/Shifts_view.php:155 includes/view/User_view.php:402
-#: includes/view/User_view.php:496 includes/view/User_view.php:591
-msgid "edit"
-msgstr "bearbeiten"
-
-#: includes/controller/angeltypes_controller.php:300
-#: includes/controller/shifts_controller.php:245
-#: includes/pages/admin_questions.php:58 includes/pages/admin_questions.php:74
-#: includes/pages/admin_rooms.php:32 includes/pages/admin_user.php:181
-#: includes/view/AngelTypes_view.php:64 includes/view/AngelTypes_view.php:182
-#: includes/view/Questions_view.php:13 includes/view/Questions_view.php:22
-#: includes/view/ShiftEntry_view.php:28 includes/view/ShiftEntry_view.php:57
-#: includes/view/ShiftTypes_view.php:28 includes/view/ShiftTypes_view.php:96
-#: includes/view/ShiftTypes_view.php:128 includes/view/Shifts_view.php:156
-#: includes/view/User_view.php:501
-msgid "delete"
-msgstr "lΓΆschen"
-
-#: includes/controller/angeltypes_controller.php:311
-#: includes/view/AngelTypes_view.php:168 includes/view/AngelTypes_view.php:537
-msgid "leave"
-msgstr "verlassen"
-
-# As already mentioned in Issue #312 : I'd suggest "join angel" and the German translation
-# "Engel hinzufΓΌgen" for this button.
-#: includes/controller/angeltypes_controller.php:317
-#: includes/view/AngelTypes_view.php:152 includes/view/AngelTypes_view.php:542
-msgid "join"
-msgstr "mitmachen"
-
-#: includes/controller/angeltypes_controller.php:354
-msgid "Angeltype doesn't exist . "
-msgstr "Engeltyp existiert nicht."
-
-#: includes/controller/event_config_controller.php:11 includes/sys_menu.php:122
+msgid "%s (not \"%s\")"
+msgstr "%s (kein \"%s\")"
+
+msgid "View"
+msgstr "Ansehen"
+
+msgid "Leave"
+msgstr "Verlassen"
+
+msgid "Join"
+msgstr "Mitmachen"
+
msgid "Event config"
msgstr "Event Einstellungen"
-#: includes/controller/event_config_controller.php:53
msgid "Please enter buildup start date."
msgstr "Bitte gib das Aufbau Start Datum an."
-#: includes/controller/event_config_controller.php:57
msgid "Please enter event start date."
msgstr "Bitte gib das Event Start Datum an."
-#: includes/controller/event_config_controller.php:61
msgid "Please enter event end date."
msgstr "Bitte gib das Event Ende Datum an."
-#: includes/controller/event_config_controller.php:65
msgid "Please enter teardown end date."
msgstr "Bitte gib das Abbau Ende Datum an."
-#: includes/controller/event_config_controller.php:71
msgid "The buildup start date has to be before the event start date."
msgstr "Das Aufbau Start Datum muss vor dem Event Start Datum liegen."
-#: includes/controller/event_config_controller.php:76
msgid "The event start date has to be before the event end date."
msgstr "Das Event Start Datum muss vor dem Event End Datum liegen."
-#: includes/controller/event_config_controller.php:81
msgid "The event end date has to be before the teardown end date."
msgstr "Das Event Ende Datum muss vor dem Abbau Ende Datum liegen."
-#: includes/controller/event_config_controller.php:86
msgid "The buildup start date has to be before the teardown end date."
msgstr "Das Aufbau Start Datum muss vor dem Abbau Ende Datum liegen."
-#: includes/controller/event_config_controller.php:120
-msgid "Settings saved."
-msgstr "Einstellungen gespeichert."
-
-#: includes/controller/public_dashboard_controller.php:27
-#: includes/pages/user_shifts.php:277 includes/view/PublicDashboard_view.php:55
msgid "Public Dashboard"
msgstr "Γffentliches Dashboard"
-#: includes/controller/shift_entries_controller.php:109
-#: includes/controller/shift_entries_controller.php:181
-#, php-format
+msgid "shifts.random"
+msgstr "ZufΓ€llige Schicht"
+
msgid "%s has been subscribed to the shift."
msgstr "%s wurde in die Schicht eingetragen."
-#: includes/controller/shift_entries_controller.php:149
msgid "User is not in angeltype."
msgstr "User ist nicht im Engeltyp."
-#: includes/controller/shift_entries_controller.php:166
-#: includes/controller/shift_entries_controller.php:210
msgid "This shift is already occupied."
msgstr "Die Schicht ist schon voll."
-#: includes/controller/shift_entries_controller.php:206
msgid "You need be accepted member of the angeltype."
msgstr "Du musst bestΓ€tigtes Mitglied des Engeltyps sein."
-#: includes/controller/shift_entries_controller.php:208
-#: includes/view/Shifts_view.php:138
msgid "This shift collides with one of your shifts."
msgstr "Diese Schicht kollidiert mit deinen Schichten."
-#: includes/controller/shift_entries_controller.php:212
msgid "This shift ended already."
msgstr "Die Schicht ist schon vorbei."
-#: includes/controller/shift_entries_controller.php:214
msgid "You are not marked as arrived."
msgstr "Du bist nicht als angekommen markiert."
-#: includes/controller/shift_entries_controller.php:216
msgid "You are not allowed to sign up yet."
msgstr "Du darfst dich noch nicht anmelden."
-#: includes/controller/shift_entries_controller.php:218
-#: includes/view/Shifts_view.php:142
msgid "You are signed up for this shift."
msgstr "Du bist fΓΌr diese Schicht eingetragen."
-#: includes/controller/shift_entries_controller.php:267
msgid "You are subscribed. Thank you!"
msgstr "Du bist eingetragen. Danke!"
-#: includes/controller/shift_entries_controller.php:326
-msgid "Shift entry not found."
-msgstr "Schichteintrag nicht gefunden."
-
-#: includes/controller/shift_entries_controller.php:348
msgid ""
"You are not allowed to remove this shift entry. If necessary, ask your "
"supporter or heaven to do so."
@@ -439,442 +268,191 @@ msgstr ""
"Du darfst diesen Schichteintrag nicht entfernen. Falls notwendig, frage "
"deinen Supporter oder im Himmel danach."
-#: includes/controller/shift_entries_controller.php:354
msgid "Shift entry removed."
msgstr "Schichteintrag gelΓΆscht."
-#: includes/controller/shifts_controller.php:65
msgid "This shift was imported from a schedule so some changes will be overwritten with the next import."
msgstr ""
"Diese Schicht wurde aus einem Fahrplan importiert. "
"Dadurch werden einige Γnderungen beim nΓ€chsten Import ΓΌberschrieben."
-#: includes/controller/shifts_controller.php:96
-msgid "Please select a room."
-msgstr "Bitte einen Raum auswΓ€hlen."
+msgid "Please select a location."
+msgstr "Bitte einen Ort auswΓ€hlen."
-#: includes/controller/shifts_controller.php:103
msgid "Please select a shifttype."
msgstr "Bitte einen Schichttyp wΓ€hlen."
-#: includes/controller/shifts_controller.php:110
msgid "Please enter a valid starting time for the shifts."
msgstr "Bitte gib eine korrekte Startzeit fΓΌr die Schichten ein."
-#: includes/controller/shifts_controller.php:117
msgid "Please enter a valid ending time for the shifts."
msgstr "Bitte gib eine korrekte Endzeit fΓΌr die Schichten ein."
-#: includes/controller/shifts_controller.php:122
msgid "The ending time has to be after the starting time."
msgstr "Die Endzeit muss nach der Startzeit liegen."
-#: includes/controller/shifts_controller.php:135
-#, php-format
msgid "Please check your input for needed angels of type %s."
msgstr "Bitte prΓΌfe deine Eingabe fΓΌr benΓΆtigte Engel des Typs %s."
-#: includes/controller/shifts_controller.php:165
msgid "Shift updated."
msgstr "Schicht aktualisiert."
-#: includes/controller/shifts_controller.php:184
msgid "This page is much more comfortable with javascript."
msgstr "Diese Seite ist mit JavaScript viel komfortabler."
-#: includes/controller/shifts_controller.php:187
-#: includes/pages/admin_import.php:123 includes/pages/admin_shifts.php:415
msgid "Shifttype"
msgstr "Schichttyp"
-#: includes/controller/shifts_controller.php:188
-#: includes/pages/admin_import.php:197 includes/pages/admin_import.php:206
-#: includes/pages/admin_import.php:215 includes/pages/admin_shifts.php:416
-#: includes/view/Shifts_view.php:18
-msgid "Title"
+msgid "title.title"
msgstr "Titel"
-#: includes/controller/shifts_controller.php:189
-msgid "Room:"
-msgstr "Raum:"
+msgid "Location:"
+msgstr "Ort:"
-#: includes/controller/shifts_controller.php:190
msgid "Start:"
msgstr "Start:"
-#: includes/controller/shifts_controller.php:191
msgid "End:"
msgstr "Ende:"
-#: includes/controller/shifts_controller.php:192
-#: includes/pages/admin_shifts.php:337 includes/pages/admin_shifts.php:452
-#: includes/view/Shifts_view.php:167
msgid "Needed angels"
msgstr "BenΓΆtigte Engel"
-#: includes/controller/shifts_controller.php:232
msgid "Shift deleted."
msgstr "Schicht gelΓΆscht."
-msgid "Shifts history"
-msgstr "Schichten Historie"
-
-msgid "%s shifts deleted."
-msgstr "%s Schichten gelΓΆscht."
-
-msgid "Created"
-msgstr "Erstellt"
-
-msgid "delete all"
-msgstr "alle lΓΆschen"
-
-#: includes/controller/shifts_controller.php:238
-#, php-format
msgid "Do you want to delete the shift %s from %s to %s?"
msgstr "MΓΆchtest Du die Schicht %s von %s bis %s lΓΆschen?"
-#: includes/controller/shifts_controller.php:268
msgid "Shift could not be found."
msgstr "Schicht konnte nicht gefunden werden."
-#: includes/controller/shifttypes_controller.php:33
-#, php-format
-msgid "Shifttype %s deleted."
-msgstr "Schichttyp %s gelΓΆscht."
-
-#: includes/controller/shifttypes_controller.php:38
-#: includes/view/ShiftTypes_view.php:21
-#, php-format
-msgid "Delete shifttype %s"
-msgstr "LΓΆsche Schichttyp %s"
-
-#: includes/controller/shifttypes_controller.php:61
-msgid "Shifttype not found."
-msgstr "Schichttyp nicht gefunden."
-
-#: includes/controller/shifttypes_controller.php:77
-#: includes/pages/admin_rooms.php:88
-msgid "Please enter a name."
-msgstr "Gib bitte einen Namen an."
-
-#: includes/controller/shifttypes_controller.php:95
-msgid "Updated shifttype."
-msgstr "Schichttyp geΓ€ndert."
-
-#: includes/controller/shifttypes_controller.php:100
-msgid "Created shifttype."
-msgstr "Schichttyp erstellt."
-
-#: includes/controller/shifttypes_controller.php:159 includes/sys_menu.php:116
-msgid "Shifttypes"
-msgstr "Schichttypen"
-
-#: includes/controller/user_angeltypes_controller.php:28
-#, php-format
msgid "There is %d unconfirmed angeltype."
msgid_plural "There are %d unconfirmed angeltypes."
msgstr[0] "Es gibt %d nicht freigeschalteten Engeltypen!"
msgstr[1] "Es gibt %d nicht freigeschaltete Engeltypen!"
-#: includes/controller/user_angeltypes_controller.php:33
msgid "Angel types which need approvals:"
msgstr "Engeltypen die bestΓ€tigt werden mΓΌssen:"
-#: includes/controller/user_angeltypes_controller.php:47
-#: includes/controller/user_angeltypes_controller.php:53
-#: includes/controller/user_angeltypes_controller.php:87
-#: includes/controller/user_angeltypes_controller.php:93
-#: includes/controller/user_angeltypes_controller.php:139
-#: includes/controller/user_angeltypes_controller.php:199
-#: includes/controller/user_angeltypes_controller.php:264
-msgid "Angeltype doesn't exist."
-msgstr "Engeltyp existiert nicht."
-
-#: includes/controller/user_angeltypes_controller.php:58
msgid "You are not allowed to delete all users for this angeltype."
msgstr "Du darfst nicht alle Benutzer von diesem Engeltyp entfernen."
-#: includes/controller/user_angeltypes_controller.php:66
-#, php-format
msgid "Denied all users for angeltype %s."
msgstr "Alle Benutzer mit Engeltyp %s abgelehnt."
-#: includes/controller/user_angeltypes_controller.php:71
-#: includes/view/UserAngelTypes_view.php:45
msgid "Deny all users"
msgstr "Alle Benutzer ablehnen"
-#: includes/controller/user_angeltypes_controller.php:98
msgid "You are not allowed to confirm all users for this angeltype."
msgstr "Du darfst nicht alle Benutzer fΓΌr diesen Engeltyp freischalten."
-#: includes/controller/user_angeltypes_controller.php:106
-#, php-format
msgid "Confirmed all users for angeltype %s."
msgstr "Alle Benutzer fΓΌr Engeltyp %s freigeschaltet."
-#: includes/controller/user_angeltypes_controller.php:111
-#: includes/view/UserAngelTypes_view.php:69
msgid "Confirm all users"
msgstr "Alle Benutzer bestΓ€tigen"
-#: includes/controller/user_angeltypes_controller.php:127
-#: includes/controller/user_angeltypes_controller.php:133
-#: includes/controller/user_angeltypes_controller.php:187
-#: includes/controller/user_angeltypes_controller.php:193
-#: includes/controller/user_angeltypes_controller.php:245
-#: includes/controller/user_angeltypes_controller.php:258
-msgid "User angeltype doesn't exist."
-msgstr "Benutzer-Engeltype existiert nicht."
-
-#: includes/controller/user_angeltypes_controller.php:144
msgid "You are not allowed to confirm this users angeltype."
msgstr "Du darfst diesen Benutzer nicht fΓΌr diesen Engeltyp freischalten."
-#: includes/controller/user_angeltypes_controller.php:150
-#: includes/controller/user_angeltypes_controller.php:205
-#: includes/controller/user_angeltypes_controller.php:270
-#: includes/controller/users_controller.php:327
-msgid "User doesn't exist."
-msgstr "Benutzer existiert nicht."
-
-#: includes/controller/user_angeltypes_controller.php:163
-#, php-format
msgid "%s confirmed for angeltype %s."
msgstr "%s fΓΌr Engeltyp %s freigeschaltet."
-#: includes/controller/user_angeltypes_controller.php:171
-#: includes/view/UserAngelTypes_view.php:89
msgid "Confirm angeltype for user"
msgstr "Engeltyp fΓΌr Benutzer bestΓ€tigen"
-#: includes/controller/user_angeltypes_controller.php:210
msgid "You are not allowed to delete this users angeltype."
msgstr "Du darfst diesen Benutzer nicht von diesem Engeltyp entfernen."
-#: includes/controller/user_angeltypes_controller.php:218
-#, php-format
msgid "User %s removed from %s."
msgstr "Benutzer %s von %s entfernt."
-#: includes/controller/user_angeltypes_controller.php:224
-#: includes/view/UserAngelTypes_view.php:113
msgid "Remove angeltype"
msgstr "Engeltyp lΓΆschen"
-#: includes/controller/user_angeltypes_controller.php:240
msgid "You are not allowed to set supporter rights."
msgstr "Du darfst keine Supporterrechte bearbeiten."
-#: includes/controller/user_angeltypes_controller.php:252
msgid "No supporter update given."
msgstr "Kein Update fΓΌr Supporterrechte gegeben."
-#: includes/controller/user_angeltypes_controller.php:278
-#, php-format
msgid "Added supporter rights for %s to %s."
msgstr "%s hat %s als Supporter bekommen."
-#: includes/controller/user_angeltypes_controller.php:279
-#, php-format
msgid "Removed supporter rights for %s from %s."
msgstr "%s hat jetzt nicht mehr %s als Supporter."
-#: includes/controller/user_angeltypes_controller.php:295
-#: includes/view/AngelTypes_view.php:263
-#: includes/view/UserAngelTypes_view.php:14
msgid "Add supporter rights"
msgstr "Supporterrechte geben"
-#: includes/controller/user_angeltypes_controller.php:295
-#: includes/view/AngelTypes_view.php:246
-#: includes/view/UserAngelTypes_view.php:14
msgid "Remove supporter rights"
msgstr "Supporterrechte entfernen"
-#: includes/controller/user_angeltypes_controller.php:334
-#, php-format
msgid "User %s added to %s."
msgstr "Benutzer %s zu %s hinzugefΓΌgt."
-#: includes/controller/user_angeltypes_controller.php:351
-#: includes/view/UserAngelTypes_view.php:142
msgid "Add user to angeltype"
msgstr "Benutzer zu Engeltyp hinzufΓΌgen"
-#: includes/controller/user_angeltypes_controller.php:368
-#, php-format
msgid "You are already a %s."
msgstr "Du bist bereits %s."
-#: includes/controller/user_angeltypes_controller.php:375
-#, php-format
msgid "You joined %s."
msgstr "Du bist %s beigetreten."
-#: includes/controller/user_angeltypes_controller.php:396
-#: includes/view/UserAngelTypes_view.php:166
-#, php-format
msgid "Become a %s"
msgstr "Werde ein %s"
-#: includes/controller/user_driver_licenses_controller.php:26
-#, php-format
-msgid ""
-"You joined an angeltype which requires a driving license. Please edit your "
-"driving license information here: %s."
-msgstr ""
-"Du bist einem Engeltypen beigetreten, der FΓΌhrerschein-Infos benΓΆtigt. Bitte "
-"trage Deine FΓΌhrerschein-Infos hier ein: %s."
-
-#: includes/controller/user_driver_licenses_controller.php:27
-msgid "driving license information"
-msgstr "FΓΌhrerschein-Infos"
-
-#: includes/controller/user_driver_licenses_controller.php:133
-msgid "Your driver license information has been saved."
-msgstr "Deine FΓΌhrerschein-Infos wurden gespeichert."
-
-#: includes/controller/user_driver_licenses_controller.php:136
-msgid "Please select at least one driving license."
-msgstr "Bitte wΓ€hle mindestens einen FΓΌhrerschein-Typen aus."
-
-#: includes/controller/user_driver_licenses_controller.php:141
-msgid "Your driver license information has been removed."
-msgstr "Deine FΓΌhrerschein-Infos wurden gelΓΆscht."
-
-#: includes/controller/user_driver_licenses_controller.php:147
-#: includes/view/UserDriverLicenses_view.php:15
-#, php-format
-msgid "Edit %s driving license information"
-msgstr "Bearbeite die FΓΌhrerschein-Infos von %s"
-
-#: includes/controller/users_controller.php:64
msgid "You cannot delete yourself."
msgstr "Du kannst Dich nicht selber lΓΆschen."
-#: includes/controller/users_controller.php:76
msgid "auth.password.error"
msgstr "Dein Passwort stimmt nicht. Bitte probiere es nochmal."
-#: includes/controller/users_controller.php:85
msgid "User deleted."
msgstr "Engel gelΓΆscht."
-#: includes/controller/users_controller.php:93 includes/view/User_view.php:118
-#, php-format
msgid "Delete %s"
msgstr "%s lΓΆschen"
-#: includes/controller/users_controller.php:163
msgid "Please enter a valid number of vouchers."
msgstr "Bitte gib eine korrekte Anzahl von Gutscheinen ein."
-#: includes/controller/users_controller.php:170
msgid "Saved the number of vouchers."
msgstr "Anzahl der Gutscheine gespeichert."
-#: includes/controller/users_controller.php:179 includes/view/User_view.php:142
-#, php-format
-msgid "%s's vouchers"
-msgstr "Gutschein von %s"
-
-#: includes/controller/users_controller.php:196
msgid "User not found."
msgstr "Benutzer nicht gefunden."
-#: includes/controller/users_controller.php:231
msgid "Enough"
msgstr "Genug"
-#: includes/controller/users_controller.php:299 includes/view/User_view.php:247
msgid "All users"
msgstr "Alle Benutzer"
-#: includes/helper/email_helper.php:50
-#, php-format
-msgid "User %s could not be notified by email due to an error."
+msgid "User %s could not be notified by e-mail due to an error."
msgstr ""
"Aufgrund eines Fehlers konnte dem User %s keine E-Mail gesendet werden."
msgid "%s (%s as %s) in %s, %s - %s"
msgstr "%s (%s als %s) in %s, %s - %s"
-#: includes/mailer/shifts_mailer.php:17
-msgid "A Shift you are registered on has changed:"
-msgstr "Eine deiner Schichten hat sich geΓ€ndert:"
-
-#: includes/mailer/shifts_mailer.php:21
-#, php-format
-msgid "* Shift type changed from %s to %s"
-msgstr "* Schichttyp von %s in %s geΓ€ndert"
-
-#: includes/mailer/shifts_mailer.php:26
-#, php-format
-msgid "* Shift title changed from %s to %s"
-msgstr "* Schicht Titel von %s nach %s geΓ€ndert"
-
-#: includes/mailer/shifts_mailer.php:32
-#, php-format
-msgid "* Shift Start changed from %s to %s"
-msgstr "* Schicht Beginn von %s nach %s geΓ€ndert"
-
-#: includes/mailer/shifts_mailer.php:41
-#, php-format
-msgid "* Shift End changed from %s to %s"
-msgstr "* Schicht Ende von %s nach %s geΓ€ndert"
-
-#: includes/mailer/shifts_mailer.php:49
-#, php-format
-msgid "* Shift Location changed from %s to %s"
-msgstr "* Schicht Ort von %s to %s geΓ€ndert"
-
-#: includes/mailer/shifts_mailer.php:59
-msgid "The updated Shift:"
-msgstr "Die aktualisierte Schicht:"
-
-#: includes/mailer/shifts_mailer.php:71
-msgid "Your Shift has changed"
-msgstr "Deine Schicht hat sich geΓ€ndert"
-
-#: includes/mailer/shifts_mailer.php:87
-msgid "A Shift you are registered on was deleted:"
-msgstr "Eine deiner Schichten wurde gelΓΆscht:"
-
-#: includes/mailer/shifts_mailer.php:99
-msgid ""
-"Since the deleted shift was already done, we added a worklog entry instead, "
-"to keep your work hours correct."
-msgstr ""
-"Da die gelΓΆschte Schicht bereits vergangen ist, haben wir einen "
-"entsprechenden Arbeitseinsatz hinzugefΓΌgt."
-
-#: includes/mailer/shifts_mailer.php:102
-msgid "Your Shift was deleted"
-msgstr "Deine Schicht wurde gelΓΆscht"
-
-#: includes/mailer/shifts_mailer.php:119
msgid "You have been assigned to a Shift:"
msgstr "Du wurdest in eine Schicht eingetragen:"
-#: includes/mailer/shifts_mailer.php:125
msgid "Assigned to Shift"
msgstr "In Schicht eingetragen"
-#: includes/mailer/shifts_mailer.php:140
msgid "You have been removed from a Shift:"
msgstr "Du wurdest aus einer Schicht ausgetragen:"
-#: includes/mailer/shifts_mailer.php:146
msgid "Removed from Shift"
msgstr "Von Schicht ausgetragen"
-#: includes/mailer/users_mailer.php:13
-msgid "Your account has been deleted"
+msgid "Your account has been deleted."
msgstr "Dein Konto wurde gelΓΆscht."
-#: includes/mailer/users_mailer.php:15
-#, php-format
msgid ""
"Your %s account has been deleted. If you have any questions regarding your "
"account deletion, please contact heaven."
@@ -882,846 +460,289 @@ msgstr ""
"Dein %s-Konto wurde gelΓΆscht. Wenn Du dazu Fragen hast, kontaktiere bitte "
"den Himmel."
-#: includes/model/UserWorkLog_model.php:167
-#: includes/model/UserWorkLog_model.php:168 includes/view/User_view.php:200
-msgid "m/d/Y h:i a"
-msgstr "d.m.Y H:i"
-
-#: includes/pages/admin_active.php:13 includes/sys_menu.php:112
msgid "Active angels"
msgstr "Aktive Engel"
-#: includes/pages/admin_active.php:42
-#, php-format
msgid ""
"At least %s angels are forced to be active. The number has to be greater."
msgstr ""
"Mindestens %s Engel werden als aktiv gekennzeichnet. Die Nummer muss grΓΆΓer "
"sein."
-#: includes/pages/admin_active.php:48
msgid "Please enter a number of angels to be marked as active."
msgstr ""
"Bitte gib eine Anzahl an Engeln ein, die als Aktiv markiert werden sollen."
-#: includes/pages/admin_active.php:95
msgid "Marked angels."
msgstr "Engel wurden markiert."
-#: includes/pages/admin_active.php:98 includes/pages/admin_rooms.php:155
-#: includes/pages/admin_rooms.php:198 includes/pages/admin_shifts.php:333
-#: includes/view/UserAngelTypes_view.php:147
-#: includes/view/User_view.php:121 includes/view/User_view.php:145
-msgid "back"
-msgstr "zurΓΌck"
+msgid "general.back"
+msgstr "ZurΓΌck"
-#: includes/pages/admin_active.php:99
-msgid "apply"
-msgstr "anwenden"
+msgid "Apply"
+msgstr "Anwenden"
-#: includes/pages/admin_active.php:112
msgid "Angel has been marked as active."
msgstr "Engel wurde als aktiv markiert."
-#: includes/pages/admin_active.php:114 includes/pages/admin_active.php:125
-#: includes/pages/admin_active.php:147 includes/pages/admin_arrive.php:44
-#: includes/pages/admin_arrive.php:62
msgid "Angel not found."
msgstr "Engel nicht gefunden."
-#: includes/pages/admin_active.php:123
msgid "Angel has been marked as not active."
msgstr "Engel wurde als nicht aktiv markiert."
-#: includes/pages/admin_active.php:134
-msgid "Angel has got a t-shirt."
+msgid "Angel has got a T-shirt."
msgstr "Engel hat ein T-Shirt bekommen."
-#: includes/pages/admin_active.php:145
-msgid "Angel has got no t-shirt."
+msgid "Angel has got no T-shirt."
msgstr "Engel hat kein T-Shirt bekommen."
-#: includes/pages/admin_active.php:235
msgid "set active"
msgstr "setze aktiv"
-#: includes/pages/admin_active.php:248
-msgid "remove active"
+msgid "Remove active"
msgstr "entferne aktiv"
-#: includes/pages/admin_active.php:261
-msgid "got t-shirt"
+msgid "Got T-shirt"
msgstr "T-Shirt bekommen"
-#: includes/pages/admin_active.php:274
-msgid "remove t-shirt"
+msgid "Remove T-shirt"
msgstr "entferne T-Shirt"
-#: includes/pages/admin_active.php:299 includes/pages/admin_arrive.php:202
-#: includes/pages/admin_arrive.php:217 includes/pages/admin_arrive.php:232
-#: includes/view/AngelTypes_view.php:424 includes/view/AngelTypes_view.php:432
-#: includes/view/User_view.php:207
msgid "Sum"
msgstr "Summe"
-#: includes/pages/admin_active.php:305
msgid "Search angel:"
msgstr "Suche Engel:"
-#: includes/pages/admin_active.php:306
msgid "Show all shifts"
msgstr "Alle Schichten anzeigen"
-#: includes/pages/admin_active.php:307 includes/pages/admin_arrive.php:178
-#: includes/pages/admin_arrive.php:179 includes/pages/admin_free.php:105
-msgid "Search"
-msgstr "Suche"
-
-#: includes/pages/admin_active.php:310
msgid "How much angels should be active?"
msgstr "Wie viele Engel sollten aktiv sein?"
-#: includes/pages/admin_active.php:311 includes/pages/admin_shifts.php:320
-#: includes/pages/admin_shifts.php:470
-msgid "Preview"
-msgstr "Vorschau"
-
-#: includes/pages/admin_active.php:315 includes/pages/admin_arrive.php:182
-msgid "Nickname"
-msgstr "Nick"
-
-#: includes/pages/admin_active.php:316 includes/pages/admin_active.php:326
-#: includes/view/User_view.php:233
msgid "Size"
msgstr "GrΓΆΓe"
msgid "No."
msgstr "Nr."
-#: includes/pages/admin_active.php:317 includes/pages/user_shifts.php:11
-#: includes/sys_menu.php:96 includes/view/AngelTypes_view.php:357
-#: includes/view/Rooms_view.php:39 includes/view/User_view.php:641
msgid "Shifts"
msgstr "Schichten"
-#: includes/pages/admin_active.php:318 includes/pages/admin_shifts.php:427
msgid "Length"
msgstr "LΓ€nge"
-#: includes/pages/admin_active.php:319
msgid "Active?"
msgstr "Aktiv?"
-#: includes/pages/admin_active.php:320 includes/view/User_view.php:231
msgid "Forced"
msgstr "Erzwungen"
-#: includes/pages/admin_active.php:321
msgid "T-shirt?"
msgstr "T-Shirt?"
-#: includes/pages/admin_active.php:324
-msgid "Shirt statistic"
+msgid "T-shirt statistic"
msgstr "T-Shirt Statistik"
-#: includes/pages/admin_active.php:327
-msgid "Given shirts"
+msgid "Given T-shirts"
msgstr "Ausgegebene T-Shirts"
-#: includes/pages/admin_arrive.php:10 includes/sys_menu.php:111
msgid "Arrive angels"
msgstr "Ankommende Engel"
-#: includes/pages/admin_arrive.php:41
msgid "Reset done. Angel has not arrived."
msgstr "ZurΓΌckgesetzt. Engel ist nicht angekommen."
-#: includes/pages/admin_arrive.php:59
msgid "Angel has been marked as arrived."
msgstr "Engel wurde als angekommen markiert."
-#: includes/pages/admin_arrive.php:106
-msgid "reset"
-msgstr "zurΓΌcksetzen"
-
-#: includes/pages/admin_arrive.php:106 includes/pages/admin_arrive.php:193
-#: includes/pages/admin_arrive.php:208 includes/pages/admin_arrive.php:223
-#: includes/view/User_view.php:601
-msgid "arrived"
-msgstr "angekommen"
+msgid "Reset"
+msgstr "ZurΓΌcksetzen"
-#: includes/pages/admin_arrive.php:183 includes/view/User_view.php:236
msgid "Planned arrival"
msgstr "Geplanter Ankunftstag"
-#: includes/pages/admin_arrive.php:184
msgid "Arrived?"
msgstr "Angekommen?"
-#: includes/pages/admin_arrive.php:185
msgid "Arrival date"
msgstr "Ankunftsdatum"
-#: includes/pages/admin_arrive.php:186 includes/view/User_view.php:241
msgid "Planned departure"
msgstr "Geplante Abreise"
-#: includes/pages/admin_arrive.php:191
msgid "Planned arrival statistics"
msgstr "Geplante Ankunfts-Statistik"
-#: includes/pages/admin_arrive.php:194 includes/pages/admin_arrive.php:209
-#: includes/pages/admin_arrive.php:224
msgid "arrived sum"
msgstr "Summe angekommen"
-#: includes/pages/admin_arrive.php:200 includes/pages/admin_arrive.php:215
-#: includes/pages/admin_arrive.php:230
-#: includes/pages/user_messages.php:118
-msgid "Date"
+msgid "title.date"
msgstr "Datum"
-#: includes/pages/admin_arrive.php:201 includes/pages/admin_arrive.php:216
-#: includes/pages/admin_arrive.php:231
-msgid "Count"
-msgstr "Anzahl"
-
-#: includes/pages/admin_arrive.php:206
msgid "Arrival statistics"
msgstr "Ankunfts-Statistik"
-#: includes/pages/admin_arrive.php:221
msgid "Planned departure statistics"
msgstr "Geplante Abreise-Statistik"
-#: includes/pages/admin_free.php:12 includes/sys_menu.php:114
msgid "Free angels"
msgstr "Freie Engel"
-#: includes/pages/admin_free.php:29
-msgid "Alle"
-msgstr "All"
-
-#: includes/pages/admin_free.php:106 includes/view/ShiftEntry_view.php:91
-#: includes/view/ShiftTypes_view.php:61
-#: includes/view/UserAngelTypes_view.php:152
msgid "Angeltype"
msgstr "Engeltyp"
-#: includes/pages/admin_free.php:112 includes/pages/guest_login.php:275
-#: includes/view/AngelTypes_view.php:298 includes/view/AngelTypes_view.php:311
-#: includes/view/User_view.php:39 includes/view/User_view.php:218
-msgid "Nick"
-msgstr "Nick"
-
-#: includes/pages/admin_free.php:113
-msgid "Next shift"
+msgid "shift.next"
msgstr "NΓ€chste Schicht"
-#: includes/pages/admin_free.php:114
msgid "Last shift"
msgstr "Letzte Schicht"
-#: includes/pages/admin_free.php:115 includes/pages/guest_login.php:336
-#: includes/view/AngelTypes_view.php:118 includes/view/AngelTypes_view.php:299
-#: includes/view/AngelTypes_view.php:312 includes/view/AngelTypes_view.php:481
-#: includes/view/User_view.php:60 includes/view/User_view.php:225
-msgid "DECT"
+msgid "general.dect"
msgstr "DECT"
-#: includes/pages/admin_groups.php:10 includes/sys_menu.php:119
msgid "Grouprights"
msgstr "Gruppenrechte"
-#: includes/pages/admin_groups.php:52 includes/pages/admin_import.php:184
-#: includes/pages/admin_import.php:188 includes/pages/admin_rooms.php:161
-#: includes/pages/admin_rooms.php:214 includes/view/AngelTypes_view.php:86
-#: includes/view/AngelTypes_view.php:87 includes/view/AngelTypes_view.php:117
-#: includes/view/AngelTypes_view.php:480 includes/view/AngelTypes_view.php:504
-#: includes/view/ShiftTypes_view.php:60 includes/view/ShiftTypes_view.php:140
-#: includes/view/User_view.php:222
-msgid "Name"
+msgid "general.name"
msgstr "Name"
-#: includes/pages/admin_groups.php:53
msgid "Privileges"
msgstr "Privilegien"
-#: includes/pages/admin_groups.php:102
msgid "Edit group"
msgstr "Gruppe bearbeiten"
-#: includes/pages/admin_import.php:8 includes/pages/admin_rooms.php:162
-#: includes/pages/admin_rooms.php:215 includes/sys_menu.php:120
-msgid "Frab import"
-msgstr "Frab Import"
-
-#: includes/pages/admin_import.php:39
-msgid "Webserver has no write-permission on import directory."
-msgstr "Der Webserver hat keine Schreibrechte fΓΌr das Verzeichnis import."
-
-#: includes/pages/admin_import.php:64 includes/pages/admin_import.php:143
-#: includes/pages/admin_import.php:242 includes/pages/admin_shifts.php:60
-#: includes/pages/admin_shifts.php:66
msgid "Please select a shift type."
msgstr "Bitte einen Schichttyp wΓ€hlen."
-#: includes/pages/admin_import.php:72 includes/pages/admin_import.php:150
-#: includes/pages/admin_import.php:249
-msgid "Please enter an amount of minutes to add to a talk's begin."
-msgstr ""
-"Bitte gib eine Anzahl Minuten ein, die vor dem Talk-Beginn hinzugefΓΌgt "
-"werden sollen."
-
-#: includes/pages/admin_import.php:79 includes/pages/admin_import.php:157
-#: includes/pages/admin_import.php:256
-msgid "Please enter an amount of minutes to add to a talk's end."
-msgstr ""
-"Bitte gib eine Anzahl Minuten ein, die nach dem Talk-Ende hinzugefΓΌgt werden "
-"sollen."
-
-#: includes/pages/admin_import.php:87
-msgid "No valid xml/xcal file provided."
-msgstr "Keine valide xml/xcal Datei hochgeladen."
-
-#: includes/pages/admin_import.php:92
-msgid "File upload went wrong."
-msgstr "Das Hochladen der Datei ist schiefgegangen."
-
-#: includes/pages/admin_import.php:96
-msgid "Please provide some data."
-msgstr "Bitte lade eine Datei hoch."
-
-#: includes/pages/admin_import.php:111 includes/pages/admin_import.php:172
-#: includes/pages/admin_import.php:292
-msgid "File Upload"
-msgstr "Datei hochladen"
-
-#: includes/pages/admin_import.php:113 includes/pages/admin_import.php:174
-#: includes/pages/admin_import.php:294
-msgid "Validation"
-msgstr "ΓberprΓΌfen"
-
-#: includes/pages/admin_import.php:115 includes/pages/admin_import.php:127
-#: includes/pages/admin_import.php:176 includes/pages/admin_import.php:218
-#: includes/pages/admin_import.php:296
-msgid "Import"
-msgstr "Importieren"
-
-#: includes/pages/admin_import.php:121
-msgid ""
-"This import will create/update/delete rooms and shifts by given FRAB-export "
-"file. The needed file format is xcal."
-msgstr ""
-"Dieser Import erzeugt, Γ€ndert und lΓΆscht RΓ€ume und Schichten anhand einer "
-"FRAB-Export Datei. Das benΓΆtigte Format ist xcal."
-
-#: includes/pages/admin_import.php:124
-msgid "Add minutes to start"
-msgstr "Minuten vor Talk-Beginn hinzufΓΌgen"
-
-#: includes/pages/admin_import.php:125
-msgid "Add minutes to end"
-msgstr "Minuten nach Talk-Ende hinzufΓΌgen"
-
-#: includes/pages/admin_import.php:126
-msgid "xcal-File (.xcal)"
-msgstr "xcal-Datei (.xcal)"
+msgid "Reset to previous state"
+msgstr "Auf vorherigen Stand zurΓΌcksetzen"
-#: includes/pages/admin_import.php:136 includes/pages/admin_import.php:231
-msgid "Missing import file."
-msgstr "Import-Datei nicht vorhanden."
-
-#: includes/pages/admin_import.php:183
-msgid "Rooms to create"
-msgstr "Anzulegende RΓ€ume"
-
-#: includes/pages/admin_import.php:187
-msgid "Rooms to delete"
-msgstr "Zu lΓΆschende RΓ€ume"
-
-#: includes/pages/admin_import.php:191
-msgid "Shifts to create"
-msgstr "Anzulegende Schichten"
-
-#: includes/pages/admin_import.php:193 includes/pages/admin_import.php:202
-#: includes/pages/admin_import.php:211
-msgid "Day"
-msgstr "Tag"
-
-#: includes/pages/admin_import.php:194 includes/pages/admin_import.php:203
-#: includes/pages/admin_import.php:212 includes/pages/admin_shifts.php:420
-#: includes/view/Shifts_view.php:26
-msgid "Start"
-msgstr "Beginn"
-
-#: includes/pages/admin_import.php:195 includes/pages/admin_import.php:204
-#: includes/pages/admin_import.php:213 includes/pages/admin_shifts.php:421
-#: includes/view/Shifts_view.php:34
-msgid "End"
-msgstr "Ende"
-
-#: includes/pages/admin_import.php:196 includes/pages/admin_import.php:205
-#: includes/pages/admin_import.php:214
-msgid "Shift type"
-msgstr "Schichttyp"
-
-#: includes/pages/admin_import.php:198 includes/pages/admin_import.php:207
-#: includes/pages/admin_import.php:216 includes/pages/admin_shifts.php:417
-msgid "Room"
-msgstr "Raum"
-
-#: includes/pages/admin_import.php:200
-msgid "Shifts to update"
-msgstr "Zu aktualisierende Schichten"
-
-#: includes/pages/admin_import.php:209
-msgid "Shifts to delete"
-msgstr "Zu lΓΆschende Schichten"
-
-#: includes/pages/admin_import.php:297
-msgid "It's done!"
-msgstr "Erledigt!"
-
-#: includes/pages/admin_rooms.php:202
-#: includes/view/User_view.php:129
-msgid "Delete"
-msgstr "lΓΆschen"
+msgid "Location"
+msgstr "Ort"
-#: includes/pages/admin_questions.php:11 includes/sys_menu.php:115
msgid "Answer questions"
msgstr "Fragen beantworten"
-#: includes/pages/admin_questions.php:27
msgid "There are unanswered questions!"
msgstr "Es gibt unbeantwortete Fragen!"
-#: includes/pages/admin_questions.php:80
-msgid "Unanswered questions"
-msgstr "Unbeantwortete Fragen"
-
-#: includes/pages/admin_questions.php:82 includes/pages/admin_questions.php:89
-msgid "From"
-msgstr "Von"
-
-#: includes/pages/admin_questions.php:83 includes/pages/admin_questions.php:90
-#: includes/view/Questions_view.php:30 includes/view/Questions_view.php:35
-msgid "Question"
-msgstr "Frage"
-
-#: includes/pages/admin_questions.php:84 includes/pages/admin_questions.php:92
-#: includes/view/Questions_view.php:37
-msgid "Answer"
-msgstr "Antwort"
-
-#: includes/pages/admin_questions.php:87 includes/view/Questions_view.php:33
-msgid "Answered questions"
-msgstr "Beantwortete Fragen"
-
-#: includes/pages/admin_questions.php:91 includes/view/Questions_view.php:36
-msgid "Answered by"
-msgstr "Antwort von"
-
-#: includes/pages/admin_questions.php:102 includes/view/Questions_view.php:40
-msgid "Answered at"
-msgstr "Beantwortet am"
-
-#: includes/pages/admin_questions.php:91 includes/view/Questions_view.php:37
-msgid "Asked at"
-msgstr "Gefragt am"
+msgid "Locations"
+msgstr "Orte"
-#: includes/pages/admin_rooms.php:7 includes/pages/user_shifts.php:230
-#: includes/sys_menu.php:118 includes/sys_menu.php:172
-msgid "Rooms"
-msgstr "RΓ€ume"
-
-#: includes/pages/admin_rooms.php:82
-msgid "This name is already in use."
-msgstr "Dieser Name ist bereits vergeben."
-
-#: includes/pages/admin_rooms.php:113
-#, php-format
-msgid "Please enter needed angels for type %s."
-msgstr "Bitte gib die Anzahl der benΓΆtigten Engel vom Typ %s an."
-
-#: includes/pages/admin_rooms.php:142
-msgid "Room saved."
-msgstr "Raum gespeichert."
-
-#: includes/pages/admin_rooms.php:163
-msgid "Map URL"
-msgstr "Karten URL"
-
-#: includes/pages/admin_rooms.php:164
-msgid "The map url is used to display an iframe on the room page."
-msgstr ""
-"Die Karten URL wird benutzt um auf der Raum-Seite ein iframe anzuzeigen."
-
-#: includes/pages/admin_rooms.php:165 includes/view/AngelTypes_view.php:110
-#: includes/view/AngelTypes_view.php:403 includes/view/Rooms_view.php:24
-#: includes/view/ShiftTypes_view.php:62 includes/view/ShiftTypes_view.php:100
-#: includes/view/Shifts_view.php:171
-msgid "Description"
+msgid "general.description"
msgstr "Beschreibung"
-#: includes/pages/admin_rooms.php:166 includes/view/AngelTypes_view.php:111
-#: includes/view/ShiftTypes_view.php:63
msgid "Please use markdown for the description."
msgstr "Bitte benutze Markdown fΓΌr die Beschreibung."
-#: includes/pages/admin_rooms.php:171 includes/view/PublicDashboard_view.php:26
msgid "Needed angels:"
msgstr "BenΓΆtigte Engel:"
-#: includes/pages/admin_rooms.php:192
-#, php-format
-msgid "Room %s deleted."
-msgstr "Raum %s gelΓΆscht."
-
-#: includes/pages/admin_rooms.php:200
-#, php-format
-msgid "Do you want to delete room %s?"
-msgstr "MΓΆchest Du den Raum %s wirklich lΓΆschen?"
-
-#: includes/pages/admin_rooms.php:210
-msgid "add"
-msgstr "Neu"
-
-#: includes/pages/admin_rooms.php:216 includes/view/Rooms_view.php:31
-msgid "Map"
-msgstr "Karte"
-
-#: includes/pages/admin_shifts.php:10 includes/sys_menu.php:117
msgid "Create shifts"
msgstr "Schichten erstellen"
-#: includes/pages/admin_shifts.php
msgid "Additional description"
msgstr "ZusΓ€tzliche Beschreibung"
msgid "This description is for single shifts, otherwise please use the description in shift type."
msgstr "Diese Beschreibung ist fΓΌr einzelne Schichten, ansonsten nutze bitte die Beschreibung im Schichttyp."
-#: includes/pages/admin_shifts.php:82
-msgid "Please select a location."
-msgstr "Bitte einen Ort auswΓ€hlen."
-
-#: includes/pages/admin_shifts.php:89
msgid "Please select a start time."
msgstr "Bitte eine Startzeit auswΓ€hlen."
-#: includes/pages/admin_shifts.php:96
msgid "Please select an end time."
msgstr "Bitte eine Endzeit auswΓ€hlen."
-#: includes/pages/admin_shifts.php:101
msgid "The shifts end has to be after its start."
msgstr "Die Endzeit muss nach der Startzeit liegen."
-#: includes/pages/admin_shifts.php:113
msgid "Please enter a shift duration in minutes."
msgstr "Gib bitte eine SchichtlΓ€nge in Minuten ein."
-#: includes/pages/admin_shifts.php:130
+msgid "Please validate the change hour %s. It should be between 00:00 and 24:00."
+msgstr "Bitte korrigiere die Schichtwechselstunde %s. Sie sollte zwischen 00:00 und 24:00 Uhr liegen."
+
msgid "Please split the shift-change hours by colons."
msgstr "Trenne die Schichtwechselstunden mit einem Komma."
-#: includes/pages/admin_shifts.php:137
msgid "Please select a mode."
msgstr "Bitte einen Modus auswΓ€hlen."
-#: includes/pages/admin_shifts.php:150
-#, php-format
msgid "Please check the needed angels for team %s."
msgstr "Bitte gib die Anzahl der benΓΆtigten Engel vom Team %s an."
-#: includes/pages/admin_shifts.php:156
msgid "There are 0 angels needed. Please enter the amounts of needed angels."
msgstr "Es werden 0 Engel benΓΆtigt. Bitte Γ€ndere das."
-#: includes/pages/admin_shifts.php:160
msgid "Please select a mode for needed angels."
msgstr "Bitte wΓ€hle einen Modus fΓΌr benΓΆtigte Engel."
-#: includes/pages/admin_shifts.php:164
msgid "Please select needed angels."
msgstr "Bitte wΓ€hle benΓΆtigte Engel."
-#: includes/pages/admin_shifts.php:335
msgid "Time and location"
msgstr "Zeit und Ort"
-#: includes/pages/admin_shifts.php:336
msgid "Type and title"
msgstr "Typ und Titel"
-#: includes/pages/admin_shifts.php:422
msgid "Mode"
msgstr "Modus"
-#: includes/pages/admin_shifts.php:423
msgid "Create one shift"
msgstr "Eine Schicht erstellen"
-#: includes/pages/admin_shifts.php:424
msgid "Create multiple shifts"
msgstr "Mehrere Schichten erstellen"
-#: includes/pages/admin_shifts.php:434
msgid "Create multiple shifts with variable length"
msgstr "Erstelle mehrere Schichten mit unterschiedlicher LΓ€nge"
-#: includes/pages/admin_shifts.php:440
msgid "Shift change hours"
msgstr "Schichtwechsel-Stunden"
-#: includes/pages/admin_shifts.php:447
msgid "Create a shift over midnight."
-msgstr ""
+msgstr "Erstelle Schichten ΓΌber Mitternacht"
-#: includes/pages/admin_shifts.php:455
-msgid "Take needed angels from room settings"
-msgstr "Γbernehme benΓΆtigte Engel von den Raum-Einstellungen"
+msgid "Copy needed angels from location settings"
+msgstr "Kopiere benΓΆtigte Engel von den Ort-Einstellungen"
+
+msgid "Copy needed angels from shift type settings"
+msgstr "Kopiere benΓΆtigte Engel von den Schichttyp-Einstellungen"
-#: includes/pages/admin_shifts.php:461
msgid "The following angels are needed"
msgstr "Die folgenden Engel werden benΓΆtigt"
-#: includes/pages/admin_user.php:11 includes/sys_menu.php:113
msgid "All Angels"
-msgstr "Engelliste"
+msgstr "Alle Engel"
-#: includes/pages/admin_user.php:32
msgid "This user does not exist."
msgstr "Benutzer existiert nicht."
-#: includes/pages/admin_user.php:71 includes/pages/guest_login.php:307
-#: includes/view/User_view.php:81
-msgid "Please select..."
-msgstr "Bitte auswΓ€hlen..."
-
-#: includes/pages/admin_user.php:76 includes/pages/admin_user.php:83
-#: includes/view/AngelTypes_view.php:89 includes/view/AngelTypes_view.php:96
-#: includes/view/AngelTypes_view.php:101 includes/view/AngelTypes_view.php:108
msgid "Yes"
msgstr "Ja"
-#: includes/pages/admin_user.php:77 includes/pages/admin_user.php:85
-#: includes/view/AngelTypes_view.php:89 includes/view/AngelTypes_view.php:96
-#: includes/view/AngelTypes_view.php:102 includes/view/AngelTypes_view.php:108
msgid "No"
msgstr "Nein"
-#: includes/pages/admin_user.php:95
msgid "Force active"
msgstr "Aktiv erzwingen"
-#: includes/pages/admin_user.php:112
-msgid ""
-"Please visit the angeltypes page or the users profile to manage users "
-"angeltypes."
-msgstr ""
-"Bitte benutze die Engeltypen-Seite um die Engeltypen des Users zu verwalten."
-
-#: includes/pages/admin_user.php:314
msgid "Edit user"
msgstr "User bearbeiten"
-#: includes/pages/guest_login.php:77
-msgid "Please enter a valid nick."
-msgstr "Gib bitte einen erlaubten Nick an."
-
-#: includes/pages/guest_login.php:77 includes/pages/guest_login.php:277
-#: includes/view/User_view.php:42
-msgid ""
-"Use up to 24 letters, numbers, connecting punctuations or spaces for your "
-"nickname."
-msgstr ""
-"Verwende bis zu 24 Buchstaben, Zahlen, verbindende Schriftzeichen (.-_) oder "
-"Leerzeichen fΓΌr deinen Nick."
-
-#: includes/pages/guest_login.php:82
-#, php-format
-msgid "Your nick \"%s\" already exists."
-msgstr "Der Nick \"%s\" existiert bereits."
-
-#: includes/pages/guest_login.php:86
-msgid "Please enter a nickname."
-msgstr "Gib bitte einen Nick an."
-
-#: includes/pages/guest_login.php:93
-msgid "E-mail address is not correct."
-msgstr "Die E-Mail Adresse ist nicht in Ordnung."
-
-#: includes/pages/guest_login.php:97
-msgid "E-mail address is already used by another user."
-msgstr "Die E-Mail Adresse wurde bereits von einem anderen User benutzt."
-
-#: includes/pages/guest_login.php:101
-msgid "Please enter your e-mail."
-msgstr "Bitte gib Deine E-Mail-Adresse ein."
-
-#: includes/pages/guest_login.php:117
-msgid "Please select your shirt size."
-msgstr "Bitte wΓ€hle Deine T-Shirt GrΓΆΓe."
-
-#: includes/pages/guest_login.php:129
-#, php-format
-msgid "Your password is too short (please use at least %s characters)."
-msgstr "Dein Passwort ist zu kurz (Bitte mindestens %s Zeichen nutzen)."
-
-#: includes/pages/guest_login.php:140 includes/pages/guest_login.php:144
-msgid ""
-"Please enter your planned date of arrival. It should be after the buildup "
-"start date and before teardown end date."
-msgstr ""
-"Bitte gib Dein geplantes Ankunftsdatum an. Es sollte nach dem Aufbaubeginn "
-"und vor dem Abbauende liegen."
-
-#: includes/pages/guest_login.php:166
-msgid "For dect numbers are only 40 digits allowed."
-msgstr "Die DECT Nummer darf nur 40 Zeichen lang sein."
-
-#: includes/pages/guest_login.php:238
-msgid "Angel registration successful!"
-msgstr "Engel-Registrierung erfolgreich!"
-
-#: includes/pages/guest_login.php:267
-msgid ""
-"By completing this form you're registering as a Chaos-Angel. This script "
-"will create you an account in the angel task scheduler."
-msgstr ""
-"Mit diesem Formular registrierst Du Dich als Engel. Du bekommst ein Konto in "
-"der Engel-Aufgabenverwaltung."
-
-#: includes/pages/guest_login.php:284 includes/view/User_view.php:66
-#, php-format
-msgid "The %s is allowed to send me an email (e.g. when my shifts change)"
-msgstr "Das %s darf mir E-Mails senden (z.B. wenn sich meine Schichten Γ€ndern)"
-
-msgid "Notify me of new news"
-msgstr "Benachrichtige mich bei neuen News"
-
-#: includes/pages/guest_login.php:291 includes/view/User_view.php:73
-msgid "Allow heaven angels to contact you by e-mail."
-msgstr "Erlaube Himmel-Engeln dich per Mail zu kontaktieren."
-
-msgid ""
-"To receive vouchers, give consent that nick, email address, worked hours and shirt size "
-"will be stored until the next similar event."
-msgstr "Um Voucher zu erhalten, stimme zu, dass Nick, E-Mail-Adresse, geleistete Arbeit und ShirtgrΓΆΓe "
-"bis zum nΓ€chsten gleichartigen Event gespeichert werden."
-
-msgid "To withdraw your approval, send an email to %1$s."
-msgstr "Dies kann jederzeit durch eine E-Mail an %1$s widerrufen werden."
-
-#: includes/pages/guest_login.php:300 includes/view/User_view.php:48
-msgid "Planned date of arrival"
-msgstr "Geplanter Ankunftstag"
-
-#: includes/pages/guest_login.php:306 includes/view/User_view.php:78
-msgid "Shirt size"
-msgstr "T-Shirt GrΓΆΓe"
-
-#: includes/pages/guest_login.php:320
-msgid "What do you want to do?"
-msgstr "Was mΓΆchtest Du machen?"
-
-#: includes/pages/guest_login.php:323
-msgid "Description of job types"
-msgstr "Beschreibung der Aufgaben"
-
-#: includes/pages/guest_login.php:330
-msgid ""
-"Some angel types have to be confirmed later by a supporter at an "
-"introduction meeting. You can change your selection in the options section."
-msgstr ""
-"Engeltypen welche eine EinfΓΌhrung benΓΆtigen, werden bei einem EinfΓΌhrungstreffen von "
-"einem Supporter freigeschaltet. Du kannst Deine Auswahl spΓ€ter in den Einstellungen Γ€ndern."
-
-#: includes/pages/guest_login.php:339 includes/view/User_view.php:61
-msgid "Mobile"
-msgstr "Handy"
-
-#: includes/pages/guest_login.php:344 includes/view/User_view.php:45
-msgid "First name"
-msgstr "Vorname"
-
-#: includes/pages/guest_login.php:347 includes/view/User_view.php:44
-msgid "Last name"
-msgstr "Nachname"
-
-#: includes/pages/guest_login.php:350 includes/view/User_view.php:38
-msgid "Entry required!"
-msgstr "Pflichtfeld!"
-
-#: includes/pages/user_messages.php:49
-msgid "Select recipient..."
-msgstr "EmpfΓ€nger auswΓ€hlen..."
-
-#: includes/pages/user_messages.php:49
-msgid "Send"
-msgstr "Senden"
-
-#: includes/pages/user_messages.php:61 includes/pages/user_messages.php:75
-msgid "Y-m-d H:i"
+msgid "general.datetime"
msgstr "d.m.Y H:i"
-#: includes/pages/user_messages.php:98
-msgid "mark as read"
-msgstr "als gelesen markieren"
-
-#: includes/pages/user_messages.php:105
-msgid "delete message"
-msgstr "Nachricht lΓΆschen"
-
-#: includes/pages/user_messages.php:114
-#, php-format
-msgid "Hello %s, here can you leave messages for other angels"
-msgstr "Hallo %s, hier kannst Du anderen Engeln Nachrichten schreiben."
-
-#: includes/pages/user_messages.php:117
-msgid "New"
-msgstr "Neu"
-
-#: includes/pages/user_messages.php:119
-msgid "Transmitted"
-msgstr "Gesendet"
-
-#: includes/pages/user_messages.php:120
-msgid "Recipient"
-msgstr "EmpfΓ€nger"
-
-#: includes/pages/user_messages.php:132 includes/pages/user_messages.php:154
-msgid "Incomplete call, missing Message ID."
-msgstr "UnvollstΓ€ndiger Aufruf, fehlende Nachrichten ID."
-
-#: includes/pages/user_messages.php:146 includes/pages/user_messages.php:165
-msgid "No Message found."
-msgstr "Keine Nachricht gefunden."
-
-#: includes/pages/user_messages.php:173
-msgid "Transmitting was terminated with an Error."
-msgstr "Γbertragung wurde mit einem Fehler abgebrochen."
-
-#: includes/pages/user_messages.php:178
-msgid "Wrong action."
-msgstr "Falsche Aktion."
-
-#: includes/pages/user_myshifts.php:11 includes/view/Shifts_view.php:161
-msgid "My shifts"
-msgstr "Meine Schichten"
-
-#: includes/pages/user_myshifts.php:39
msgid "Key changed."
msgstr "Key geΓ€ndert."
-#: includes/pages/user_myshifts.php:42 includes/view/User_view.php:646
-#: includes/pages/user_myshifts.php:42 includes/pages/user_shifts.php:310
msgid "Reset API key"
msgstr "API-Key zurΓΌcksetzen"
-#: includes/pages/user_myshifts.php:44
msgid ""
"If you reset the key, the url to your iCal- and JSON-export and your atom/rss "
"feed changes! You have to update it in every application using one of these "
@@ -1730,74 +751,24 @@ msgstr ""
"Wenn du den API-Key zurΓΌcksetzt, Γ€ndert sich die URL zu deinem iCal-, JSON-"
"Export und Atom/RSS Feed! Du musst diesen ΓΌberall Γ€ndern, wo er in Benutzung ist."
-#: includes/pages/user_myshifts.php:47
msgid "Continue"
msgstr "Fortfahren"
-#: includes/pages/user_myshifts.php:86
msgid "Please enter a freeload comment!"
msgstr "Gib bitte einen SchwΓ€nz-Kommentar ein!"
-#: includes/pages/user_myshifts.php:111
msgid "Shift saved."
msgstr "Schicht gespeichert."
-#: includes/sys_menu.php:94
-msgid "News"
-msgstr "News"
-
-#: includes/sys_menu.php:95
-msgid "Meetings"
-msgstr "Treffen"
-
-#: includes/pages/user_questions.php:11 includes/sys_menu.php:98
-#: includes/view/Questions_view.php:40
msgid "Ask the Heaven"
msgstr "Frag den Himmel"
-#: includes/pages/user_questions.php:55
-msgid "You question was saved."
-msgstr "Frage gespeichert."
-
-#: includes/pages/user_questions.php:59
-msgid "Please enter a question!"
-msgstr "Gib eine Frage ein!"
+msgid "The administration has not configured any locations yet."
+msgstr "Die Administratoren habe noch keine Orte eingerichtet."
-#: includes/pages/user_questions.php:71
-msgid "Incomplete call, missing Question ID."
-msgstr "UnvollstΓ€ndiger Aufruf, fehlende Fragen ID."
-
-#: includes/pages/user_questions.php:86
-msgid "No question found."
-msgstr "Keine Frage gefunden."
-
-#: includes/sys_menu.php:69
-#: includes/view/User_view.php:616
-msgid "Settings"
-msgstr "Einstellungen"
-
-msgid ""
-"Please enter your planned date of departure. It should be after your planned "
-"arrival date and after buildup start date and before teardown end date."
-msgstr ""
-"Bitte gibt dein geplantes Abreisedatum an. Es sollte nach Deinem "
-"Anreisedatum, nach dem Aufbaubeginn und vor dem Abbauende liegen."
-
-msgid "-> not OK. Please try again."
-msgstr "-> Nicht OK. Bitte erneut versuchen."
-
-msgid "Your password is to short (please use at least 6 characters)."
-msgstr "Dein Passwort ist zu kurz (Bitte mindestens 6 Zeichen nutzen)."
-
-#: includes/pages/user_shifts.php:101
-msgid "The administration has not configured any rooms yet."
-msgstr "Die Administratoren habe noch keine RΓ€ume eingerichtet."
-
-#: includes/pages/user_shifts.php:120
msgid "The administration has not configured any shifts yet."
msgstr "Die Administratoren haben noch keine Schichten angelegt."
-#: includes/pages/user_shifts.php:137
msgid ""
"The administration has not configured any angeltypes yet - or you are not "
"subscribed to any angeltype."
@@ -1805,71 +776,51 @@ msgstr ""
"Die Administratoren haben noch keine Engeltypen konfiguriert - oder Du hast "
"noch keine Engeltypen ausgewΓ€hlt."
-#: includes/pages/user_shifts.php:204
msgid "occupied"
msgstr "belegt"
-#: includes/pages/user_shifts.php:208
msgid "free"
msgstr "frei"
-#: includes/pages/user_shifts.php:253
msgid "Own"
msgstr "Eigene"
-#: includes/pages/user_shifts.php:258
msgid "Occupancy"
msgstr "Belegung"
-#: includes/pages/user_shifts.php:261
msgid ""
"The tasks shown here are influenced by the angeltypes you joined already!"
msgstr ""
"Die Schichten, die hier angezeigt werden, sind von Deinen Einstellungen "
"(Engeltypen/Aufgaben) abhΓ€ngig!"
-#: includes/pages/user_shifts.php:263
-msgid "Description of the jobs."
-msgstr "Beschreibung der Aufgaben."
-
-#: includes/pages/user_shifts.php:267
msgid "Filter"
msgstr "Filter"
-#: includes/pages/user_shifts.php:268
msgid "Yesterday"
msgstr "Gestern"
-#: includes/pages/user_shifts.php:269
msgid "Today"
msgstr "Heute"
-#: includes/pages/user_shifts.php:270
msgid "Tomorrow"
msgstr "Morgen"
-#: includes/pages/user_shifts.php:271
msgid "last 8h"
msgstr "letzte 8h"
-#: includes/pages/user_shifts.php:272
msgid "last 4h"
msgstr "letzte 4h"
-#: includes/pages/user_shifts.php:273
msgid "next 4h"
msgstr "nΓ€chste 4h"
-#: includes/pages/user_shifts.php:274
msgid "next 8h"
msgstr "nΓ€chste 8h"
-#: includes/pages/user_shifts.php:292
msgid "iCal export and API"
msgstr "iCal Export und API"
-#: includes/pages/user_shifts.php:293
-#, php-format
msgid ""
"Export your own shifts. iCal format or JSON format available (please keep secret, otherwise JSON Format verfΓΌgbar (Link bitte geheimhalten, sonst API-Key zurΓΌcksetzen)."
-#: includes/pages/user_shifts.php:304
msgid "Show API Key"
msgstr "API Key anzeigen"
-#: includes/pages/user_shifts.php:327 includes/view/ShiftTypes_view.php:48
msgid "All"
msgstr "Alle"
-#: includes/pages/user_shifts.php:327
msgid "None"
msgstr "Keine"
-#: includes/sys_menu.php:78
-msgid "Logout"
-msgstr "Logout"
+msgid "general.logout"
+msgstr "Abmelden"
-#: includes/sys_menu.php:141
msgid "Admin"
msgstr "Admin"
-#: includes/sys_menu.php:163
-msgid "Manage rooms"
-msgstr "Verwalte RΓ€ume"
+msgid "Manage locations"
+msgstr "Orte verwalten"
-#: includes/sys_template.php:316
msgid "No data found."
msgstr "Nichts gefunden."
-#: includes/view/AngelTypes_view.php:40 includes/view/AngelTypes_view.php:454
msgid "Unconfirmed"
msgstr "UnbestΓ€tigt"
-#: includes/view/AngelTypes_view.php:42 includes/view/AngelTypes_view.php:46
msgid "Supporter"
msgstr "Supporter"
-#: includes/view/AngelTypes_view.php:44 includes/view/AngelTypes_view.php:48
msgid "Member"
msgstr "Mitglied"
-#: includes/view/AngelTypes_view.php:60
-#, php-format
msgid "Do you want to delete angeltype %s?"
msgstr "MΓΆchtest Du den Engeltypen %s lΓΆschen?"
-#: includes/view/AngelTypes_view.php:63 includes/view/ShiftEntry_view.php:27
-#: includes/view/ShiftEntry_view.php:56 includes/view/ShiftTypes_view.php:25
-#: includes/view/UserAngelTypes_view.php:27
-#: includes/view/UserAngelTypes_view.php:55
-#: includes/view/UserAngelTypes_view.php:74
-#: includes/view/UserAngelTypes_view.php:98
-#: includes/view/UserAngelTypes_view.php:122
-#: includes/view/UserAngelTypes_view.php:175
-msgid "cancel"
-msgstr "abbrechen"
-
-#: includes/view/AngelTypes_view.php:89 includes/view/AngelTypes_view.php:90
-#: includes/view/AngelTypes_view.php:505
-msgid "Requires introduction"
+msgid "angeltypes.restricted"
msgstr "BenΓΆtigt EinfΓΌhrung"
-#: includes/view/AngelTypes_view.php:93
-msgid ""
-"Angel types which require introduction can only be used by an angel if "
-"enabled by a supporter (double opt-in)."
+msgid "angeltypes.restricted.info"
msgstr ""
"Engeltypen, welche eine EinfΓΌhrung benΓΆtigen, mΓΌssen von einem Supporter freigeschaltet werden "
"(double-opt-in)."
-#: includes/view/AngelTypes_view.php:96 includes/view/AngelTypes_view.php:97
-msgid "No Self Sign Up allowed"
-msgstr "Kein Selbst-Eintragen erlaubt"
+msgid "shift.self_signup"
+msgstr "Schichten selbst eintragen"
+
+msgid "shift.self_signup.allowed"
+msgstr "Schichten selbst eintragen erlaubt"
+
+msgid "angeltypes.shift.self_signup.info"
+msgstr "Engeltypen, welche Schichten selbst eintragen erlaubt haben, "
+"erlauben Engeln sich selbst in ihre Schichten einzutragen, "
+"ist Schichten selbst eintragen nicht erlaubt kΓΆnnen nur Supporter "
+"oder Admins Engel in die Schichten des Engeltyps eintragen."
+
-#: includes/view/AngelTypes_view.php:99 includes/view/AngelTypes_view.php:105
msgid "Requires driver license"
msgstr "BenΓΆtigt FΓΌhrerschein"
-#: includes/view/AngelTypes_view.php:108 includes/view/AngelTypes_view.php:109
msgid "Show on dashboard"
msgstr "Auf dem Dashboard anzeigen"
-#: includes/view/AngelTypes_view.php:112 includes/view/AngelTypes_view.php:479
msgid "Contact"
msgstr "Kontakt"
-#: includes/view/AngelTypes_view.php:115
msgid "Primary contact person/desk for user questions."
msgstr "Ansprechpartner fΓΌr Fragen."
-#: includes/view/AngelTypes_view.php:145
msgid "my driving license"
msgstr "Meine FΓΌhrerschein-Infos"
-#: includes/view/AngelTypes_view.php:157
msgid ""
"This angeltype requires a driver license. Please enter your driver license "
"information!"
@@ -1980,8 +906,6 @@ msgstr ""
"Dieser Engeltyp benΓΆtigt FΓΌhrerschein-Infos. Bitte trage Deine FΓΌhrerschein-"
"Infos ein!"
-#: includes/view/AngelTypes_view.php:162
-#, php-format
msgid ""
"You are unconfirmed for this angeltype. Please go to the introduction for %s "
"to get confirmed."
@@ -1989,462 +913,222 @@ msgstr ""
"Du bist noch nicht fΓΌr diesen Engeltyp bestΓ€tigt. Bitte gehe zur EinfΓΌhrung "
"fΓΌr %s um bestΓ€tigt zu werden."
-#: includes/view/AngelTypes_view.php:224
-msgid "confirm"
-msgstr "bestΓ€tigen"
+msgid "Confirm"
+msgstr "BestΓ€tigen"
-#: includes/view/AngelTypes_view.php:232
-msgid "deny"
-msgstr "ablehnen"
+msgid "Deny"
+msgstr "Ablehnen"
-#: includes/view/AngelTypes_view.php:270
-msgid "remove"
-msgstr "entfernen"
+msgid "Remove"
+msgstr "Entfernen"
-#: includes/view/AngelTypes_view.php:300
msgid "Driver"
msgstr "Fahrer"
-#: includes/view/AngelTypes_view.php:301
msgid "Has car"
msgstr "Hat Auto"
-#: includes/view/AngelTypes_view.php:302
-#: includes/view/UserDriverLicenses_view.php:31
-msgid "Car"
-msgstr "Auto"
-
-#: includes/view/AngelTypes_view.php:303
-msgid "3,5t Transporter"
-msgstr "3,5t Transporter"
-
-#: includes/view/AngelTypes_view.php:304
-msgid "7,5t Truck"
-msgstr "7,5t LKW"
-
-#: includes/view/AngelTypes_view.php:305
-msgid "12t Truck"
-msgstr "12t LKW"
-
-#: includes/view/AngelTypes_view.php:306
-#: includes/view/UserDriverLicenses_view.php:49
-msgid "Forklift"
-msgstr "Gabelstapler"
-
-#: includes/view/AngelTypes_view.php:350
msgid "Info"
msgstr "Info"
-#: includes/view/AngelTypes_view.php:418
msgid "Supporters"
msgstr "Supporter"
-#: includes/view/AngelTypes_view.php:438
msgid "Members"
msgstr "Mitglieder"
-#: includes/view/AngelTypes_view.php:446
-#: includes/view/UserAngelTypes_view.php:154
msgid "Add"
msgstr "HinzufΓΌgen"
-#: includes/view/AngelTypes_view.php:458
-msgid "confirm all"
+msgid "Confirm all"
msgstr "Alle bestΓ€tigen"
-#: includes/view/AngelTypes_view.php:462
-msgid "deny all"
+msgid "Deny all"
msgstr "Alle ablehnen"
-#: includes/view/AngelTypes_view.php:499
-msgid "New angeltype"
-msgstr "Neuer Engeltyp"
-
-#: includes/view/AngelTypes_view.php:506
-msgid "Self Sign Up Allowed"
-msgstr "Selbst-Eintragen erlaubt"
-
-#: includes/view/AngelTypes_view.php:507
msgid "Membership"
msgstr "Mitgliedschaft"
-#: includes/view/AngelTypes_view.php:586
-msgid "FAQ"
-msgstr "FAQ"
-
-#: includes/view/EventConfig_view.php:91
msgid "Event Name"
msgstr "Event Name"
-#: includes/view/EventConfig_view.php:92
msgid "Event Name is shown on the start page."
msgstr "Event Name wird auf der Startseite angezeigt."
-#: includes/view/EventConfig_view.php:93
msgid "Event Welcome Message"
msgstr "Event Willkommens-Nachricht"
-#: includes/view/EventConfig_view.php:96
msgid ""
"Welcome message is shown after successful registration. You can use markdown."
msgstr ""
"Die Willkommens-Nachricht wird nach einer erfolgreichen Registrierung "
"angezeigt. Du kannst Markdown benutzen."
-#: includes/view/EventConfig_view.php:100
msgid "Buildup date"
msgstr "Aufbau Datum"
-#: includes/view/EventConfig_view.php:101
msgid "Event start date"
msgstr "Event Start Datum"
-#: includes/view/EventConfig_view.php:104
msgid "Teardown end date"
msgstr "Abbau Ende Datum"
-#: includes/view/EventConfig_view.php:105
msgid "Event end date"
msgstr "Event Ende Datum"
-#: includes/view/PublicDashboard_view.php:37
msgid "Angels needed in the next 3 hrs"
msgstr "BenΓΆtigte Engel in den nΓ€chsten 3 Stunden"
-#: includes/view/PublicDashboard_view.php:38
msgid "Angels needed for nightshifts"
msgstr "BenΓΆtigte Engel fΓΌr Nachtschichten"
-#: includes/view/PublicDashboard_view.php:39
msgid "Angels currently working"
msgstr "Aktuell arbeitende Engel"
-#: includes/view/PublicDashboard_view.php:40
msgid "Hours to be worked"
msgstr "Noch zu schaffende Stunden"
-#: includes/view/PublicDashboard_view.php:56
msgid "Fullscreen"
msgstr "Vollbild"
msgid "Filtered"
msgstr "Filtern"
-#: includes/view/Questions_view.php:28
-msgid "Open questions"
-msgstr "Offene Fragen"
-
-#: includes/view/Questions_view.php:42
-msgid "Your Question:"
-msgstr "Deine Frage:"
-
-#: includes/view/ShiftCalendarRenderer.php:146
msgid "No shifts found."
msgstr "Keine Schichten gefunden."
-#: includes/view/ShiftCalendarRenderer.php:246
-msgid "Time"
-msgstr "Zeit"
-
-#: includes/view/ShiftCalendarRenderer.php:312
msgid "Your shift"
msgstr "Meine Schicht"
-#: includes/view/ShiftCalendarRenderer.php:313
msgid "Help needed"
msgstr "Hilfe benΓΆtigt"
-#: includes/view/ShiftCalendarRenderer.php:314
msgid "Other angeltype needed / collides with my shifts"
msgstr "Andere Engeltypen benΓΆtigt / kollidiert mit meinen Schichten"
-#: includes/view/ShiftCalendarRenderer.php:315
msgid "Shift is full"
msgstr "Schicht ist voll"
-#: includes/view/ShiftCalendarRenderer.php:316
-msgid "Shift running/ended or user not arrived/allowed"
-msgstr ""
-"Schicht lΓ€uft/vorbei oder du bist noch nicht angekommen/darfst dich noch "
-"nicht anmelden"
+msgid "Shift is running/ended or you have not arrived"
+msgstr "Schicht lΓ€uft/vorbei oder du bist noch nicht angekommen"
-#: includes/view/ShiftCalendarShiftRenderer.php:135
msgid "Add more angels"
-msgstr "Neue Engel hinzufΓΌgen"
+msgstr "Mehr Engel hinzufΓΌgen"
-#: includes/view/ShiftCalendarShiftRenderer.php:180
-#, php-format
msgid "%d helper needed"
msgid_plural "%d helpers needed"
msgstr[0] "%d Helfer benΓΆtigt"
msgstr[1] "%d Helfer benΓΆtigt"
-#: includes/view/ShiftCalendarShiftRenderer.php:193
-#: includes/view/Shifts_view.php:85
msgid "Sign up"
msgstr "Eintragen"
-#: includes/view/ShiftCalendarShiftRenderer.php:199
msgid "ended"
msgstr "vorbei"
-# Wie ist dies zu verstehen bitte?
-#: includes/view/ShiftCalendarShiftRenderer.php:204
msgid "please arrive for signup"
msgstr "Ankommen zum Eintragen"
-#: includes/view/ShiftCalendarShiftRenderer.php:208
msgid "not yet"
msgstr "noch nicht"
-#: includes/view/ShiftCalendarShiftRenderer.php:223
-#: includes/view/Shifts_view.php:89
-#, php-format
msgid "Become %s"
msgstr "Werde ein %s"
-#: includes/view/ShiftCalenderRenderer.php:225
-#: includes/view/ShiftCalenderRenderer.php:232
msgid "m-d"
msgstr "d.m."
-#: includes/view/ShiftEntry_view.php:18
-#, php-format
msgid "Do you want to sign off %s from shift %s from %s to %s as %s?"
msgstr "MΓΆchtest Du %s von der Schicht %s von %s bis %s als %s austragen?"
-#: includes/view/ShiftEntry_view.php:47
-#, php-format
msgid "Do you want to sign off from your shift %s from %s to %s as %s?"
msgstr "MΓΆchtest du dich von deiner Schicht %s von %s bis %s als %s austragen?"
-#: includes/view/ShiftEntry_view.php:68
msgid "Shift sign off"
msgstr "Von Schicht austragen"
-#: includes/view/ShiftEntry_view.php:89
msgid "Do you want to sign up the following user for this shift?"
msgstr "MΓΆchtest du den folgenden User fΓΌr die Schicht eintragen?"
-#: includes/view/ShiftEntry_view.php:92 includes/view/ShiftEntry_view.php:117
-#: includes/view/UserAngelTypes_view.php:153
-msgid "User"
-msgstr "Benutzer"
-
-#: includes/view/ShiftEntry_view.php:114
-#, php-format
msgid "Do you want to sign up the following user for this shift as %s?"
msgstr "MΓΆchtest du den folgenden User als %s in die Schicht eintragen?"
-#: includes/view/ShiftEntry_view.php:138
-#, php-format
msgid "Do you want to sign up for this shift as %s?"
msgstr "MΓΆchtest du dich fΓΌr diese Schicht als %s eintragen?"
-#: includes/view/ShiftEntry_view.php:140 includes/view/ShiftEntry_view.php:192
msgid "Comment (for your eyes only):"
msgstr "Kommentar (nur fΓΌr Dich):"
-#: includes/view/ShiftEntry_view.php:151
msgid "Shift signup"
msgstr "Schicht Anmeldung"
-#: includes/view/ShiftEntry_view.php:182 includes/view/User_view.php:390
-#: includes/view/User_view.php:392
msgid "Freeloaded"
msgstr "GeschwΓ€nzt"
-#: includes/view/ShiftEntry_view.php:185
msgid "Freeload comment (Only for shift coordination):"
msgstr "SchwΓ€nzer Kommentar (Nur fΓΌr die Schicht-Koordination):"
-#: includes/view/ShiftEntry_view.php:197
msgid "Edit shift entry"
msgstr "Schichteintrag bearbeiten"
-#: includes/view/ShiftEntry_view.php:200
msgid "Angel:"
msgstr "Engel:"
-#: includes/view/ShiftEntry_view.php:201
msgid "Date, Duration:"
msgstr "Termin, Dauer:"
-#: includes/view/ShiftEntry_view.php:202
-msgid "Location:"
-msgstr "Ort:"
-
-#: includes/view/ShiftEntry_view.php:203
msgid "Title:"
msgstr "Titel:"
-#: includes/view/ShiftEntry_view.php:204
msgid "Type:"
msgstr "Typ:"
-#: includes/view/ShiftTypes_view.php:22
-#, php-format
-msgid "Do you want to delete shifttype %s?"
-msgstr "MΓΆchtest Du den Schichttypen %s lΓΆschen?"
-
-#: includes/view/ShiftTypes_view.php:54
-msgid "Edit shifttype"
-msgstr "Schichttyp bearbeiten"
-
-#: includes/view/ShiftTypes_view.php:54
-msgid "Create shifttype"
-msgstr "Schichttyp erstellen"
-
-#: includes/view/ShiftTypes_view.php:79
-#, php-format
-msgid "for team %s"
-msgstr "fΓΌr Team %s"
-
-#: includes/view/ShiftTypes_view.php:137
-msgid "New shifttype"
-msgstr "Neuer Schichttyp"
-
-#: includes/view/Shifts_view.php:42 includes/view/User_view.php:570
-msgid "Location"
-msgstr "Ort"
-
-#: includes/view/Shifts_view.php:57
-#, php-format
msgid "created at %s by %s"
msgstr "erstellt am %s von %s"
-#: includes/view/Shifts_view.php:64
-#, php-format
msgid "edited at %s by %s"
msgstr "bearbeitet am %s von %s"
-#: includes/view/Shifts_view.php:147
-#, php-format
+msgid "History ID: %s"
+msgstr "Historien-ID: %s"
+
msgid "This shift is in the far future and becomes available for signup at %s."
msgstr ""
"Diese Schicht liegt in der fernen Zukunft und du kannst dich ab %s eintragen."
-#: includes/view/UserAngelTypes_view.php:18
-#, php-format
msgid "Do you really want to add supporter rights for %s to %s?"
msgstr "Sollen %s %s als neuen Supporter bekommen?"
-#: includes/view/UserAngelTypes_view.php:19
-#, php-format
msgid "Do you really want to remove supporter rights for %s from %s?"
msgstr "MΓΆchtest Du wirklich %s von %s als Supporter befreien?"
-#: includes/view/UserAngelTypes_view.php:29
-#: includes/view/UserAngelTypes_view.php:57
-#: includes/view/UserAngelTypes_view.php:75
-#: includes/view/UserAngelTypes_view.php:99
-#: includes/view/UserAngelTypes_view.php:123
-msgid "yes"
-msgstr "Ja"
-
-#: includes/view/UserAngelTypes_view.php:47
-#, php-format
msgid "Do you really want to deny all users for %s?"
msgstr "MΓΆchtest Du wirklich alle Benutzer als %s ablehnen?"
-#: includes/view/UserAngelTypes_view.php:71
-#, php-format
msgid "Do you really want to confirm all users for %s?"
msgstr "MΓΆchtest Du wirklich alle Benutzer als %s bestΓ€tigen?"
-#: includes/view/UserAngelTypes_view.php:92
-#, php-format
msgid "Do you really want to confirm %s for %s?"
msgstr "MΓΆchtest Du wirklich %s fΓΌr %s bestΓ€tigen?"
-#: includes/view/UserAngelTypes_view.php:116
-#, php-format
msgid "Do you really want to delete %s from %s?"
msgstr "MΓΆchtest Du wirklich %s von %s entfernen?"
-#: includes/view/UserAngelTypes_view.php:169
-#, php-format
msgid "Do you really want to add %s to %s?"
msgstr "MΓΆchtest Du wirklich %s zu %s hinzufΓΌgen?"
+msgid "Do you want to become a %2$s?"
+msgstr "MΓΆchtest Du ein %2$s werden?"
+
msgid "Confirm user"
msgstr "Benutzer bestΓ€tigen"
msgid "Hide at Registration"
msgstr "Ausblenden bei Registrierung"
-#: includes/view/UserAngelTypes_view.php:176
-msgid "save"
-msgstr "Speichern"
-
-#: includes/view/UserDriverLicenses_view.php:17
msgid "Back to profile"
msgstr "ZurΓΌck zum Profil"
-#: includes/view/UserDriverLicenses_view.php:21
-msgid "Privacy"
-msgstr "PrivatsphΓ€re"
-
-#: includes/view/UserDriverLicenses_view.php:21
-msgid ""
-"Your driving license information is only visible for supporters and admins."
-msgstr "Deine FΓΌhrerschein-Infos sind nur fΓΌr Supporter und Admins sichtbar."
-
-#: includes/view/UserDriverLicenses_view.php:22
-msgid "I am willing to drive a car for the event"
-msgstr "Ich mΓΆchte fΓΌr das Event Auto fahren"
-
-#: includes/view/UserDriverLicenses_view.php:27
-msgid ""
-"I have my own car with me and am willing to use it for the event (You'll get "
-"reimbursed for fuel)"
-msgstr ""
-"Ich habe mein eigenes Auto dabei und mΓΆchte es zum Fahren fΓΌr das Event "
-"verwenden (Du wirst fΓΌr Spritkosten entschΓ€digt)"
-
-#: includes/view/UserDriverLicenses_view.php:30
-msgid "Driver license"
-msgstr "FΓΌhrerschein"
-
-#: includes/view/UserDriverLicenses_view.php:34
-msgid "Transporter 3,5t"
-msgstr "3,5t Transporter"
-
-#: includes/view/UserDriverLicenses_view.php:39
-msgid "Truck 7,5t"
-msgstr "7,5t LKW"
-
-#: includes/view/UserDriverLicenses_view.php:44
-msgid "Truck 12t"
-msgstr "12t LKW"
-
-#, php-format
-msgid "Do you want to delete the worklog entry for %s?"
-msgstr "MΓΆchtest du den Arbeitseinsatz von %s wirklich lΓΆschen?"
-
-#: includes/view/User_view.php:572
-msgid "Comment"
-msgstr "Kommentar"
-
-msgid "Pronoun"
-msgstr "Pronomen"
-
-msgid "Will be shown on your profile page and in angel lists."
-msgstr "Wird auf deiner Profilseite und in Engellisten angezeigt."
-
-#: includes/view/User_view.php:37
-msgid "Here you can change your user details."
-msgstr "Hier kannst Du Deine Details Γ€ndern."
-
-#: includes/view/User_view.php:55
-msgid "Planned date of departure"
-msgstr "Geplanter Abreisetag"
-
-#: includes/view/User_view.php:83
-msgid "You can manage your Angeltypes on the Angeltypes page."
-msgstr "Du kannst deine Engeltypen auf der Engeltypen-Seite verwalten."
-
-#: includes/view/User_view.php:124
msgid ""
"Do you really want to delete the user including all his shifts and every "
"other piece of his data?"
@@ -2452,144 +1136,84 @@ msgstr ""
"MΓΆchtest Du wirklich den Engel inklusive aller seiner Schichten und allen "
"anderen seiner Daten lΓΆschen?"
-#: includes/view/User_view.php:128
msgid "Your password"
msgstr "Dein Passwort"
-#: includes/view/User_view.php:148
-#, php-format
msgid "Angel can receive another %d vouchers."
msgstr "Engel kann noch %d Gutscheine bekommen."
-#: includes/view/User_view.php:148
-#, php-format
msgid "Angel can receive another %d vouchers and is FA."
msgstr "Engel kann noch %d Gutscheine bekommen und ist FA."
-#: includes/view/User_view.php:153
msgid "Number of vouchers given out"
msgstr "Anzahl Gutscheine bekommen"
-#: includes/view/User_view.php:221
-msgid "Prename"
-msgstr "Vorname"
-
-#: includes/view/User_view.php:227 includes/view/User_view.php:697
-msgid "Arrived"
-msgstr "Angekommen"
-
-#: includes/view/User_view.php:228
msgid "Voucher"
msgstr "Gutschein"
-#: includes/view/User_view.php:229
msgid "Freeloads"
msgstr "SchwΓ€nzereien"
-#: includes/view/User_view.php:230 includes/view/User_view.php:734
-msgid "Active"
-msgstr "Aktiv"
-
-#: includes/view/User_view.php:232 includes/view/User_view.php:737
-msgid "T-Shirt"
+msgid "T-shirt"
msgstr "T-Shirt"
-#: includes/view/User_view.php:244
msgid "Last login"
msgstr "Letzter Login"
-#: includes/view/User_view.php:250
-msgid "New user"
-msgstr "Neuer User"
-
-#: includes/view/User_view.php:283
-msgid "Free"
-msgstr "Frei"
-
-#: includes/view/User_view.php:291 includes/view/User_view.php:295
-#, php-format
msgid "Next shift %c"
msgstr "NΓ€chste Schicht %c"
-#: includes/view/User_view.php:302
-#, php-format
msgid "Shift started %c"
msgstr "Schicht startete %c"
-#: includes/view/User_view.php:307
-#, php-format
msgid "Shift ends %c"
msgstr "Schicht endet %c"
-#: includes/view/User_view.php:324
-#, php-format
msgid "Shift ended %c"
msgstr "Schicht endete %c"
-#: includes/view/User_view.php:409
-msgid "sign off"
-msgstr "austragen"
+msgid "Sign off"
+msgstr "Austragen"
-#: includes/view/User_view.php:461
msgid "Sum:"
msgstr "Summe:"
-#: includes/view/User_view.php:470
-msgid "Your t-shirt score"
-msgstr "Dein T-Shirt Score"
+msgid "T-shirt score"
+msgstr "T-Shirt Score"
-#: includes/view/User_view.php:511
msgid "Work log entry"
msgstr "Arbeitseinsatz"
-#: includes/view/User_view.php:514
-#, php-format
msgid "Added by %s at %s"
msgstr "Erstellt von %s am %s"
-#: includes/view/User_view.php:568
-msgid "Day & time"
-msgstr "Tag & Zeit"
+msgid "Day & Time"
+msgstr "Tag & Zeit"
-#: includes/view/User_view.php:569
msgid "Duration"
msgstr "Dauer"
-#: includes/view/User_view.php:571
-msgid "Name & workmates"
-msgstr "Name & Kollegen"
-
-#: includes/view/User_view.php:573
-msgid "Action"
-msgstr "Aktion"
+msgid "Name & Workmates"
+msgstr "Name & Kollegen"
-#: includes/view/User_view.php:576
msgid "You have done enough."
msgstr "Du hast genug gemacht."
-#: includes/view/User_view.php:595
-msgid "driving license"
-msgstr "FΓΌhrerschein"
+msgid "%s has done enough."
+msgstr "%s hat genug gemacht."
-#: includes/view/User_view.php:608
msgid "Vouchers"
msgstr "Gutscheine"
-#: includes/view/User_view.php:620
msgid "iCal Export"
msgstr "iCal Export"
-#: includes/view/User_view.php:624
msgid "JSON Export"
msgstr "JSON Export"
-#: includes/view/User_view.php:645
-#, php-format
-msgid "Your night shifts between %d and %d am count twice."
-msgstr "Deine Nachtschichten zwischen %d und %d Uhr zΓ€hlen doppelt."
+msgid "Your night shifts between %d and %d am count twice for the %s score."
+msgstr "Deine Nachtschichten zwischen %d und %d Uhr zΓ€hlen fΓΌr den %s Score doppelt."
-#: includes/view/User_view.php:653
-#, php-format
msgid ""
"Go to the shifts table to sign yourself up for some "
"shifts."
@@ -2597,53 +1221,40 @@ msgstr ""
"Gehe zur Schicht-Tabelle, um Dich fΓΌr Schichten "
"einzutragen."
-#: includes/view/User_view.php:679
-msgid "User state"
-msgstr "Engelzustand"
+msgid "State"
+msgstr "Status"
-#: includes/view/User_view.php:699
msgid "Not arrived"
msgstr "Nicht angekommen"
-#: includes/view/User_view.php:718
msgid "Freeloader"
msgstr "SchwΓ€nzer"
-#: includes/view/User_view.php:726
-#, php-format
msgid "Arrived at %s"
msgstr "Angekommen am %s"
-#: includes/view/User_view.php:732
-msgid "Active (forced)"
-msgstr "Aktiv (erzwungen)"
-
-#: includes/view/User_view.php:743
-#, php-format
msgid "Not arrived (Planned: %s)"
msgstr "Nicht angekommen (Geplant: %s)"
-#: includes/view/User_view.php:753
-#, php-format
msgid "Got %s of %s vouchers"
msgstr "%s von %s Gutscheinen bekommen"
-#: includes/view/User_view.php:756
msgid "Got no vouchers"
msgstr "Keine Gutscheine bekommen"
msgid "out of %s"
msgstr "von %s"
-#: includes/view/User_view.php:89
-msgid "Show mobile number to other users to contact me"
-msgstr "Mache meine Handynummer fΓΌr andere Benutzer sichtbar"
-
-#: includes/view/User_view.php:797
msgid "Rights"
-msgstr "Rechte"
+msgstr "Berechtigungen"
+
+msgid ""
+"You are not marked as arrived. Please go to heaven, get your angel "
+"badge and/or tell them that you arrived already."
+msgstr ""
+"Du bist nicht als angekommen markiert. Geh bitte zum Himmel, "
+"hole Dein Badge ab und/oder melde dich als angekommen."
-#: includes/view/User_view.php:853
msgid ""
"Please enter your planned date of departure on your settings page to give us "
"a feeling for teardown capacities."
@@ -2651,8 +1262,6 @@ msgstr ""
"Bitte gib Dein geplantes Abreisedatum an, damit wir ein GefΓΌhl fΓΌr die Abbau-"
"Planung bekommen."
-#: includes/view/User_view.php:867
-#, php-format
msgid ""
"You freeloaded at least %s shifts. Shift signup is locked. Please go to "
"heavens desk to be unlocked again."
@@ -2660,25 +1269,25 @@ msgstr ""
"Du hast mindestens %s Schichten geschwΓ€nzt. Schicht-Registrierung ist "
"gesperrt. Bitte gehe zum Himmelsschreibtisch um wieder entsperrt zu werden."
-#: includes/view/User_view.php:886
-msgid ""
-"You are not marked as arrived. Please go to heaven's desk, get your angel "
-"badge and/or tell them that you arrived already."
+msgid "tshirt.required.hint"
+msgstr "Bitte gib eine T-Shirt-GrΓΆΓe in deinen Einstellungen an."
+
+msgid "dect.required.hint"
msgstr ""
-"Du bist nicht als angekommen markiert. Bitte gehe zur Himmelsverwaltung, "
-"hole Dein Badge ab und/oder erklΓ€re ihnen, dass Du bereits angekommen bist."
+"Bitte gib eine DECT-Telefonnummer in deinen Einstellungen an. Wenn du "
+"keine Nummer hast, trage einfach '-' ein."
-#: includes/view/User_view.php:899
-msgid "You need to specify a tshirt size in your settings!"
-msgstr "Bitte eine T-Shirt-GrΓΆΓe auswΓ€hlen"
+msgid "pronoun.required.hint"
+msgstr "Bitte gib ein Pronomen in deinen Einstellungen an."
-#: includes/view/User_view.php:913
-msgid ""
-"You need to specify a DECT phone number in your settings! If you don't have "
-"a DECT phone, just enter '-'."
-msgstr ""
-"Bitte eine DECT-Telefonnummer in den Einstellungen eingeben. Wenn du noch "
-"keine Nummer hast, bitte einfach \"-\" angeben."
+msgid "firstname.required.hint"
+msgstr "Bitte gib einen Vornamen in deinen Einstellungen an."
+
+msgid "lastname.required.hint"
+msgstr "Bitte gib einen Nachnamen in deinen Einstellungen an."
+
+msgid "mobile.required.hint"
+msgstr "Bitte gib eine Handynummer in deinen Einstellungen an."
msgid ""
"Here you can change the user entry. Under the item 'Arrived' the angel is marked as present, "
@@ -2693,16 +1302,6 @@ msgstr ""
"Ist der Engel Aktiv, hat er damit Anspruch auf ein T-Shirt. Wenn T-Shirt ein 'Ja' enthΓ€lt, bedeutet dies, "
"dass der Engel bereits sein T-Shirt erhalten hat."
-msgid ""
-"If the angel was Active, this entitles him to a T-shirt. If T-shirt contains a 'Ja', "
-"it means that the angel has already received his T-shirt."
-msgstr ""
-"War der Engel Aktiv, hat er damit Anspruch auf ein T-Shirt. Wenn T-Shirt ein 'Ja' enthΓ€lt, "
-"bedeutet dies, dass der Engel bereits sein T-Shirt erhalten hat."
-
-msgid "Please visit the angeltypes page or the users profile to manage the users angeltypes."
-msgstr "Bitte besuche die Seite Engeltypen oder das Benutzerprofil, um die Engeltypen des Benutzers zu verwalten."
-
msgid "Here you can reset the password of this angel:"
msgstr "Hier kannst du das Passwort fΓΌr diesen Engel zurΓΌcksetzen:"
@@ -2718,7 +1317,7 @@ msgstr "Du kannst keine Engel mit mehr Rechten bearbeiten."
msgid "You cannot edit your own rights."
msgstr "Du kannst deine eigenen Rechte nicht bearbeiten."
-msgid "Changes where saved."
+msgid "Changes were saved."
msgstr "Γnderung wurde gespeichert."
msgid "Password reset done."
@@ -2730,6 +1329,9 @@ msgstr "Die EintrΓ€ge mΓΌssen ΓΌbereinstimmen und dΓΌrfen nicht leer sein!"
msgid "Number of shifts: %s"
msgstr "Anzahl an Schichten: %s"
+msgid "Shifts created."
+msgstr "Schichten erstellt."
+
msgid "If the angel is active, it can claim a goodie. If goodie is set to 'Yes', the angel already got their goodie."
msgstr "Ist der Engel Aktiv, hat er damit Anspruch auf ein Goodie. Wenn Goodie ein 'Ja' enthΓ€lt, bedeutet dies, "
"dass der Engel bereits sein Goodie erhalten hat."
@@ -2737,8 +1339,11 @@ msgstr "Ist der Engel Aktiv, hat er damit Anspruch auf ein Goodie. Wenn Goodie e
msgid "Goodie"
msgstr "Goodie"
-msgid "Your goodie score"
-msgstr "Dein Goodie Score"
+msgid "goodie"
+msgstr "Goodie"
+
+msgid "Goodie score"
+msgstr "Goodie Score"
msgid "Given goodies"
msgstr "Ausgegebene Goodies"
@@ -2746,10 +1351,10 @@ msgstr "Ausgegebene Goodies"
msgid "Goodie statistic"
msgstr "Goodie Statistik"
-msgid "remove goodie"
-msgstr "entferne Goodie"
+msgid "Remove goodie"
+msgstr "Goodie entfernen"
-msgid "got goodie"
+msgid "Got goodie"
msgstr "Goodie bekommen"
msgid "Goodie?"
@@ -2761,32 +1366,13 @@ msgstr "Engel hat ein Goodie bekommen."
msgid "Angel has got no goodie."
msgstr "Engel hat kein Goodie bekommen."
-#: src/Middleware/LegacyMiddleware.php:83
msgid "page.404.text"
msgstr ""
"Diese Seite existiert nicht oder Du hast keinen Zugriff. Melde Dich an um "
"Zugriff zu erhalten!"
-#~ msgid "Token is not correct."
-#~ msgstr "Der Token ist nicht in Ordnung."
-
-#~ msgid "Needed shirts"
-#~ msgstr "BenΓΆtigte T-Shirts"
-
-#~ msgid "Only confirmed"
-#~ msgstr "Nur bestΓ€tigte"
-
-#~ msgid "Registration successful"
-#~ msgstr "Registrierung erfolgreich"
-
-#~ msgid "Please enter a new password."
-#~ msgstr "Gib bitte ein neues Passwort ein."
-
-#~ msgid "auth.no-password"
-#~ msgstr "Gib bitte ein Passwort ein."
-
-#~ msgid "auth.no-nickname"
-#~ msgstr "Gib bitte einen Nick an."
+msgid "form.select_placeholder"
+msgstr "Bitte auswΓ€hlen..."
msgid "form.load_schedule"
msgstr "Programm laden"
@@ -2806,6 +1392,9 @@ msgstr "Vorschau"
msgid "form.delete"
msgstr "LΓΆschen"
+msgid "form.delete_all"
+msgstr "Alle lΓΆschen"
+
msgid "form.updated"
msgstr "Aktualisiert"
@@ -2818,12 +1407,18 @@ msgstr "Du kannst hier Markdown verwenden"
msgid "form.required"
msgstr "Pflichtfeld"
+msgid "form.user_select"
+msgstr "WΓ€hle einen User"
+
msgid "schedule.import"
msgstr "Programm importieren"
msgid "schedule.edit.title"
msgstr "Programm bearbeiten"
+msgid "schedule.delete.title"
+msgstr "Programm mit %u Schichten lΓΆschen"
+
msgid "schedule.import.title"
msgstr "Programm importieren"
@@ -2832,7 +1427,7 @@ msgstr "Aktualisiert am: %s"
msgid "schedule.import.text"
msgstr ""
-"Importe erstellen RΓ€ume und erstellen, aktualisieren und lΓΆschen Schichten anhand eines schedule.xml exportes."
+"Importe erstellen Orte und erstellen, aktualisieren und lΓΆschen Schichten anhand eines schedule.xml exportes."
msgid "schedule.import.load.title"
msgstr "Programm importieren: Vorschau"
@@ -2849,14 +1444,20 @@ msgstr "Programm URL (schedule.xml)"
msgid "schedule.shift-type"
msgstr "Schichttyp"
+msgid "schedule.needed-from-shift-type"
+msgstr "Engeltypen vom Schichttyp laden (sonst vom Ort)"
+
msgid "schedule.minutes-before"
msgstr "Minuten vor Talk beginn hinzufΓΌgen"
msgid "schedule.minutes-after"
msgstr "Minuten nach Talk ende hinzufΓΌgen"
-msgid "schedule.import.rooms.add"
-msgstr "Neue RΓ€ume"
+msgid "schedule.for_locations"
+msgstr "FΓΌr Orte"
+
+msgid "schedule.import.locations.add"
+msgstr "Neue Orte"
msgid "schedule.import.shifts.add"
msgstr "Neue Schichten"
@@ -2867,23 +1468,14 @@ msgstr "Zu aktualisierende Schichten"
msgid "schedule.import.shifts.delete"
msgstr "Zu lΓΆschende Schichten"
-msgid "schedule.import.rooms.name"
-msgstr "Name"
-
msgid "schedule.import.shift.dates"
msgstr "Zeit"
msgid "schedule.import.shift.type"
msgstr "Typ"
-msgid "schedule.import.shift.title"
-msgstr "Titel"
-
-msgid "schedule.import.shift.room"
-msgstr "Raum"
-
-msgid "shifts_history.schedule"
-msgstr "Programm: %s"
+msgid "schedule.import.shift.location"
+msgstr "Ort"
msgid "news.title"
msgstr "News"
@@ -2897,8 +1489,8 @@ msgstr "+"
msgid "news.is_meeting"
msgstr "[Treffen]"
-msgid "news.edit.is_important"
-msgstr "Wichtig"
+msgid "news.edit.is_highlighted"
+msgstr "Hervorgehoben"
msgid "news.read_more"
msgstr "Weiterlesen"
@@ -2936,12 +1528,27 @@ msgstr "Nachricht"
msgid "news.edit.hint"
msgstr "Du kannst Markdown und den [more] Tag benutzen"
+msgid "news.delete.title"
+msgstr "News \"%s\" lΓΆschen"
+
+msgid "news.comments.delete.title"
+msgstr "Kommentar \"%s\" lΓΆschen"
+
+msgid "notification.news.updated.introduction"
+msgstr "Die News %1$s wurde aktualisiert"
+
+msgid "notification.news.updated.text"
+msgstr "Du kannst sie dir unter %3$s anschauen."
+
msgid "form.search"
msgstr "Suchen"
msgid "log.log"
msgstr "Logs"
+msgid "log.only_own"
+msgstr "Du siehst hier deine eigenen Logs. Die logs anderer User kΓΆnnen nur BΓΌrokraten sehen."
+
msgid "log.time"
msgstr "Zeit"
@@ -2954,15 +1561,15 @@ msgstr "Nachricht"
msgid "settings.settings"
msgstr "Einstellungen"
-msgid "settings.profile.user_details.info"
-msgstr "Hier kannst Du Deine Details Γ€ndern."
-
msgid "settings.profile.entry_required"
-msgstr "Pflichtfeld!"
+msgstr "Pflichtfeld"
-msgid "settings.profile.nick"
+msgid "general.nick"
msgstr "Nick"
+msgid "settings.profile.nick.already-taken"
+msgstr "Der Nick ist bereits vergeben."
+
msgid "settings.profile.pronoun"
msgstr "Pronomen"
@@ -2981,18 +1588,21 @@ msgstr "Geplanter Ankunftstag"
msgid "settings.profile.planned_departure_date"
msgstr "Geplanter Abreisetag"
-msgid "settings.profile.dect"
-msgstr "DECT"
-
msgid "settings.profile.mobile"
msgstr "Handy"
msgid "settings.profile.mobile_show"
msgstr "Mache meine Handynummer fΓΌr andere Benutzer sichtbar."
-msgid "settings.profile.email"
+msgid "settings.profile.email-preferences"
+msgstr "E-Mail Einstellungen"
+
+msgid "general.email"
msgstr "E-Mail"
+msgid "settings.profile.email.already-taken"
+msgstr "Diese E-Mail-Adresse ist bereits vergeben."
+
msgid "settings.profile.email_shiftinfo"
msgstr "Das %s darf mir E-Mails senden (z.B. wenn sich meine Schichten Γ€ndern)."
@@ -3003,11 +1613,11 @@ msgid "settings.profile.email_messages"
msgstr "Benachrichtige mich bei neuen privaten Nachrichten."
msgid "settings.profile.email_by_human_allowed"
-msgstr "Erlaube Himmel-Engeln dich per Mail zu kontaktieren."
+msgstr "Erlaube Himmel-Engeln mich per E-Mail zu kontaktieren."
msgid "settings.profile.email_goody"
-msgstr "Um Voucher zu erhalten, stimme zu, dass Nick, E-Mail-Adresse, geleistete Arbeit und ShirtgrΓΆΓe "
-"bis zum nΓ€chsten gleichartigen Event gespeichert werden."
+msgstr "Um gegebenenfalls Voucher fΓΌr das nΓ€chste gleichartige Event zu erhalten stimme ich zu, "
+"dass mein Nick, E-Mail-Adresse, geleistete Arbeit und T-Shirt-GrΓΆΓe solange gespeichert werden."
msgid "settings.profile.privacy"
msgstr "Dies kann jederzeit durch eine E-Mail an %1$s widerrufen werden."
@@ -3024,6 +1634,9 @@ msgstr "Passwort"
msgid "settings.password.info"
msgstr "Hier kannst Du Dein Passwort Γ€ndern."
+msgid "settings.password.confirmation-does-not-match"
+msgstr "Passwort und Passwortwiederholung stimmen nicht ΓΌberein."
+
msgid "settings.password.password"
msgstr "Altes Passwort"
@@ -3036,6 +1649,21 @@ msgstr "Passwort wiederholen"
msgid "settings.password.success"
msgstr "Passwort wurde erfolgreich geΓ€ndert."
+msgid "settings.sessions"
+msgstr "Sitzungen"
+
+msgid "settings.sessions.info"
+msgstr "Hier kannst Du deine Bowser-Sitzungen sehen und lΓΆschen."
+
+msgid "settings.sessions.current"
+msgstr "Aktuelle Sitzung"
+
+msgid "settings.sessions.id"
+msgstr "Sitzungs-ID"
+
+msgid "settings.sessions.last_activity"
+msgstr "Zuletzt verwendet"
+
msgid "settings.theme"
msgstr "Theme"
@@ -3045,6 +1673,79 @@ msgstr "Hier kannst Du Dein Theme Γ€ndern."
msgid "settings.theme.success"
msgstr "Theme wurde erfolgreich geΓ€ndert."
+msgid "settings.certificates"
+msgstr "Zertifikate"
+
+msgid "settings.certificates.info"
+msgstr "Diese Informationen sind nur fΓΌr Supporter und Admins sichtbar."
+
+msgid "settings.certificates.title.ifsg"
+msgstr "Gesundheitsbelehrungen"
+
+msgid "settings.certificates.driving_license"
+msgstr "FΓΌhrerschein"
+
+msgid "settings.certificates.has_car"
+msgstr ""
+"Ich habe mein eigenes Auto dabei und mΓΆchte es zum Fahren fΓΌr das Event "
+"verwenden (Du wirst fΓΌr Spritkosten entschΓ€digt)"
+
+msgid "settings.certificates.drive_car"
+msgstr "Auto"
+
+msgid "settings.certificates.drive_3_5t"
+msgstr "3,5t Transporter"
+
+msgid "settings.certificates.drive_7_5t"
+msgstr "7,5t LKW"
+
+msgid "settings.certificates.drive_12t"
+msgstr "12t LKW"
+
+msgid "settings.certificates.drive_forklift"
+msgstr "Gabelstapler"
+
+msgid "settings.certificates.ifsg_light"
+msgstr "Ich wurde vor Ort nach IfSG Β§43 (Frikadellendiplom light) belehrt."
+
+msgid "settings.certificates.ifsg"
+msgstr "Ich habe eine Belehrung nach Β§43 IfSG (Frikadellendiplom) bei meinem Gesundheitsamt "
+"erhalten und innerhalb von 3 Monaten die Zweitbelehrung durch uns oder meinen Arbeitgeber/Koch/Verein bekommen. "
+"ZusΓ€tzlich ist die Zweitbelehrung nicht Γ€lter als zwei Jahre."
+
+msgid "settings.certificates.success"
+msgstr "Zertifikate wurden erfolgreich aktualisiert."
+
+msgid "angeltype.ifsg.required"
+msgstr "BenΓΆtigt eine Gesundheitsbelehrung"
+
+msgid "ifsg.certificate"
+msgstr "Gesundheitsbelehrung"
+
+msgid "ifsg.certificate_light"
+msgstr "Gesundheitsbelehrung vor Ort"
+
+msgid "angeltype.ifsg.own"
+msgstr "Meine Gesundheitsbelehrung"
+
+msgid "angeltype.ifsg.required.info"
+msgstr "Dieser Engeltyp benΓΆtigt eine Gesundheitsbelehrung. Bitte trage deine Gesundheitsbelehrung ein!"
+
+msgid "angeltype.ifsg.required.info.here"
+msgstr "Dieser Engeltyp benΓΆtigt eine Gesundheitsbelehrung. "
+"Bitte trage deine Gesundheitsbelehrung hier ein: %s"
+
+msgid "angeltype.driving_license.required.info.here"
+msgstr ""
+"Du bist einem Engeltypen beigetreten, der FΓΌhrerschein-Infos benΓΆtigt. "
+"Bitte trage Deine FΓΌhrerschein-Infos hier ein: %s."
+
+msgid "ifsg.info"
+msgstr "Gesundheitsbelehrungs-Infos"
+
+msgid "driving_license.info"
+msgstr "FΓΌhrerschein-Infos"
+
msgid "settings.language"
msgstr "Sprache"
@@ -3054,6 +1755,35 @@ msgstr "Hier kannst Du Deine Sprache Γ€ndern."
msgid "settings.language.success"
msgstr "Sprache wurde erfolgreich geΓ€ndert."
+msgid "settings.api"
+msgstr "API"
+
+msgid "settings.api.about"
+msgstr ""
+"Die API erlaubt es dir, ΓΌber externe Programme, mit dem Engelsystem zu interagieren. "
+"Sie ist noch nicht vollstΓ€ndig, wir arbeiten aber daran sie zu erweitern.\n"
+"Der API Einstiegspunkt befindet sich unter `%s` und ist in der [OpenAPI Spezifikation](%s) beschrieben.\n"
+"Teile deinen persΓΆnlichen API Key mit niemandem, er erlaubt es deine persΓΆnlichen Daten einzusehen "
+"und Γnderungen in deinem Namen durch zu fΓΌhren!"
+
+msgid "settings.api.shifts_json_show"
+msgstr "JSON Schichten Export anzeigen"
+
+msgid "settings.api.ical_show"
+msgstr "iCal export anzeigen"
+
+msgid "settings.api.news_show"
+msgstr "News feeds anzeigen"
+
+msgid "settings.api.key_show"
+msgstr "API Key anzeigen"
+
+msgid "settings.api.key_reset"
+msgstr "API Key zurΓΌcksetzen"
+
+msgid "settings.api.key_reset_confirm"
+msgstr "Wenn du den API Key zurΓΌcksetzt, musst ihn in allen deinen Anwendungen aktualisieren."
+
msgid "settings.oauth"
msgstr "Single Sign-On"
@@ -3090,6 +1820,9 @@ msgstr "Frage"
msgid "faq.message"
msgstr "Antwort"
+msgid "faq.delete.title"
+msgstr "FAQ \"%s\" lΓΆschen"
+
msgid "question.questions"
msgstr "Fragen"
@@ -3108,17 +1841,20 @@ msgstr "Frage"
msgid "question.answer"
msgstr "Antwort"
+msgid "question.delete.title"
+msgstr "Frage \"%s\" lΓΆschen"
+
msgid "user.edit.shirt"
-msgstr "Shirt bearbeiten"
+msgstr "T-Shirt bearbeiten"
msgid "user.edit.goodie"
msgstr "Goodie bearbeiten"
msgid "form.shirt"
-msgstr "Shirt"
+msgstr "T-Shirt"
msgid "user.shirt_size"
-msgstr "Shirt grΓΆΓe"
+msgstr "T-Shirt grΓΆΓe"
msgid "user.active"
msgstr "Aktiv"
@@ -3129,8 +1865,11 @@ msgstr "Aktiv (erzwungen)"
msgid "user.arrived"
msgstr "Angekommen"
+msgid "user.arrive"
+msgstr "Ankommen"
+
msgid "user.got_shirt"
-msgstr "Shirt bekommen"
+msgstr "T-Shirt bekommen"
msgid "user.got_goodie"
msgstr "Goodie bekommen"
@@ -3147,12 +1886,9 @@ msgstr "Zur Konversation"
msgid "message.message"
msgstr "Nachricht"
-msgid "angel"
+msgid "general.angel"
msgstr "Engel"
-msgid "date"
-msgstr "Datum"
-
msgid "worklog.add"
msgstr "Arbeitseinsatz hinzufΓΌgen"
@@ -3187,41 +1923,144 @@ msgid "angeltypes.restricted.hint"
msgstr "Dieser Engeltyp benΓΆtigt eine Einweisung bei einem EinfΓΌhrungstreffen. "
"Weitere Informationen findest du mΓΆglicherweise in der Beschreibung."
-msgid "angeltypes.name"
-msgstr "Name"
-
-msgid "angeltypes.dect"
-msgstr "DECT"
+msgid "angeltypes.can-change-later"
+msgstr "Du kannst Deine Auswahl spΓ€ter in den Einstellungen Γ€ndern."
msgid "angeltypes.email"
msgstr "E-Mail"
+msgid "angeltypes.hide_on_shift_view"
+msgstr "Auf Schicht-Ansicht ausblenden"
+
+msgid "angeltypes.hide_on_shift_view.info"
+msgstr "Wenn ausgewΓ€hlt, kΓΆnnen nur Admins und Mitglieder des Engeltyps auf der "
+"Schicht Seite die Filteroption fΓΌr diesen Engeltyp sehen."
+
+msgid "location.location"
+msgstr "Ort"
+
+msgid "location.locations"
+msgstr "Orte"
+
+msgid "location.map_url"
+msgstr "Karte"
+
+msgid "location.required_angels"
+msgstr "BenΓΆtigte Engel (bei Fahrplan import)"
+
+msgid "location.map_url.info"
+msgstr "Die Karte wird auf der Ort-Seite als iframe eingebettet."
+
+msgid "location.create.title"
+msgstr "Ort erstellen"
+
+msgid "location.edit.title"
+msgstr "Ort bearbeiten"
+
+msgid "location.delete.title"
+msgstr "Ort \"%s\" lΓΆschen"
+
+msgid "shifttype.shifttypes"
+msgstr "Schichttypen"
+
+msgid "shifttype.edit.title"
+msgstr "Schichttyp bearbeiten"
+
+msgid "shifttype.create.title"
+msgstr "Schichttyp erstellen"
+
+msgid "shifttype.delete.title"
+msgstr "Schichttyp \"%s\" lΓΆschen"
+
+msgid "shifttype.required_angels"
+msgstr "BenΓΆtigte Engel (bei Fahrplan import)"
+
+msgid "event.day"
+msgstr "Tag %1$d"
+
+msgid "dashboard.day"
+msgstr "Tag"
+
+msgid "registration.title"
+msgstr "Engel-Registrierung"
+
+msgid "registration.login_data"
+msgstr "Anmeldedaten"
+
+msgid "registration.event_data"
+msgstr "Eventdaten"
+
+msgid "registration.what_todo"
+msgstr "Was mΓΆchtest Du machen?"
+
msgid "registration.register"
msgstr "Registrieren"
-msgid "room.rooms"
-msgstr "RΓ€ume"
+msgid "confirmation.delete"
+msgstr "MΓΆchtest du es wirklich lΓΆschen?"
-msgid "room.name"
-msgstr "Name"
+msgid "general.id"
+msgstr "ID"
-msgid "room.dect"
-msgstr "DECT"
+msgid "general.user"
+msgstr "Benutzer"
-msgid "room.map_url"
-msgstr "Karte"
+msgid "general.count"
+msgstr "Anzahl"
-msgid "room.description"
-msgstr "Beschreibung"
+msgid "general.created_at"
+msgstr "Erstellt am"
-msgid "room.required_angels"
-msgstr "BenΓΆtigte Engel"
+msgid "shifts.history"
+msgstr "Schichten Historie"
+
+msgid "shifts.history.schedule"
+msgstr "Programm: %s"
+
+msgid "shifts.history.delete_all.title"
+msgstr "%u Schichten lΓΆschen"
-msgid "room.map_url.info"
-msgstr "Die Karte wird auf der Raum-Seite als iframe eingebettet."
+msgid "shifts.start"
+msgstr "Start"
-msgid "room.create.title"
-msgstr "Raum erstellen"
+msgid "shifts.end"
+msgstr "Ende"
+
+msgid "user.info"
+msgstr "Benutzer Info"
+
+msgid "user.info.hint"
+msgstr ""
+"Wird auf der Benutzer Seite fΓΌr Schichtkoordinatoren und Admins angezeigt. "
+"Wenn ein Engel nicht als angekommen markiert ist, "
+"entfernt eine Benutzer Info die nicht-angekommen Nachricht im SystemmenΓΌ des Engels."
+
+msgid "user_info.not_arrived_hint"
+msgstr "Wenn du dich fΓΌr Schichten eintragen willst, komm gerne im Himmel vorbei."
+
+msgid "design.title"
+msgstr "Design"
+
+msgid "notification.shift.updated.introduction"
+msgstr "Eine deiner Schichten wurde aktualisiert:"
-msgid "room.edit.title"
-msgstr "Raum bearbeiten"
+msgid "notification.shift.updated.type"
+msgstr "Schichttyp wurde von %s in %s geΓ€ndert"
+
+msgid "notification.shift.updated.title"
+msgstr "Schicht Titel wurde von %s in %s geΓ€ndert"
+
+msgid "notification.shift.updated.description"
+msgstr "Schicht Beschreibung wurde geΓ€ndert"
+
+msgid "notification.shift.updated.start"
+msgstr "Schicht Start wurde von %s zu %s geΓ€ndert"
+
+msgid "notification.shift.updated.end"
+msgstr "Schicht Ende wurde von %s zu %s geΓ€ndert"
+
+msgid "notification.shift.updated.location"
+msgstr "Schicht Ort wurde von %s nach %s verschoben"
+
+msgid "notification.shift.updated.shift"
+msgstr "Die aktualisierte Schicht:"
diff --git a/resources/lang/en_US/additional.po b/resources/lang/en_US/additional.po
index 6d3f1864e..441b94ffb 100644
--- a/resources/lang/en_US/additional.po
+++ b/resources/lang/en_US/additional.po
@@ -15,19 +15,42 @@ msgstr "No user was found or password is wrong. Please try again. If you are sti
msgid "validation.password.required"
msgstr "The password is required."
+msgid "validation.password.length"
+msgstr "The password entered is too short."
+
msgid "validation.login.required"
msgstr "The login name is required."
+msgid "validation.pronoun.required"
+msgstr "Please enter your pronoun."
+
+msgid "validation.firstname.required"
+msgstr "Please enter your first name."
+
+msgid "validation.lastname.required"
+msgstr "Please enter your last name."
+
+msgid "validation.mobile.required"
+msgstr "Please enter your mobile number."
+
+msgid "validation.dect.required"
+msgstr "Please enter your DECT number."
+
+msgid "validation.username.required"
+msgstr "Please enter your nick."
+
+msgid "validation.username.username"
+msgstr ""
+"Please enter a valid nick:"
+"Use up to 24 letters, numbers or connecting punctuations (.-_) for your nickname."
+
msgid "validation.email.required"
-msgstr "The email address is required."
+msgstr "The e-mail address is required."
msgid "validation.email.email"
-msgstr "This email address is not valid."
-
-msgid "validation.password.min"
-msgstr "Your new password is too short."
+msgstr "This e-mail address is not valid."
-msgid "validation.new_password.min"
+msgid "validation.new_password.length"
msgstr "Your new password is too short."
msgid "validation.password.confirmed"
@@ -36,6 +59,21 @@ msgstr "Your passwords are not equal."
msgid "validation.password_confirmation.required"
msgstr "You have to confirm your password."
+msgid "validation.tshirt_size.required"
+msgstr "Please choose your T-shirt size."
+
+msgid "validation.tshirt_size.shirtSize"
+msgstr "Please choose a valid T-shirt size."
+
+msgid "validation.planned_arrival_date.required"
+msgstr "Please enter your planned date of arrival."
+
+msgid "validation.planned_arrival_date.min"
+msgstr "The planned date of arrival must not be before the buil-up start date."
+
+msgid "validation.planned_arrival_date.between"
+msgstr "The planned date of arrival must be between the build-up and tear-down date."
+
msgid "schedule.edit.success"
msgstr "The schedule was configured successfully."
@@ -51,6 +89,9 @@ msgstr "The shift type can't not be found."
msgid "schedule.import.success"
msgstr "Schedule import successful."
+msgid "schedule.delete.success"
+msgstr "Schedule deletion successful."
+
msgid "shifts.filter.toggle"
msgstr "collapse/show filters"
@@ -78,6 +119,9 @@ msgstr "Comment saved."
msgid "news.comment-delete.success"
msgstr "Comment successfully deleted."
+msgid "news.edit.duplicate"
+msgstr "This news has already been created."
+
msgid "news.edit.success"
msgstr "News successfully updated."
@@ -127,6 +171,9 @@ msgid "oauth.temporarily_unavailable"
msgstr "The OAuth-Provider is currently unable to handle the request "
"due to a temporary overloading or maintenance of the server."
+msgid "profile.my-shifts"
+msgstr "My shifts"
+
msgid "settings.profile"
msgstr "Profile"
@@ -138,9 +185,15 @@ msgid "settings.profile.planned_departure_date.invalid"
msgstr "Please enter your planned date of departure. "
"It should be after your planned arrival date and after buildup start date and before teardown end date."
-msgid "settings.profile.success"
+msgid "settings.success"
msgstr "Settings saved."
+msgid "settings.sessions.delete_success"
+msgstr "Session deleted successfully."
+
+msgid "settings.api.key_reset_success"
+msgstr "API key successfully reset."
+
msgid "faq.delete.success"
msgstr "FAQ entry successfully deleted."
@@ -163,7 +216,10 @@ msgid "notification.news.new.introduction"
msgstr "A new news is available: %1$s"
msgid "notification.news.new.text"
-msgstr "You can watch it at %3$s"
+msgstr "You can view it at %3$s"
+
+msgid "notification.news.updated"
+msgstr "Updated News: %s"
msgid "notification.messages.new"
msgstr "New private message from %s"
@@ -200,6 +256,12 @@ msgstr ""
"Since the deleted shift was already done, "
"we added a worklog entry instead, to keep your work hours correct."
+msgid "notification.shift.updated"
+msgstr "Your shift was updated"
+
+msgid "notification.shift.no_next_found"
+msgstr "There is no available shift."
+
msgid "user.edit.success"
msgstr "User edited successfully."
@@ -215,11 +277,26 @@ msgstr "Work log successfully updated."
msgid "worklog.delete.success"
msgstr "Work log successfully deleted."
-msgid "room.edit.success"
-msgstr "Room edited successfully."
+msgid "location.edit.success"
+msgstr "Location edited successfully."
+
+msgid "location.delete.success"
+msgstr "Location successfully deleted."
+
+msgid "shifttype.edit.success"
+msgstr "Shift type edited successfully."
-msgid "room.delete.success"
-msgstr "Room successfully deleted."
+msgid "shifttype.delete.success"
+msgstr "Shift type successfully deleted."
msgid "validation.name.exists"
msgstr "The name is already used."
+
+msgid "registration.disabled"
+msgstr "The registration is disabled."
+
+msgid "registration.successful"
+msgstr "Registration successful. You can now log in!"
+
+msgid "shifts.history.delete.success"
+msgstr "Shifts deleted successfully."
diff --git a/resources/lang/en_US/default.po b/resources/lang/en_US/default.po
index 1683b2d24..378317afe 100644
--- a/resources/lang/en_US/default.po
+++ b/resources/lang/en_US/default.po
@@ -16,29 +16,59 @@ msgstr ""
"Language: en_US\n"
"X-Poedit-SearchPath-0: .\n"
-#~ msgid "auth.no-nickname"
-#~ msgstr "Please enter a nickname."
-
-#~ msgid "auth.no-password"
-#~ msgstr "Please enter a password."
-
msgid "auth.password.error"
msgstr "Your password is incorrect. Please try it again."
msgid "form.submit"
msgstr "Submit"
-msgid "login.login"
+msgid "form.send_notification"
+msgstr "Send notifications"
+
+msgid "general.login"
msgstr "Login"
+msgid "general.dect"
+msgstr "DECT"
+
+msgid "general.name"
+msgstr "Name"
+
+msgid "general.description"
+msgstr "Description"
+
+msgid "page.403.title"
+msgstr "Forbidden"
+
+msgid "page.403.headline"
+msgstr "You are not allowed to access this page"
+
msgid "page.403.login"
msgstr "Please log in."
+msgid "page.error.title"
+msgstr "Error %s"
+
+msgid "page.404.title"
+msgstr "Page not found"
+
+msgid "page.404.not_found"
+msgstr "No sleep found"
+
msgid "page.404.text"
msgstr ""
"This page could not be found or you don't have permission to view it. "
"You probably have to sign in or register in order to gain access!"
+msgid "page.405.title"
+msgstr "405: Method not allowed"
+
+msgid "page.419.title"
+msgstr "Authentication expired"
+
+msgid "page.419.text"
+msgstr "The provided CSRF token is invalid or has expired"
+
msgid "credits.credit"
msgstr ""
"The original engelsystem was written by "
@@ -55,6 +85,9 @@ msgstr ""
"[contributors list on GitHub](https://github.com/engelsystem/engelsystem/graphs/contributors)"
" for a complete list."
+msgid "form.select_placeholder"
+msgstr "Please select..."
+
msgid "form.load_schedule"
msgstr "Load schedule"
@@ -73,6 +106,9 @@ msgstr "Preview"
msgid "form.delete"
msgstr "Delete"
+msgid "form.delete_all"
+msgstr "Delete all"
+
msgid "form.updated"
msgstr "Updated"
@@ -85,12 +121,18 @@ msgstr "Required"
msgid "form.markdown"
msgstr "You can use Markdown here"
+msgid "form.user_select"
+msgstr "Select a user"
+
msgid "schedule.import"
msgstr "Import schedule"
msgid "schedule.edit.title"
msgstr "Edit schedule"
+msgid "schedule.delete.title"
+msgstr "Delete schedule with %u shifts"
+
msgid "schedule.import.title"
msgstr "Import schedule"
@@ -98,7 +140,7 @@ msgid "schedule.last_update"
msgstr "Last updated: %s"
msgid "schedule.import.text"
-msgstr "Imports create rooms and create, update and delete shifts according to a schedule.xml export."
+msgstr "Imports create locations and create, update and delete shifts according to a schedule.xml export."
msgid "schedule.import.load.title"
msgstr "Import schedule: Preview"
@@ -115,17 +157,23 @@ msgstr "Schedule URL (schedule.xml)"
msgid "schedule.shift-type"
msgstr "Shift type"
+msgid "schedule.needed-from-shift-type"
+msgstr "Load angel types from shift type (else from location)"
+
msgid "schedule.minutes-before"
msgstr "Add minutes before talk begins"
msgid "schedule.minutes-after"
msgstr "Add minutes after talk ends"
+msgid "schedule.for_locations"
+msgstr "For locations"
+
msgid "schedule.import.request_error"
msgstr "Unable to load schedule."
-msgid "schedule.import.rooms.add"
-msgstr "Rooms to create"
+msgid "schedule.import.locations.add"
+msgstr "Locations to create"
msgid "schedule.import.shifts.add"
msgstr "Shifts to create"
@@ -136,23 +184,17 @@ msgstr "Shifts to update"
msgid "schedule.import.shifts.delete"
msgstr "Shifts to delete"
-msgid "schedule.import.rooms.name"
-msgstr "Name"
-
msgid "schedule.import.shift.dates"
msgstr "Times"
msgid "schedule.import.shift.type"
msgstr "Type"
-msgid "schedule.import.shift.title"
+msgid "title.title"
msgstr "Title"
-msgid "schedule.import.shift.room"
-msgstr "Room"
-
-msgid "shifts_history.schedule"
-msgstr "Schedule: %s"
+msgid "schedule.import.shift.location"
+msgstr "Location"
msgid "news.title"
msgstr "News"
@@ -193,8 +235,8 @@ msgstr "Subject"
msgid "news.edit.is_meeting"
msgstr "Meeting"
-msgid "news.edit.is_important"
-msgstr "Important"
+msgid "news.edit.is_highlighted"
+msgstr "Highlighted"
msgid "news.edit.is_pinned"
msgstr "Pin to top"
@@ -205,12 +247,27 @@ msgstr "Message"
msgid "news.edit.hint"
msgstr "You can use Markdown and the [more] tag"
+msgid "news.delete.title"
+msgstr "Delete news \"%s\""
+
+msgid "news.comments.delete.title"
+msgstr "Delete comment \"%s\""
+
+msgid "notification.news.updated.introduction"
+msgstr "The news %1$s was updated"
+
+msgid "notification.news.updated.text"
+msgstr "You can view it at %3$s"
+
msgid "form.search"
msgstr "Search"
msgid "log.log"
msgstr "Logs"
+msgid "log.only_own"
+msgstr "You can view your own logs. The logs of other users can be checked by bureaucrats."
+
msgid "log.time"
msgstr "Time"
@@ -223,15 +280,15 @@ msgstr "Message"
msgid "settings.settings"
msgstr "Settings"
-msgid "settings.profile.user_details.info"
-msgstr "Here you can change your user details."
-
msgid "settings.profile.entry_required"
-msgstr "Entry required!"
+msgstr "Entry required"
-msgid "settings.profile.nick"
+msgid "general.nick"
msgstr "Nick"
+msgid "settings.profile.nick.already-taken"
+msgstr "The nick is already taken."
+
msgid "settings.profile.pronoun"
msgstr "Pronoun"
@@ -250,17 +307,20 @@ msgstr "Planned date of arrival"
msgid "settings.profile.planned_departure_date"
msgstr "Planned date of departure"
-msgid "settings.profile.dect"
-msgstr "DECT"
-
msgid "settings.profile.mobile"
msgstr "Mobile"
msgid "settings.profile.mobile_show"
msgstr "Show mobile number to other users to contact me."
-msgid "settings.profile.email"
-msgstr "E-Mail"
+msgid "settings.profile.email-preferences"
+msgstr "E-mail preferences"
+
+msgid "general.email"
+msgstr "E-mail"
+
+msgid "settings.profile.email.already-taken"
+msgstr "This e-mail address is already taken."
msgid "settings.profile.email_shiftinfo"
msgstr "The %s is allowed to send me an e-mail (e.g. when my shifts change)."
@@ -272,17 +332,17 @@ msgid "settings.profile.email_messages"
msgstr "Notify me on new private messages."
msgid "settings.profile.email_by_human_allowed"
-msgstr "Allow heaven angels to contact you by e-mail."
+msgstr "Allow heaven angels to contact me by e-mail."
msgid "settings.profile.email_goody"
-msgstr "To receive vouchers, give consent that nick, e-mail address, worked hours and shirt size will be stored until "
-"the next similar event."
+msgstr "To possibly receive vouchers for the next similar event, I consent "
+"that my nick, e-mail address, worked hours and T-shirt size will be stored until then."
msgid "settings.profile.privacy"
msgstr "To withdraw your approval, send an e-mail to %1$s."
msgid "settings.profile.shirt_size"
-msgstr "Shirt size"
+msgstr "T-shirt size"
msgid "settings.profile.angeltypes.info"
msgstr "You can manage your Angeltypes on the Angeltypes page."
@@ -293,11 +353,14 @@ msgstr "Password"
msgid "settings.password.info"
msgstr "Here you can change your password."
+msgid "settings.password.confirmation-does-not-match"
+msgstr "Password and password confirmation do not match."
+
msgid "settings.password.password"
msgstr "Old password"
msgid "settings.password.new_password"
-msgstr "New passwort"
+msgstr "New password"
msgid "settings.password.new_password2"
msgstr "Password confirmation"
@@ -305,6 +368,21 @@ msgstr "Password confirmation"
msgid "settings.password.success"
msgstr "Password was changed successfully."
+msgid "settings.sessions"
+msgstr "Sessions"
+
+msgid "settings.sessions.info"
+msgstr "Here you can see and delete your browser sessions."
+
+msgid "settings.sessions.current"
+msgstr "Current session"
+
+msgid "settings.sessions.id"
+msgstr "Session ID"
+
+msgid "settings.sessions.last_activity"
+msgstr "Last activity"
+
msgid "settings.theme"
msgstr "Theme"
@@ -314,6 +392,79 @@ msgstr "Here you can change your theme."
msgid "settings.theme.success"
msgstr "Theme was changed successfully."
+msgid "settings.certificates"
+msgstr "Certificates"
+
+msgid "settings.certificates.info"
+msgstr "This information is only visible for supporters and admins."
+
+msgid "settings.certificates.title.ifsg"
+msgstr "Health instructions"
+
+msgid "settings.certificates.driving_license"
+msgstr "Driving license"
+
+msgid "settings.certificates.has_car"
+msgstr ""
+"I have my own car with me and am willing to use it for the event (You'll get "
+"reimbursed for fuel)"
+
+msgid "settings.certificates.drive_car"
+msgstr "Car"
+
+msgid "settings.certificates.drive_3_5t"
+msgstr "3.5t Transporter"
+
+msgid "settings.certificates.drive_7_5t"
+msgstr "7.5t Truck"
+
+msgid "settings.certificates.drive_12t"
+msgstr "12t Truck"
+
+msgid "settings.certificates.drive_forklift"
+msgstr "Forklift"
+
+msgid "settings.certificates.ifsg_light"
+msgstr "I was instructed about IfSG Β§43 (aka Frikadellendiplom light) on site."
+
+msgid "settings.certificates.ifsg"
+msgstr "I have gotten the instruction about Β§43 IfSG (aka Frikadellendiplom) from my Health Department "
+"and a second instruction from us or my employer/chef/assosiation within 3 months. "
+"Additionally my second instruction is not older than 2 years."
+
+msgid "settings.certificates.success"
+msgstr "Certificates were updated successfully."
+
+msgid "angeltype.ifsg.required"
+msgstr "Requires health instruction"
+
+msgid "ifsg.certificate"
+msgstr "health instruction"
+
+msgid "ifsg.certificate_light"
+msgstr "health instruction on site"
+
+msgid "angeltype.ifsg.own"
+msgstr "my health instruction"
+
+msgid "angeltype.ifsg.required.info"
+msgstr "This angeltype requires a health instruction. Please enter your health instruction information!"
+
+msgid "angeltype.ifsg.required.info.here"
+msgstr "You joined an angeltype which requires a health instruction. "
+"Please edit your health instruction information here: %s."
+
+msgid "angeltype.driving_license.required.info.here"
+msgstr ""
+"You joined an angeltype which requires a driving license. "
+"Please edit your driving license information here: %s."
+
+msgid "ifsg.info"
+msgstr "Health instruction information"
+
+msgid "driving_license.info"
+msgstr "driving license information"
+
msgid "settings.language"
msgstr "Language"
@@ -323,6 +474,35 @@ msgstr "Here you can change your language."
msgid "settings.language.success"
msgstr "Language was changed successfully."
+msgid "settings.api"
+msgstr "API"
+
+msgid "settings.api.about"
+msgstr ""
+"The API allows you to interact with the Engelsystem by using external programs. "
+"It's not complete but we are working on extending it.\n"
+"The API endpoint is located at `%s` and described in the [OpenAPI specification](%s).\n"
+"Don't share your personal API key with anyone as it can be used to view your personal data "
+"and do changes your behalf!"
+
+msgid "settings.api.shifts_json_show"
+msgstr "Show JSON shifts export"
+
+msgid "settings.api.ical_show"
+msgstr "Show iCal export"
+
+msgid "settings.api.news_show"
+msgstr "Show news feeds"
+
+msgid "settings.api.key_show"
+msgstr "Show API key"
+
+msgid "settings.api.key_reset"
+msgstr "Reset API key"
+
+msgid "settings.api.key_reset_confirm"
+msgstr "If you reset the API key you have to update it in all your applications."
+
msgid "settings.oauth"
msgstr "Single Sign-On"
@@ -359,6 +539,9 @@ msgstr "Question"
msgid "faq.message"
msgstr "Answer"
+msgid "faq.delete.title"
+msgstr "Delete FAQ \"%s\""
+
msgid "question.questions"
msgstr "Questions"
@@ -377,17 +560,20 @@ msgstr "Question"
msgid "question.answer"
msgstr "Answer"
+msgid "question.delete.title"
+msgstr "Delete question \"%s\""
+
msgid "user.edit.shirt"
-msgstr "Edit shirt"
+msgstr "Edit T-shirt"
msgid "user.edit.goodie"
msgstr "Edit goodie"
msgid "form.shirt"
-msgstr "Shirt"
+msgstr "T-shirt"
msgid "user.shirt_size"
-msgstr "Shirt size"
+msgstr "T-shirt size"
msgid "user.active"
msgstr "Active"
@@ -398,8 +584,11 @@ msgstr "Active (forced)"
msgid "user.arrived"
msgstr "Arrived"
+msgid "user.arrive"
+msgstr "Arrive"
+
msgid "user.got_shirt"
-msgstr "Got shirt"
+msgstr "Got T-shirt"
msgid "user.got_goodie"
msgstr "Got goodie"
@@ -419,9 +608,6 @@ msgstr "Message"
msgid "angel"
msgstr "Angel"
-msgid "date"
-msgstr "Date"
-
msgid "worklog.add"
msgstr "Add work log"
@@ -452,45 +638,308 @@ msgstr "Teams-/Job description"
msgid "angeltypes.about.text"
msgstr "Here you can find the list of teams and their tasks. If you have further questions, have a look at the FAQ."
+msgid "angeltypes.restricted"
+msgstr "Requires introduction"
+
+msgid "angeltypes.restricted.info"
+msgstr "Angel types which require introduction can only be used by an angel "
+"if enabled by a supporter (double opt-in)."
+
msgid "angeltypes.restricted.hint"
msgstr "This angeltype requires the attendance at an introduction meeting. "
"You might find additional information in the description."
-msgid "angeltypes.name"
-msgstr "Name"
-
-msgid "angeltypes.dect"
-msgstr "DECT"
+msgid "angeltypes.can-change-later"
+msgstr "You can change your selection later in the settings."
msgid "angeltypes.email"
-msgstr "E-Mail"
+msgstr "E-mail"
+
+msgid "angeltypes.shift.self_signup.info"
+msgstr "Angel types which have shift self signup enabled allow angels to self sign up for there shifts, "
+"if shift self signup is disabled only supporters and admins can sign angels into shifts of these angel types."
+
+msgid "shift.self_signup"
+msgstr "Shift self signup"
+
+msgid "shift.self_signup.allowed"
+msgstr "Shift self signup allowed"
+
+msgid "angeltypes.hide_on_shift_view"
+msgstr "Hide on shift view"
+
+msgid "angeltypes.hide_on_shift_view.info"
+msgstr "If checked only admins and members of the angeltype "
+"can see the filter option for this angeltype on the shifts page"
msgid "registration.register"
msgstr "Register"
-msgid "room.rooms"
-msgstr "Rooms"
+msgid "location.location"
+msgstr "Location"
-msgid "room.name"
-msgstr "Name"
-
-msgid "room.dect"
-msgstr "DECT"
+msgid "location.locations"
+msgstr "Locations"
-msgid "room.map_url"
+msgid "location.map_url"
msgstr "Map"
-msgid "room.description"
-msgstr "Description"
+msgid "location.required_angels"
+msgstr "Required angels (on schedule import)"
+
+msgid "location.map_url.info"
+msgstr "The map will be embedded on the location page as an iframe."
+
+msgid "location.create.title"
+msgstr "Create location"
+
+msgid "location.edit.title"
+msgstr "Edit location"
+
+msgid "location.delete.title"
+msgstr "Delete location \"%s\""
+
+msgid "shifttype.shifttypes"
+msgstr "Shift types"
+
+msgid "shifttype.edit.title"
+msgstr "Edit shift type"
+
+msgid "shifttype.create.title"
+msgstr "Create shift type"
+
+msgid "shifttype.delete.title"
+msgstr "Delete shift type \"%s\""
+
+msgid "shifttype.required_angels"
+msgstr "Required angels (on schedule import)"
+
+msgid "event.day"
+msgstr "Day %1$d"
+
+msgid "dashboard.day"
+msgstr "Day"
+
+msgid "registration.title"
+msgstr "Angel registration"
+
+msgid "registration.login_data"
+msgstr "Login data"
+
+msgid "registration.event_data"
+msgstr "Event data"
+
+msgid "registration.what_todo"
+msgstr "What do you want to do?"
+
+msgid "tshirt.required.hint"
+msgstr "Please specify a T-shirt size in your settings!"
+
+msgid "dect.required.hint"
+msgstr ""
+"Please specify a DECT phone number in your settings! "
+"If you don't have a DECT phone, just enter '-'."
+
+msgid "pronoun.required.hint"
+msgstr "Please enter a pronoun in your settings!"
+
+msgid "firstname.required.hint"
+msgstr "Please enter a firstname in your settings!"
+
+msgid "lastname.required.hint"
+msgstr "Please enter a lastname in your settings!"
+
+msgid "mobile.required.hint"
+msgstr "Please enter a mobile number in your settings!"
+
+msgid "confirmation.delete"
+msgstr "Do you really want to delete it?"
+
+msgid "general.datetime"
+msgstr "Y-m-d H:i"
+
+msgid "general.date"
+msgstr "Y-m-d"
+
+msgid "general.id"
+msgstr "ID"
+
+msgid "general.user"
+msgstr "User"
+
+msgid "general.count"
+msgstr "Count"
+
+msgid "general.created_at"
+msgstr "Created at"
+
+msgid "shifts.random"
+msgstr "ZufΓ€llige Schicht"
+
+msgid "shifts.history"
+msgstr "Shifts history"
+
+msgid "shifts.history.schedule"
+msgstr "Schedule: %s"
+
+msgid "shifts.history.delete_all.title"
+msgstr "Delete %u shifts"
+
+msgid "shifts.start"
+msgstr "Start"
+
+msgid "shifts.end"
+msgstr "End"
+
+msgid "user.info"
+msgstr "User info"
+
+msgid "user.info.hint"
+msgstr ""
+"Is displayed for shift coordinators and admins in the user view. "
+"If an angel is not marked as arrived a user-info removes the not-arrived notification in the angels sysmenu."
+
+msgid "user_info.not_arrived_hint"
+msgstr "If you want to sign up for shifts, feel free to drop by heaven."
+
+msgid "email.greeting"
+msgstr "Hi %s,"
+
+msgid "email.introduction"
+msgstr "here is a message for you from the %s:"
+
+msgid "email.footer"
+msgstr ""
+"This e-mail is autogenerated and has not been signed. "
+"You got this e-mail because you are registered in the %s."
+
+msgid "password.email.message"
+msgstr "Please visit %s to recover your password."
+
+msgid "password.minimal_length"
+msgstr "Minimal length %d characters"
+
+msgid "footer.eventinfo.name_start_end"
+msgstr "%1$s, from %2$s to %3$s"
+
+msgid "footer.eventinfo.name_start"
+msgstr "%1$s, starting %2$s"
+
+msgid "footer.eventinfo.start_end"
+msgstr "Event from %1$s to %2$s"
+
+msgid "footer.issues"
+msgstr "Bugs / Features"
+
+msgid "footer.github"
+msgstr "Development Platform"
+
+msgid "credits.title"
+msgstr "Credits"
+
+msgid "general.register"
+msgstr "Register"
+
+msgid "shift.next"
+msgstr "Next shift"
+
+msgid "general.logout"
+msgstr "Logout"
+
+msgid "credits.source"
+msgstr "Source code"
+
+msgid "credits.version"
+msgstr "Version: _%s_"
+
+msgid "design.title"
+msgstr "Design"
+
+msgid "login.welcome"
+msgstr "Welcome to the %s!"
+
+msgid "event.buildup.start"
+msgstr "Buildup starts"
+
+msgid "event.starts"
+msgstr "Event starts"
+
+msgid "event.ends"
+msgstr "Event ends"
+
+msgid "event.teardown.ends"
+msgstr "Teardown ends"
+
+msgid "login.password.reset"
+msgstr "I forgot my password"
+
+msgid "login.registration"
+msgstr "Please sign up, if you want to help us!"
+
+msgid "login.registration.external"
+msgstr "Registration is only available via external login."
+
+msgid "login.registration.disabled"
+msgstr "Registration is disabled."
+
+msgid "login.do"
+msgstr "What can I do?"
+
+msgid "login.jobs"
+msgstr "Read about the jobs you can do to help us."
+
+msgid "login.cookies"
+msgstr "Please note: You have to activate cookies!"
+
+msgid "general.angel"
+msgstr "Angel"
+
+msgid "title.date"
+msgstr "Date"
+
+msgid "password.reset.confirm"
+msgstr "Confirm password"
+
+msgid "password.recovery.success"
+msgstr "We sent you an e-mail containing your password recovery link."
+
+msgid "password.reset.title"
+msgstr "Password recovery"
+
+msgid "password.recovery.text"
+msgstr ""
+"We will send you an e-mail with a password recovery link. "
+"Please use the e-mail address you used for registration."
+
+msgid "form.recover"
+msgstr "Recover"
+
+msgid "notification.shift.updated.introduction"
+msgstr "Your shift has changed:"
+
+msgid "notification.shift.updated.type"
+msgstr "Shift type changed from %s to %s"
+
+msgid "notification.shift.updated.title"
+msgstr "Shift title changed from %s to %s"
+
+msgid "notification.shift.updated.description"
+msgstr "Shift description changed"
+
+msgid "notification.shift.updated.start"
+msgstr "Shift start changed from %s to %s"
+
+msgid "notification.shift.updated.end"
+msgstr "Shift end changed from %s to %s"
-msgid "room.required_angels"
-msgstr "Required angels"
+msgid "notification.shift.updated.location"
+msgstr "Shift location moved from %s to %s"
-msgid "room.map_url.info"
-msgstr "The map will be embedded on the room page as an iframe."
+msgid "notification.shift.updated.shift"
+msgstr "The updated Shift:"
-msgid "room.create.title"
-msgstr "Create room"
+msgid "general.actions"
+msgstr "Actions"
-msgid "room.edit.title"
-msgstr "Edit room"
+msgid "general.back"
+msgstr "Back"
diff --git a/resources/lang/pt_BR/default.po b/resources/lang/pt_BR/default.po
deleted file mode 100644
index 9f48b4ce9..000000000
--- a/resources/lang/pt_BR/default.po
+++ /dev/null
@@ -1,2610 +0,0 @@
-msgid ""
-msgstr ""
-"Project-Id-Version: Engelsystem 2.0\n"
-"POT-Creation-Date: 2017-04-25 05:23+0200\n"
-"PO-Revision-Date: 2018-11-27 00:29+0100\n"
-"Last-Translator: samba \n"
-"Language-Team: \n"
-"Language: pt_BR\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.0.1\n"
-"X-Poedit-KeywordsList: _;gettext;gettext_noop\n"
-"X-Poedit-Basepath: ../../..\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Poedit-SourceCharset: UTF-8\n"
-"X-Poedit-SearchPath-0: .\n"
-
-#: includes/controller/angeltypes_controller.php:7
-#: includes/pages/user_shifts.php:164 includes/view/AngelTypes_view.php:62
-#: includes/view/AngelTypes_view.php:86 includes/view/User_view.php:356
-msgid "Angeltypes"
-msgstr "Tipo de Anjo"
-
-#: includes/controller/angeltypes_controller.php:53
-#: includes/pages/guest_login.php:377 includes/view/AngelTypes_view.php:265
-#: includes/view/AngelTypes_view.php:326 includes/view/User_view.php:110
-msgid "Teams/Job description"
-msgstr "Time/Descrição do trabalho"
-
-#: includes/controller/angeltypes_controller.php:72
-#, php-format
-msgid "Angeltype %s deleted."
-msgstr "Tipo de anjo %s apagado."
-
-#: includes/controller/angeltypes_controller.php:77
-#: includes/view/AngelTypes_view.php:41
-#, php-format
-msgid "Delete angeltype %s"
-msgstr "Apagar tipo de anjo %s"
-
-#: includes/controller/angeltypes_controller.php:116
-msgid "Please check the name. Maybe it already exists."
-msgstr "Por favor verifique o nome. Pode ser que jΓ‘ exista."
-
-#: includes/controller/angeltypes_controller.php:141
-#: includes/view/AngelTypes_view.php:60
-#, php-format
-msgid "Edit %s"
-msgstr "Editar %s"
-
-#: includes/controller/angeltypes_controller.php:162
-#: includes/view/AngelTypes_view.php:252
-#, php-format
-msgid "Team %s"
-msgstr "Time %s"
-
-#: includes/controller/angeltypes_controller.php:181
-#: includes/view/User_view.php:274
-msgid "view"
-msgstr "ver"
-
-#: includes/controller/angeltypes_controller.php:185
-#: includes/pages/admin_free.php:71 includes/pages/admin_groups.php:23
-#: includes/pages/admin_rooms.php:16 includes/view/AngelTypes_view.php:107
-#: includes/view/ShiftTypes_view.php:55 includes/view/ShiftTypes_view.php:67
-#: includes/view/Shifts_view.php:55 includes/view/User_view.php:277
-#: includes/view/User_view.php:328
-msgid "edit"
-msgstr "editar"
-
-#: includes/controller/angeltypes_controller.php:186
-#: includes/controller/shifts_controller.php:178
-#: includes/pages/admin_questions.php:42 includes/pages/admin_questions.php:56
-#: includes/pages/admin_rooms.php:17 includes/pages/admin_user.php:120
-#: includes/view/AngelTypes_view.php:45 includes/view/AngelTypes_view.php:110
-#: includes/view/Questions_view.php:5 includes/view/Questions_view.php:12
-#: includes/view/ShiftTypes_view.php:16 includes/view/ShiftTypes_view.php:56
-#: includes/view/ShiftTypes_view.php:68 includes/view/Shifts_view.php:56
-msgid "delete"
-msgstr "deletar"
-
-#: includes/controller/angeltypes_controller.php:191
-#: includes/view/AngelTypes_view.php:103 includes/view/AngelTypes_view.php:288
-msgid "leave"
-msgstr "sair"
-
-#: includes/controller/angeltypes_controller.php:193
-#: includes/view/AngelTypes_view.php:94 includes/view/AngelTypes_view.php:290
-msgid "join"
-msgstr "entrar"
-
-#: includes/controller/angeltypes_controller.php:220
-#: includes/controller/user_angeltypes_controller.php:29
-#: includes/controller/user_angeltypes_controller.php:35
-#: includes/controller/user_angeltypes_controller.php:65
-#: includes/controller/user_angeltypes_controller.php:71
-#: includes/controller/user_angeltypes_controller.php:119
-#: includes/controller/user_angeltypes_controller.php:170
-#: includes/controller/user_angeltypes_controller.php:235
-msgid "Angeltype doesn't exist."
-msgstr "Esse tipo de anjo nΓ£o existe."
-
-#: includes/controller/event_config_controller.php:4
-msgid "Event config"
-msgstr "Configuração do evento"
-
-#: includes/controller/event_config_controller.php:48
-msgid "Please enter buildup start date."
-msgstr "Por favor digite a data de inΓcio da montagem."
-
-#: includes/controller/event_config_controller.php:52
-msgid "Please enter event start date."
-msgstr "Por favor digite a data de inΓcio do evento."
-
-#: includes/controller/event_config_controller.php:56
-msgid "Please enter event end date."
-msgstr "Por favor digite a data de tΓ©rmino do evento."
-
-#: includes/controller/event_config_controller.php:60
-msgid "Please enter teardown end date."
-msgstr "Por favor digite a data de desmontagem do evento"
-
-#: includes/controller/event_config_controller.php:66
-msgid "The buildup start date has to be before the event start date."
-msgstr "A data de montagem deve ser anterior a data de inΓcio do evento."
-
-#: includes/controller/event_config_controller.php:71
-msgid "The event start date has to be before the event end date."
-msgstr ""
-"A data de inΓcio do evento deve ser anterior a data de tΓ©rmino do evento."
-
-#: includes/controller/event_config_controller.php:76
-msgid "The event end date has to be before the teardown end date."
-msgstr "A data de tΓ©rmino deve ser anterior a data de desmontagem do evento."
-
-#: includes/controller/event_config_controller.php:81
-msgid "The buildup start date has to be before the teardown end date."
-msgstr "A data de montagem deve ser anterior a data de desmontagem do evento."
-
-#: includes/controller/event_config_controller.php:92
-msgid "Settings saved."
-msgstr "Configuraçáes salvas."
-
-#: includes/controller/shift_entries_controller.php:56
-msgid ""
-"You are not allowed to sign up for this shift. Maybe shift is full or "
-"already running."
-msgstr ""
-"VocΓͺ nΓ£o tem permissΓ£o para se inscrever nesse turno. Talvez o turno esteja "
-"lotado ou jΓ‘ esteja em andamento."
-
-#: includes/controller/shift_entries_controller.php:103
-msgid "You are subscribed. Thank you!"
-msgstr "VocΓͺ jΓ‘ estΓ‘ inscrito. Obrigado!"
-
-#: includes/controller/shift_entries_controller.php:103
-#: includes/pages/user_myshifts.php:4
-msgid "My shifts"
-msgstr "Meus turnos"
-
-#: includes/controller/shift_entries_controller.php:111
-#: includes/view/User_view.php:348
-msgid "Freeloader"
-msgstr "Freeloader"
-
-#: includes/controller/shift_entries_controller.php:180
-msgid "Shift entry deleted."
-msgstr "O turno foi deletado."
-
-#: includes/controller/shift_entries_controller.php:182
-msgid "Entry not found."
-msgstr "Entrada nΓ£o encontrada."
-
-#: includes/controller/shifts_controller.php:63
-msgid "Please select a room."
-msgstr "Por favor selecione uma sala."
-
-#: includes/controller/shifts_controller.php:70
-msgid "Please select a shifttype."
-msgstr "Por favor selecione um tssipo de turno."
-
-#: includes/controller/shifts_controller.php:77
-msgid "Please enter a valid starting time for the shifts."
-msgstr "Por favor entre com um horΓ‘rio de inΓcio vΓ‘lido para os turnos."
-
-#: includes/controller/shifts_controller.php:84
-msgid "Please enter a valid ending time for the shifts."
-msgstr "Por favor entre com um horΓ‘rio de tΓ©rmino vΓ‘lido para os turnos."
-
-#: includes/controller/shifts_controller.php:89
-msgid "The ending time has to be after the starting time."
-msgstr "O horΓ‘rio de tΓ©rmino deve ser apΓ³s o horΓ‘rio de inΓcio."
-
-#: includes/controller/shifts_controller.php:97
-#, php-format
-msgid "Please check your input for needed angels of type %s."
-msgstr "Por favor verifique seu input para os anjos de tipo %s necessΓ‘rios."
-
-#: includes/controller/shifts_controller.php:120
-msgid "Shift updated."
-msgstr "Turno atualizado."
-
-#: includes/controller/shifts_controller.php:135
-msgid "This page is much more comfortable with javascript."
-msgstr "Esta pΓ‘gina Γ© muito mais confortΓ‘vel com javascript"
-
-#: includes/controller/shifts_controller.php:137
-#: includes/pages/admin_import.php:98 includes/pages/admin_shifts.php:319
-msgid "Shifttype"
-msgstr "Tipo de turno"
-
-#: includes/controller/shifts_controller.php:138
-#: includes/pages/admin_import.php:158 includes/pages/admin_import.php:167
-#: includes/pages/admin_import.php:176 includes/pages/admin_shifts.php:320
-#: includes/view/Shifts_view.php:62
-msgid "Title"
-msgstr "TΓtulo"
-
-#: includes/controller/shifts_controller.php:139
-msgid "Room:"
-msgstr "Sala:"
-
-#: includes/controller/shifts_controller.php:140
-msgid "Start:"
-msgstr "InΓcio:"
-
-#: includes/controller/shifts_controller.php:141
-msgid "End:"
-msgstr "Fim:"
-
-#: includes/controller/shifts_controller.php:142
-#: includes/pages/admin_shifts.php:270 includes/pages/admin_shifts.php:334
-#: includes/view/Shifts_view.php:88
-msgid "Needed angels"
-msgstr "Anjos necessΓ‘rios"
-
-#: includes/controller/shifts_controller.php:144
-#: includes/pages/admin_groups.php:54 includes/pages/admin_news.php:35
-#: includes/pages/admin_questions.php:40 includes/pages/admin_rooms.php:157
-#: includes/pages/admin_shifts.php:272 includes/pages/user_messages.php:44
-#: includes/pages/user_news.php:107 includes/pages/user_news.php:164
-#: includes/view/AngelTypes_view.php:76 includes/view/EventConfig_view.php:122
-#: includes/view/Questions_view.php:32 includes/view/ShiftEntry_view.php:32
-#: includes/view/ShiftTypes_view.php:39
-#: includes/view/UserDriverLicenses_view.php:34 includes/view/User_view.php:56
-#: includes/view/User_view.php:65 includes/view/User_view.php:70
-#: includes/view/User_view.php:75 includes/view/User_view.php:146
-#: includes/view/User_view.php:402
-msgid "Save"
-msgstr "Salvar"
-
-#: includes/controller/shifts_controller.php:172
-msgid "Shift deleted."
-msgstr "Turno deletado."
-
-#: includes/controller/shifts_controller.php:177
-#, php-format
-msgid "Do you want to delete the shift %s from %s to %s?"
-msgstr "VocΓͺ quer deletar o turno %s de %s para %s?"
-
-#: includes/controller/shifts_controller.php:195
-msgid "Shift could not be found."
-msgstr "O turno nΓ£o pΓ΄de ser encontrado."
-
-#: includes/controller/shifttypes_controller.php:31
-#, php-format
-msgid "Shifttype %s deleted."
-msgstr "Tipo de turno %s deletado."
-
-#: includes/controller/shifttypes_controller.php:36
-#: includes/view/ShiftTypes_view.php:12
-#, php-format
-msgid "Delete shifttype %s"
-msgstr "Apagar tipo de turno %s"
-
-#: includes/controller/shifttypes_controller.php:58
-msgid "Shifttype not found."
-msgstr "Tipo de turno nΓ£o encontrado."
-
-#: includes/controller/shifttypes_controller.php:74
-#: includes/pages/admin_rooms.php:71
-msgid "Please enter a name."
-msgstr "Por favor digite um nome."
-
-#: includes/controller/shifttypes_controller.php:94
-msgid "Updated shifttype."
-msgstr "Tipo de turno atualizado."
-
-#: includes/controller/shifttypes_controller.php:101
-msgid "Created shifttype."
-msgstr "Tipo de turno criado"
-
-#: includes/controller/shifttypes_controller.php:155
-msgid "Shifttypes"
-msgstr "Tipos de turno"
-
-#: includes/controller/user_angeltypes_controller.php:19
-#, php-format
-msgid "There is %d unconfirmed angeltype."
-msgid_plural "There are %d unconfirmed angeltypes."
-msgstr[0] "HΓ‘ %d anjo nΓ£o confirmado."
-msgstr[1] "There are %d unconfirmed angeltypes."
-
-#: includes/controller/user_angeltypes_controller.php:19
-msgid "Angel types which need approvals:"
-msgstr "Tipos de anjo que precisam de aprovaçáes:"
-
-#: includes/controller/user_angeltypes_controller.php:40
-msgid "You are not allowed to delete all users for this angeltype."
-msgstr ""
-"VocΓͺ nΓ£o tΓͺm permissΓ£o para apagar todos os usuΓ‘rios desse tipo de anjo."
-
-#: includes/controller/user_angeltypes_controller.php:48
-#, php-format
-msgid "Denied all users for angeltype %s."
-msgstr "Todos os usuΓ‘rios com tipo de anjo %s negados."
-
-#: includes/controller/user_angeltypes_controller.php:53
-#: includes/view/UserAngelTypes_view.php:15
-msgid "Deny all users"
-msgstr "Negar todos os usuΓ‘rios"
-
-#: includes/controller/user_angeltypes_controller.php:77
-#: includes/controller/user_angeltypes_controller.php:107
-#: includes/controller/user_angeltypes_controller.php:113
-#: includes/controller/user_angeltypes_controller.php:158
-#: includes/controller/user_angeltypes_controller.php:164
-#: includes/controller/user_angeltypes_controller.php:216
-#: includes/controller/user_angeltypes_controller.php:229
-msgid "User angeltype doesn't exist."
-msgstr "O tipo de anjo deste usuΓ‘rio nΓ£o existe."
-
-#: includes/controller/user_angeltypes_controller.php:82
-msgid "You are not allowed to confirm all users for this angeltype."
-msgstr ""
-"VocΓͺ nΓ£o tem permissΓ£o para confirmar todos os usuΓ‘rios com este tipo de "
-"anjo."
-
-#: includes/controller/user_angeltypes_controller.php:90
-#, php-format
-msgid "Confirmed all users for angeltype %s."
-msgstr "Todos os usuΓ‘rios com tipo de anjo %s confirmados."
-
-#: includes/controller/user_angeltypes_controller.php:95
-#: includes/view/UserAngelTypes_view.php:26
-msgid "Confirm all users"
-msgstr "Confirmar todos usuΓ‘rios"
-
-#: includes/controller/user_angeltypes_controller.php:124
-msgid "You are not allowed to confirm this users angeltype."
-msgstr "VocΓͺ nΓ£o tem permissΓ£o para confirmar o tipo de anjo deste usuΓ‘rio."
-
-#: includes/controller/user_angeltypes_controller.php:130
-#: includes/controller/user_angeltypes_controller.php:176
-#: includes/controller/user_angeltypes_controller.php:241
-#: includes/controller/users_controller.php:312
-msgid "User doesn't exist."
-msgstr "UsuΓ‘rio nΓ£o existente."
-
-#: includes/controller/user_angeltypes_controller.php:141
-#, php-format
-msgid "%s confirmed for angeltype %s."
-msgstr "%s confirmado para o tipo de anjo %s."
-
-#: includes/controller/user_angeltypes_controller.php:146
-#: includes/view/UserAngelTypes_view.php:37
-msgid "Confirm angeltype for user"
-msgstr "Confirme o tipo de anjo para o usuΓ‘rio"
-
-#: includes/controller/user_angeltypes_controller.php:181
-msgid "You are not allowed to delete this users angeltype."
-msgstr "VocΓͺ nΓ£o tem permissΓ£o para deletar o tipo de anjo deste usuΓ‘rio."
-
-#: includes/controller/user_angeltypes_controller.php:191
-#, php-format
-msgid "User %s removed from %s."
-msgstr "UsuΓ‘rio %s removido de %s."
-
-#: includes/controller/user_angeltypes_controller.php:199
-#: includes/view/UserAngelTypes_view.php:48
-msgid "Remove angeltype"
-msgstr "Remover esse tipo de anjo"
-
-#: includes/controller/user_angeltypes_controller.php:211
-msgid "You are not allowed to set supporter rights."
-msgstr "VocΓͺ nΓ£o tem autorização para definir permissΓ΅es de apoiadores."
-
-#: includes/controller/user_angeltypes_controller.php:223
-msgid "No supporter update given."
-msgstr "Nenhuma atualização de apoiador informada."
-
-#: includes/controller/user_angeltypes_controller.php:248
-#, php-format
-msgid "Added supporter rights for %s to %s."
-msgstr "PermissΓ΅es de apoiador incluΓdos para %s a %s."
-
-#: includes/controller/user_angeltypes_controller.php:248
-#, php-format
-msgid "Removed supporter rights for %s from %s."
-msgstr "PermissΓ΅es de apoiador removidos para %s a %s."
-
-#: includes/controller/user_angeltypes_controller.php:256
-#: includes/view/AngelTypes_view.php:156
-#: includes/view/UserAngelTypes_view.php:4
-msgid "Add supporter rights"
-msgstr "Adicionar permissΓ£o ao apoiador"
-
-#: includes/controller/user_angeltypes_controller.php:256
-#: includes/view/AngelTypes_view.php:147
-#: includes/view/UserAngelTypes_view.php:4
-msgid "Remove supporter rights"
-msgstr "Remover permissΓ΅es de apoiador"
-
-#: includes/controller/user_angeltypes_controller.php:289
-#, php-format
-msgid "User %s added to %s."
-msgstr "UsuΓ‘rio %s adicionado a %s."
-
-#: includes/controller/user_angeltypes_controller.php:299
-#: includes/view/UserAngelTypes_view.php:64
-msgid "Add user to angeltype"
-msgstr "Adicionar usuΓ‘rio a tipo de anjo"
-
-#: includes/controller/user_angeltypes_controller.php:312
-#, php-format
-msgid "You are already a %s."
-msgstr "VocΓͺ jΓ‘ Γ© %s."
-
-#: includes/controller/user_angeltypes_controller.php:319
-#, php-format
-msgid "You joined %s."
-msgstr "VocΓͺ se juntou a %s."
-
-#: includes/controller/user_angeltypes_controller.php:332
-#: includes/view/UserAngelTypes_view.php:78
-#, php-format
-msgid "Become a %s"
-msgstr "Torne-se %s"
-
-#: includes/controller/user_driver_licenses_controller.php:19
-#, php-format
-msgid ""
-"You joined an angeltype which requires a driving license. Please edit your "
-"driving license information here: %s."
-msgstr ""
-"VocΓͺ se tornou um tipo de anjo que requer carteira de motorista. Por favor "
-"inclua \n"
-"seus dados aqui: %s."
-
-#: includes/controller/user_driver_licenses_controller.php:19
-msgid "driving license information"
-msgstr "dados da carteira de motorista"
-
-#: includes/controller/user_driver_licenses_controller.php:113
-msgid "Your driver license information has been saved."
-msgstr "Dados da carteira de motorista salvos."
-
-#: includes/controller/user_driver_licenses_controller.php:116
-msgid "Please select at least one driving license."
-msgstr "Selecione pelo menos uma carteira de motorista."
-
-#: includes/controller/user_driver_licenses_controller.php:121
-msgid "Your driver license information has been removed."
-msgstr "Seus dados de carteira de motorista foram removidos."
-
-#: includes/controller/user_driver_licenses_controller.php:127
-#: includes/view/UserDriverLicenses_view.php:15
-#, php-format
-msgid "Edit %s driving license information"
-msgstr "Editar dados da carteira de motorista de %s"
-
-#: includes/controller/users_controller.php:52
-msgid "You cannot delete yourself."
-msgstr "VocΓͺ nΓ£o pode se deletar."
-
-#: includes/controller/users_controller.php:61
-#: includes/pages/guest_login.php:315
-msgid "Your password is incorrect. Please try it again."
-msgstr "Sua senha estΓ‘ incorreta. Por favor, tente novamente."
-
-#: includes/controller/users_controller.php:71
-msgid "User deleted."
-msgstr "UsuΓ‘rio deletado."
-
-#: includes/controller/users_controller.php:79 includes/view/User_view.php:121
-#, php-format
-msgid "Delete %s"
-msgstr "Apagar %s"
-
-#: includes/controller/users_controller.php:120
-msgid "Please enter a valid number of vouchers."
-msgstr "Por favor, entre com um nΓΊmero vΓ‘lido de vouchers."
-
-#: includes/controller/users_controller.php:131
-msgid "Saved the number of vouchers."
-msgstr "NΓΊmero de vouchers salvo."
-
-#: includes/controller/users_controller.php:139 includes/view/User_view.php:138
-#, php-format
-msgid "%s's vouchers"
-msgstr "Vouchers de %s"
-
-#: includes/controller/users_controller.php:151
-msgid "User not found."
-msgstr "UsuΓ‘rio nΓ£o encontrado."
-
-#: includes/controller/users_controller.php:205 includes/view/User_view.php:175
-msgid "All users"
-msgstr "Todos usuΓ‘rios"
-
-#: includes/controller/users_controller.php:217
-msgid "Token is not correct."
-msgstr "O token nΓ£o estΓ‘ correto."
-
-#: includes/controller/users_controller.php:227
-#: includes/pages/guest_login.php:102
-msgid "Your passwords don't match."
-msgstr "Suas senhas nΓ£o correspondem."
-
-#: includes/controller/users_controller.php:231
-msgid "Your password is to short (please use at least 6 characters)."
-msgstr "Sua senha Γ© muito curta (por favor use no mΓnimo 6 caracteres)."
-
-#: includes/controller/users_controller.php:236
-msgid "Password saved."
-msgstr "Sua senha foi salva."
-
-#: includes/controller/users_controller.php:257
-#: includes/controller/users_controller.php:261
-#: includes/pages/guest_login.php:67
-msgid "E-mail address is not correct."
-msgstr "E-mail nΓ£o estΓ‘ correto."
-
-#: includes/controller/users_controller.php:265
-#: includes/pages/guest_login.php:71
-msgid "Please enter your e-mail."
-msgstr "Por favor digite seu e-mail."
-
-#: includes/controller/users_controller.php:270
-#: includes/controller/users_controller.php:295
-msgid "Password recovery"
-msgstr "Recuperação de senha"
-
-#: includes/controller/users_controller.php:270
-#, php-format
-msgid "Please visit %s to recover your password."
-msgstr "Por favor visite %s para recuperar sua senha"
-
-#: includes/controller/users_controller.php:271
-msgid "We sent you an email containing your password recovery link."
-msgstr "Nós enviamos um email com o link para recuperação da sua senha."
-
-#: includes/helper/email_helper.php:12
-#, php-format
-msgid "Hi %s,"
-msgstr "Oi %s,"
-
-#: includes/helper/email_helper.php:12
-#, php-format
-msgid "here is a message for you from the %s:"
-msgstr "aqui estΓ‘ uma mensagem do %s para vocΓͺ:"
-
-#: includes/helper/email_helper.php:12
-#, php-format
-msgid ""
-"This email is autogenerated and has not been signed. You got this email "
-"because you are registered in the %s."
-msgstr "VocΓͺ recebeu esse email porque estΓ‘ registrado no %s."
-
-#: includes/mailer/shifts_mailer.php:10
-msgid "A Shift you are registered on has changed:"
-msgstr "Um turno em que vocΓͺ estava registrado foi modificado:"
-
-#: includes/mailer/shifts_mailer.php:14
-#, php-format
-msgid "* Shift type changed from %s to %s"
-msgstr "* Tipo de turno alterado de %s para %s"
-
-#: includes/mailer/shifts_mailer.php:19
-#, php-format
-msgid "* Shift title changed from %s to %s"
-msgstr "* TΓtulo do turno alterado de %s para %s"
-
-#: includes/mailer/shifts_mailer.php:24
-#, php-format
-msgid "* Shift Start changed from %s to %s"
-msgstr "* InΓcio do turno alterado de %s para %s"
-
-#: includes/mailer/shifts_mailer.php:29
-#, php-format
-msgid "* Shift End changed from %s to %s"
-msgstr "* TΓ©rmino do turno alterado de %s para %s"
-
-#: includes/mailer/shifts_mailer.php:34
-#, php-format
-msgid "* Shift Location changed from %s to %s"
-msgstr "* Local do turno alterado de %s para %s"
-
-#: includes/mailer/shifts_mailer.php:44
-msgid "The updated Shift:"
-msgstr "Turno atualizado:"
-
-#: includes/mailer/shifts_mailer.php:53
-msgid "Your Shift has changed"
-msgstr "O seu turno foi modificado"
-
-#: includes/mailer/shifts_mailer.php:62
-msgid "A Shift you are registered on was deleted:"
-msgstr "Um turno em que vocΓͺ estava registrado foi apagado:"
-
-#: includes/mailer/shifts_mailer.php:71
-msgid "Your Shift was deleted"
-msgstr "Seu turno foi apagado"
-
-#: includes/mailer/shifts_mailer.php:80
-msgid "You have been assigned to a Shift:"
-msgstr "VocΓͺ foi alocado a um turno:"
-
-#: includes/mailer/shifts_mailer.php:86
-msgid "Assigned to Shift"
-msgstr "Alocado ao turno"
-
-#: includes/mailer/shifts_mailer.php:94
-msgid "You have been removed from a Shift:"
-msgstr "VocΓͺ foi removido de um turno:"
-
-#: includes/mailer/shifts_mailer.php:100
-msgid "Removed from Shift"
-msgstr "Removido do turno"
-
-#: includes/mailer/users_mailer.php:7
-msgid "Your account has been deleted"
-msgstr "A sua conta foi deletada."
-
-#: includes/mailer/users_mailer.php:7
-msgid ""
-"Your angelsystem account has been deleted. If you have any questions "
-"regarding your account deletion, please contact heaven."
-msgstr ""
-"Sua conta engelsystem foi deletada. Se vocΓͺ tiver questΓ΅es sobre a deleção "
-"da sua conta, por favor entre em contato com o paraΓso."
-
-#: includes/pages/admin_active.php:4
-msgid "Active angels"
-msgstr "Anjos ativos"
-
-#: includes/pages/admin_active.php:29
-#, php-format
-msgid ""
-"At least %s angels are forced to be active. The number has to be greater."
-msgstr "No mΓnimo %s anjos precisam estar ativos. O nΓΊmero deve ser maior."
-
-#: includes/pages/admin_active.php:34
-msgid "Please enter a number of angels to be marked as active."
-msgstr "Por favor insira o nΓΊmero de anjos a marcar como ativos."
-
-#: includes/pages/admin_active.php:59
-msgid "Marked angels."
-msgstr "Anjos marcados."
-
-#: includes/pages/admin_active.php:61 includes/pages/admin_rooms.php:137
-#: includes/pages/admin_rooms.php:173 includes/pages/admin_shifts.php:266
-#: includes/view/UserAngelTypes_view.php:67 includes/view/User_view.php:124
-#: includes/view/User_view.php:141
-msgid "back"
-msgstr "voltar"
-
-#: includes/pages/admin_active.php:61
-msgid "apply"
-msgstr "aplicar"
-
-#: includes/pages/admin_active.php:71
-msgid "Angel has been marked as active."
-msgstr "Anjo marcado como ativo."
-
-#: includes/pages/admin_active.php:73 includes/pages/admin_active.php:83
-#: includes/pages/admin_active.php:103 includes/pages/admin_arrive.php:23
-#: includes/pages/admin_arrive.php:34
-msgid "Angel not found."
-msgstr "Anjo nΓ£o encontrado."
-
-#: includes/pages/admin_active.php:81
-msgid "Angel has been marked as not active."
-msgstr "Anjo marcado como nΓ£o ativo."
-
-#: includes/pages/admin_active.php:91
-msgid "Angel has got a t-shirt."
-msgstr "Anjo tem uma camiseta."
-
-#: includes/pages/admin_active.php:101
-msgid "Angel has got no t-shirt."
-msgstr "Anjo nΓ£o tem camiseta."
-
-#: includes/pages/admin_active.php:142
-msgid "set active"
-msgstr "definir ativo"
-
-#: includes/pages/admin_active.php:145
-msgid "remove active"
-msgstr "remover ativo"
-
-#: includes/pages/admin_active.php:146
-msgid "got t-shirt"
-msgstr "pegou camiseta"
-
-#: includes/pages/admin_active.php:149
-msgid "remove t-shirt"
-msgstr "remover camiseta"
-
-#: includes/pages/admin_active.php:168 includes/pages/admin_arrive.php:165
-#: includes/pages/admin_arrive.php:180 includes/pages/admin_arrive.php:195
-#: includes/view/AngelTypes_view.php:221 includes/view/AngelTypes_view.php:229
-#: includes/view/User_view.php:165
-msgid "Sum"
-msgstr "SomatΓ³ria"
-
-#: includes/pages/admin_active.php:175
-msgid "Search angel:"
-msgstr "Buscar Anjo:"
-
-#: includes/pages/admin_active.php:176
-msgid "Show all shifts"
-msgstr "Mostrar todos os turnos"
-
-#: includes/pages/admin_active.php:177 includes/pages/admin_arrive.php:141
-#: includes/pages/admin_arrive.php:142 includes/pages/admin_free.php:78
-#: includes/pages/admin_free.php:87 includes/pages/admin_log.php:23
-#: includes/pages/admin_log.php:24
-msgid "Search"
-msgstr "Buscar"
-
-#: includes/pages/admin_active.php:180
-msgid "How much angels should be active?"
-msgstr "Quantos anjos deverΓ£o estar ativos?"
-
-#: includes/pages/admin_active.php:181 includes/pages/admin_shifts.php:254
-#: includes/pages/admin_shifts.php:342
-msgid "Preview"
-msgstr "PrΓ©-visualizar"
-
-#: includes/pages/admin_active.php:185 includes/pages/admin_arrive.php:145
-msgid "Nickname"
-msgstr "Apelido"
-
-#: includes/pages/admin_active.php:186 includes/pages/admin_active.php:196
-#: includes/view/User_view.php:191
-msgid "Size"
-msgstr "Tamanho"
-
-#: includes/pages/admin_active.php:187 includes/pages/user_shifts.php:5
-#: includes/view/User_view.php:364
-msgid "Shifts"
-msgstr "Turnos"
-
-#: includes/pages/admin_active.php:188 includes/pages/admin_shifts.php:329
-msgid "Length"
-msgstr "Duração"
-
-#: includes/pages/admin_active.php:189
-msgid "Active?"
-msgstr "Ativo?"
-
-#: includes/pages/admin_active.php:190 includes/view/User_view.php:189
-msgid "Forced"
-msgstr "Forçados"
-
-#: includes/pages/admin_active.php:191
-msgid "T-shirt?"
-msgstr "Camiseta?"
-
-#: includes/pages/admin_active.php:194
-msgid "Shirt statistics"
-msgstr "EstatΓsticas de camiseta"
-
-#: includes/pages/admin_active.php:197
-msgid "Needed shirts"
-msgstr "Camisetas necessΓ‘rias"
-
-#: includes/pages/admin_active.php:198
-msgid "Given shirts"
-msgstr "Camisetas entregues"
-
-#: includes/pages/admin_arrive.php:4
-msgid "Arrive angels"
-msgstr "Anjos que chegaram"
-
-#: includes/pages/admin_arrive.php:20
-msgid "Reset done. Angel has not arrived."
-msgstr "Reset realizado. Anjo nΓ£o chegou."
-
-#: includes/pages/admin_arrive.php:31
-msgid "Angel has been marked as arrived."
-msgstr "Chegada do anjo registrada."
-
-#: includes/pages/admin_arrive.php:71 includes/view/UserAngelTypes_view.php:9
-#: includes/view/UserAngelTypes_view.php:20
-#: includes/view/UserAngelTypes_view.php:31
-#: includes/view/UserAngelTypes_view.php:42
-#: includes/view/UserAngelTypes_view.php:53
-msgid "yes"
-msgstr "sim"
-
-#: includes/pages/admin_arrive.php:72
-msgid "reset"
-msgstr "resetar"
-
-#: includes/pages/admin_arrive.php:72 includes/pages/admin_arrive.php:156
-#: includes/pages/admin_arrive.php:171 includes/pages/admin_arrive.php:186
-#: includes/view/User_view.php:330
-msgid "arrived"
-msgstr "chegou"
-
-#: includes/pages/admin_arrive.php:146
-msgid "Planned arrival"
-msgstr "Chegada planejada"
-
-#: includes/pages/admin_arrive.php:147
-msgid "Arrived?"
-msgstr "Chegou?"
-
-#: includes/pages/admin_arrive.php:148
-msgid "Arrival date"
-msgstr "Data de chegada"
-
-#: includes/pages/admin_arrive.php:149
-msgid "Planned departure"
-msgstr "SaΓda planejada"
-
-#: includes/pages/admin_arrive.php:154
-msgid "Planned arrival statistics"
-msgstr "EstatΓsticas de chegadas planejadas"
-
-#: includes/pages/admin_arrive.php:157 includes/pages/admin_arrive.php:172
-#: includes/pages/admin_arrive.php:187
-msgid "arrived sum"
-msgstr "soma dos que chegaram"
-
-#: includes/pages/admin_arrive.php:163 includes/pages/admin_arrive.php:178
-#: includes/pages/admin_arrive.php:193 includes/pages/admin_news.php:30
-#: includes/pages/user_messages.php:76
-msgid "Date"
-msgstr "Data"
-
-#: includes/pages/admin_arrive.php:164 includes/pages/admin_arrive.php:179
-#: includes/pages/admin_arrive.php:194
-msgid "Count"
-msgstr "Contar"
-
-#: includes/pages/admin_arrive.php:169
-msgid "Arrival statistics"
-msgstr "EstatΓsticas de chegadas"
-
-#: includes/pages/admin_arrive.php:184
-msgid "Planned departure statistics"
-msgstr "EstatΓsticas de saΓdas planejadas"
-
-#: includes/pages/admin_free.php:4
-msgid "Free angels"
-msgstr "Anjos livres"
-
-#: includes/pages/admin_free.php:81 includes/view/ShiftTypes_view.php:36
-#: includes/view/UserAngelTypes_view.php:70
-msgid "Angeltype"
-msgstr "Tipo de anjo"
-
-#: includes/pages/admin_free.php:84
-msgid "Only confirmed"
-msgstr "Somente confirmados"
-
-#: includes/pages/admin_free.php:92 includes/pages/guest_login.php:225
-#: includes/pages/guest_login.php:354 includes/view/AngelTypes_view.php:177
-#: includes/view/AngelTypes_view.php:190 includes/view/User_view.php:40
-#: includes/view/User_view.php:97 includes/view/User_view.php:181
-msgid "Nick"
-msgstr "Apelido"
-
-#: includes/pages/admin_free.php:94 includes/pages/guest_login.php:255
-#: includes/view/AngelTypes_view.php:178 includes/view/AngelTypes_view.php:191
-#: includes/view/User_view.php:47 includes/view/User_view.php:184
-msgid "DECT"
-msgstr "DECT"
-
-#: includes/pages/admin_free.php:95 includes/pages/guest_login.php:264
-#: includes/view/User_view.php:52
-msgid "Jabber"
-msgstr "Jabber"
-
-#: includes/pages/admin_free.php:96 includes/pages/guest_login.php:228
-#: includes/view/User_view.php:49 includes/view/User_view.php:386
-msgid "E-Mail"
-msgstr "E-Mail"
-
-#: includes/pages/admin_groups.php:4
-msgid "Grouprights"
-msgstr "Direitos de grupo"
-
-#: includes/pages/admin_groups.php:29 includes/pages/admin_import.php:145
-#: includes/pages/admin_import.php:149 includes/pages/admin_rooms.php:143
-#: includes/pages/admin_rooms.php:189 includes/view/AngelTypes_view.php:66
-#: includes/view/AngelTypes_view.php:268 includes/view/ShiftTypes_view.php:35
-#: includes/view/ShiftTypes_view.php:78 includes/view/User_view.php:183
-msgid "Name"
-msgstr "Nome"
-
-#: includes/pages/admin_groups.php:30
-msgid "Privileges"
-msgstr "PrivilΓ©gios"
-
-#: includes/pages/admin_groups.php:55
-msgid "Edit group"
-msgstr "Editar grupo"
-
-#: includes/pages/admin_import.php:4 includes/pages/admin_rooms.php:144
-#: includes/pages/admin_rooms.php:190
-msgid "Frab import"
-msgstr "Importação Frab"
-
-#: includes/pages/admin_import.php:26
-msgid "Webserver has no write-permission on import directory."
-msgstr ""
-"O servidor web não possui permissão de escrita no diretório de importação."
-
-#: includes/pages/admin_import.php:54 includes/pages/admin_import.php:118
-#: includes/pages/admin_import.php:196 includes/pages/admin_shifts.php:53
-#: includes/pages/admin_shifts.php:59
-msgid "Please select a shift type."
-msgstr "Por favor selecione um tipo de turno."
-
-#: includes/pages/admin_import.php:61 includes/pages/admin_import.php:125
-#: includes/pages/admin_import.php:203
-msgid "Please enter an amount of minutes to add to a talk's begin."
-msgstr ""
-"Por favor insira um nΓΊmero de minutos para adicionar ao inΓcio de uma "
-"palestra."
-
-#: includes/pages/admin_import.php:68 includes/pages/admin_import.php:132
-#: includes/pages/admin_import.php:210
-msgid "Please enter an amount of minutes to add to a talk's end."
-msgstr ""
-"Por favor insira um nΓΊmero de minutos para adicionar ao tΓ©rmino de uma "
-"palestra."
-
-#: includes/pages/admin_import.php:76
-msgid "No valid xml/xcal file provided."
-msgstr "Nenhum arquivo xml/xcal vΓ‘lido foi fornecido."
-
-#: includes/pages/admin_import.php:81
-msgid "File upload went wrong."
-msgstr "Falha no upload do arquivo."
-
-#: includes/pages/admin_import.php:85
-msgid "Please provide some data."
-msgstr "Por favor insira alguns dados."
-
-#: includes/pages/admin_import.php:93 includes/pages/admin_import.php:140
-#: includes/pages/admin_import.php:253
-msgid "File Upload"
-msgstr "Enviar arquivo"
-
-#: includes/pages/admin_import.php:93 includes/pages/admin_import.php:140
-#: includes/pages/admin_import.php:253
-msgid "Validation"
-msgstr "Validação"
-
-#: includes/pages/admin_import.php:93 includes/pages/admin_import.php:102
-#: includes/pages/admin_import.php:140 includes/pages/admin_import.php:179
-#: includes/pages/admin_import.php:253
-msgid "Import"
-msgstr "Importar"
-
-#: includes/pages/admin_import.php:97
-msgid ""
-"This import will create/update/delete rooms and shifts by given FRAB-export "
-"file. The needed file format is xcal."
-msgstr ""
-"Esta importação irÑ criar/atualizar/deletar salas e turnos a partir do "
-"arquivo FRAB-Export. O formato necessΓ‘rio Γ© xcal."
-
-#: includes/pages/admin_import.php:99
-msgid "Add minutes to start"
-msgstr "Adicionar minutos ao inΓcio"
-
-#: includes/pages/admin_import.php:100
-msgid "Add minutes to end"
-msgstr "Adicionar minutos ao fim"
-
-#: includes/pages/admin_import.php:101
-msgid "xcal-File (.xcal)"
-msgstr "Adicionar minutos ao fim"
-
-#: includes/pages/admin_import.php:111 includes/pages/admin_import.php:185
-msgid "Missing import file."
-msgstr "Arquivo para importar nΓ£o encontrado."
-
-#: includes/pages/admin_import.php:144
-msgid "Rooms to create"
-msgstr "Salas para criar"
-
-#: includes/pages/admin_import.php:148
-msgid "Rooms to delete"
-msgstr "Salas para apagar"
-
-#: includes/pages/admin_import.php:152
-msgid "Shifts to create"
-msgstr "Turnos para criar"
-
-#: includes/pages/admin_import.php:154 includes/pages/admin_import.php:163
-#: includes/pages/admin_import.php:172 includes/view/User_view.php:366
-msgid "Day"
-msgstr "Dia"
-
-#: includes/pages/admin_import.php:155 includes/pages/admin_import.php:164
-#: includes/pages/admin_import.php:173 includes/pages/admin_shifts.php:324
-#: includes/view/Shifts_view.php:66
-msgid "Start"
-msgstr "InΓcio"
-
-#: includes/pages/admin_import.php:156 includes/pages/admin_import.php:165
-#: includes/pages/admin_import.php:174 includes/pages/admin_shifts.php:325
-#: includes/view/Shifts_view.php:74
-msgid "End"
-msgstr "Fim"
-
-#: includes/pages/admin_import.php:157 includes/pages/admin_import.php:166
-#: includes/pages/admin_import.php:175
-msgid "Shift type"
-msgstr "Tipo de turno"
-
-#: includes/pages/admin_import.php:159 includes/pages/admin_import.php:168
-#: includes/pages/admin_import.php:177 includes/pages/admin_shifts.php:321
-msgid "Room"
-msgstr "Sala"
-
-#: includes/pages/admin_import.php:161
-msgid "Shifts to update"
-msgstr "Turnos para atualizar"
-
-#: includes/pages/admin_import.php:170
-msgid "Shifts to delete"
-msgstr "Turnos para deletar"
-
-#: includes/pages/admin_import.php:254
-msgid "It's done!"
-msgstr "EstΓ‘ feito!"
-
-#: includes/pages/admin_log.php:4
-msgid "Log"
-msgstr "Log"
-
-#: includes/pages/admin_news.php:10
-msgid "Edit news entry"
-msgstr "Editar notΓcia"
-
-#: includes/pages/admin_news.php:31
-msgid "Author"
-msgstr "Autor"
-
-#: includes/pages/admin_news.php:32 includes/pages/user_news.php:161
-msgid "Subject"
-msgstr "Assunto"
-
-#: includes/pages/admin_news.php:34 includes/pages/user_news.php:163
-msgid "Meeting"
-msgstr "ReuniΓ£o"
-
-#: includes/pages/admin_news.php:38 includes/pages/admin_rooms.php:177
-#: includes/view/User_view.php:129
-msgid "Delete"
-msgstr "Apagar"
-
-#: includes/pages/admin_news.php:52
-msgid "News entry updated."
-msgstr "NotΓcia atualizada."
-
-#: includes/pages/admin_news.php:61
-msgid "News entry deleted."
-msgstr "NotΓcia deletada."
-
-#: includes/pages/admin_questions.php:4
-msgid "Answer questions"
-msgstr "Responder perguntas"
-
-#: includes/pages/admin_questions.php:18
-msgid "There are unanswered questions!"
-msgstr "Existem perguntas nΓ£o respondidas!"
-
-#: includes/pages/admin_questions.php:61
-msgid "Unanswered questions"
-msgstr "Perguntas nΓ£o respondidas"
-
-#: includes/pages/admin_questions.php:63 includes/pages/admin_questions.php:70
-msgid "From"
-msgstr "De"
-
-#: includes/pages/admin_questions.php:64 includes/pages/admin_questions.php:71
-#: includes/view/Questions_view.php:19 includes/view/Questions_view.php:24
-msgid "Question"
-msgstr "QuestΓ£o"
-
-#: includes/pages/admin_questions.php:65 includes/pages/admin_questions.php:73
-#: includes/view/Questions_view.php:26
-msgid "Answer"
-msgstr "Resposta"
-
-#: includes/pages/admin_questions.php:68 includes/view/Questions_view.php:22
-msgid "Answered questions"
-msgstr "Perguntas respondidas"
-
-#: includes/pages/admin_questions.php:72 includes/view/Questions_view.php:25
-msgid "Answered by"
-msgstr "Respondido por"
-
-#: includes/pages/admin_rooms.php:4 includes/pages/user_shifts.php:159
-#: includes/sys_menu.php:176
-msgid "Rooms"
-msgstr "Salas"
-
-#: includes/pages/admin_rooms.php:67
-msgid "This name is already in use."
-msgstr "Este nome jΓ‘ estΓ‘ em uso."
-
-#: includes/pages/admin_rooms.php:97
-#, php-format
-msgid "Please enter needed angels for type %s."
-msgstr "Por favor insira os anjos necessΓ‘rios de tipo %s."
-
-#: includes/pages/admin_rooms.php:124
-msgid "Room saved."
-msgstr "Sala salva"
-
-#: includes/pages/admin_rooms.php:145 includes/pages/admin_rooms.php:191
-msgid "Public"
-msgstr "PΓΊblico"
-
-#: includes/pages/admin_rooms.php:146
-msgid "Room number"
-msgstr "NΓΊmero da sala"
-
-#: includes/pages/admin_rooms.php:151
-msgid "Needed angels:"
-msgstr "Anjos necessΓ‘rios:"
-
-#: includes/pages/admin_rooms.php:167
-#, php-format
-msgid "Room %s deleted."
-msgstr "Sala %s deletada."
-
-#: includes/pages/admin_rooms.php:175
-#, php-format
-msgid "Do you want to delete room %s?"
-msgstr "VocΓͺ quer deletar as salas %s?"
-
-#: includes/pages/admin_rooms.php:185
-msgid "add"
-msgstr "adicionar"
-
-#: includes/pages/admin_shifts.php:4
-msgid "Create shifts"
-msgstr "Criar turnos"
-
-#: includes/pages/admin_shifts.php:71
-msgid "Please select a location."
-msgstr "Por favor, selecione uma localização."
-
-#: includes/pages/admin_shifts.php:78
-msgid "Please select a start time."
-msgstr "Por favor, selecione um horΓ‘rio de inΓcio."
-
-#: includes/pages/admin_shifts.php:85
-msgid "Please select an end time."
-msgstr "Por favor, selecione um horΓ‘rio de tΓ©rmino."
-
-#: includes/pages/admin_shifts.php:90
-msgid "The shifts end has to be after its start."
-msgstr "O tΓ©rmino do turno deve ser posterior ao seu inΓcio."
-
-#: includes/pages/admin_shifts.php:102
-msgid "Please enter a shift duration in minutes."
-msgstr "Por favor insira a duração do turno em minutos."
-
-#: includes/pages/admin_shifts.php:110
-msgid "Please split the shift-change hours by colons."
-msgstr "Por favor divida os horΓ‘rios de mudanΓ§a de turno por vΓrgulas."
-
-#: includes/pages/admin_shifts.php:115
-msgid "Please select a mode."
-msgstr "Por favor selecione um modo."
-
-#: includes/pages/admin_shifts.php:128
-#, php-format
-msgid "Please check the needed angels for team %s."
-msgstr "Por favor confira os anjos necessΓ‘rios para o time %s."
-
-#: includes/pages/admin_shifts.php:133
-msgid "There are 0 angels needed. Please enter the amounts of needed angels."
-msgstr ""
-"HΓ‘ 0 anjos necessΓ‘rios. Por favor insira o nΓΊmero de anjos necessΓ‘rios."
-
-#: includes/pages/admin_shifts.php:137
-msgid "Please select a mode for needed angels."
-msgstr "Por favor escolha um modo para os anjos necessΓ‘rios."
-
-#: includes/pages/admin_shifts.php:141
-msgid "Please select needed angels."
-msgstr "Por favor selecione os anjos necessΓ‘rios."
-
-#: includes/pages/admin_shifts.php:268
-msgid "Time and location"
-msgstr "HorÑrio e localização"
-
-#: includes/pages/admin_shifts.php:269
-msgid "Type and title"
-msgstr "Tipo e tΓtulo"
-
-#: includes/pages/admin_shifts.php:326
-msgid "Mode"
-msgstr "Modo"
-
-#: includes/pages/admin_shifts.php:327
-msgid "Create one shift"
-msgstr "Criar um turno"
-
-#: includes/pages/admin_shifts.php:328
-msgid "Create multiple shifts"
-msgstr "Criar mΓΊltiplos turnos"
-
-#: includes/pages/admin_shifts.php:330
-msgid "Create multiple shifts with variable length"
-msgstr "Criar múltiplos turnos com duração variÑvel"
-
-#: includes/pages/admin_shifts.php:331
-msgid "Shift change hours"
-msgstr "Mudança de horÑrio do turno"
-
-#: includes/pages/admin_shifts.php:335
-msgid "Take needed angels from room settings"
-msgstr "Pegar os anjos necessÑrios a partir das configuraçáes das salas"
-
-#: includes/pages/admin_shifts.php:336
-msgid "The following angels are needed"
-msgstr "Os seguintes anjos sΓ£o necessΓ‘rios"
-
-#: includes/pages/admin_user.php:4
-msgid "All Angels"
-msgstr "Todos os anjos"
-
-#: includes/pages/admin_user.php:20
-msgid "This user does not exist."
-msgstr "Esse usuΓ‘rio nΓ£o existe."
-
-#: includes/pages/admin_user.php:46 includes/view/AngelTypes_view.php:67
-#: includes/view/AngelTypes_view.php:68 includes/view/AngelTypes_view.php:69
-msgid "Yes"
-msgstr "Sim"
-
-#: includes/pages/admin_user.php:47 includes/view/AngelTypes_view.php:67
-#: includes/view/AngelTypes_view.php:68 includes/view/AngelTypes_view.php:69
-msgid "No"
-msgstr "NΓ£o"
-
-#: includes/pages/admin_user.php:60
-msgid "Force active"
-msgstr "Forçar ativação"
-
-#: includes/pages/admin_user.php:79
-msgid ""
-"Please visit the angeltypes page or the users profile to manage users "
-"angeltypes."
-msgstr ""
-"Por favor visite a pΓ‘gina de tipos de anjo ou o perfil do usuΓ‘rio para "
-"gerenciar\n"
-"seus tipos de anjo."
-
-#: includes/pages/admin_user.php:204
-msgid "Edit user"
-msgstr "Editar usuΓ‘rio"
-
-#: includes/pages/guest_credits.php:3
-msgid "Credits"
-msgstr "CrΓ©ditos"
-
-#: includes/pages/guest_login.php:4 includes/pages/guest_login.php:349
-#: includes/pages/guest_login.php:356 includes/view/User_view.php:95
-#: includes/view/User_view.php:99
-msgid "Login"
-msgstr "Login"
-
-#: includes/pages/guest_login.php:8 includes/pages/guest_login.php:285
-msgid "Register"
-msgstr "Registrar"
-
-#: includes/pages/guest_login.php:12
-msgid "Logout"
-msgstr "Logout"
-
-#: includes/pages/guest_login.php:56
-#, php-format
-msgid "Your nick \"%s\" already exists."
-msgstr "Seu apelido \"%s\" jΓ‘ existe."
-
-#: includes/pages/guest_login.php:60
-#, php-format
-msgid "Your nick "%s" is too short (min. 2 characters)."
-msgstr "Seu apelido "%s" Γ© muito pequeno (mΓnimo 2 caracteres)."
-
-#: includes/pages/guest_login.php:86
-msgid "Please check your jabber account information."
-msgstr "Por favor verifique a informação da sua conta jabber."
-
-#: includes/pages/guest_login.php:95
-msgid "Please select your shirt size."
-msgstr "Por favor escolha o tamanho da camisa."
-
-#: includes/pages/guest_login.php:106
-#, php-format
-msgid "Your password is too short (please use at least %s characters)."
-msgstr "Sua senha Γ© muito curta (por favor use pelo menos %s caracteres)."
-
-#: includes/pages/guest_login.php:115
-msgid ""
-"Please enter your planned date of arrival. It should be after the buildup "
-"start date and before teardown end date."
-msgstr ""
-"Por favor insira a data planejada para sua chegada. Ela deve ser posterior Γ "
-"data de montagem e anterior Γ data de desmontagem."
-
-#: includes/pages/guest_login.php:189
-msgid "Angel registration successful!"
-msgstr "Conta criada com sucesso!"
-
-#: includes/pages/guest_login.php:217
-msgid ""
-"By completing this form you're registering as a Chaos-Angel. This script "
-"will create you an account in the angel task scheduler."
-msgstr ""
-"Ao completar esse formulΓ‘rio vocΓͺ estarΓ‘ se registrando como um voluntΓ‘rio. "
-"Esse script criarΓ‘ uma conta no sistema."
-
-#: includes/pages/guest_login.php:229 includes/view/User_view.php:50
-#, php-format
-msgid ""
-"The %s is allowed to send me an email (e.g. when my shifts change)"
-msgstr ""
-"Permito que o %s me envie emails (por exemplo, quando meus turnos "
-"mudam)"
-
-#: includes/pages/guest_login.php:230 includes/view/User_view.php:51
-msgid "Allow heaven angels to contact you by e-mail."
-msgstr "Permito que humanos me enviem emails"
-
-#: includes/pages/guest_login.php:235 includes/view/User_view.php:43
-msgid "Planned date of arrival"
-msgstr "Data planejada de chegada"
-
-#: includes/pages/guest_login.php:238 includes/view/User_view.php:54
-msgid "Shirt size"
-msgstr "Tamanho da camiseta"
-
-#: includes/pages/guest_login.php:243 includes/pages/guest_login.php:355
-#: includes/view/User_view.php:98 includes/view/User_view.php:400
-msgid "Password"
-msgstr "Senha"
-
-#: includes/pages/guest_login.php:246 includes/view/User_view.php:401
-msgid "Confirm password"
-msgstr "Confirme a senha"
-
-#: includes/pages/guest_login.php:249
-msgid "What do you want to do?"
-msgstr "O que vocΓͺ gostaria de fazer?"
-
-#: includes/pages/guest_login.php:249
-msgid "Description of job types"
-msgstr "Descrição dos trabalhos"
-
-#: includes/pages/guest_login.php:250
-msgid ""
-"Restricted angel types need will be confirmed later by a supporter. You can "
-"change your selection in the options section."
-msgstr ""
-"Tipos de anjo restritos precisam de confirmação posterior de um apoiador. "
-"VocΓͺ pode \n"
-"mudar sua seleção na seção 'Opçáes'."
-
-#: includes/pages/guest_login.php:258 includes/view/User_view.php:48
-msgid "Mobile"
-msgstr "Celular"
-
-#: includes/pages/guest_login.php:261 includes/view/User_view.php:46
-msgid "Phone"
-msgstr "Telefone"
-
-#: includes/pages/guest_login.php:267 includes/view/User_view.php:42
-msgid "First name"
-msgstr "Nome"
-
-#: includes/pages/guest_login.php:270 includes/view/User_view.php:41
-msgid "Last name"
-msgstr "Sobrenome"
-
-#: includes/pages/guest_login.php:275 includes/view/User_view.php:45
-msgid "Age"
-msgstr "Idade"
-
-#: includes/pages/guest_login.php:278 includes/view/User_view.php:53
-msgid "Hometown"
-msgstr "Cidade"
-
-#: includes/pages/guest_login.php:281 includes/view/User_view.php:39
-msgid "Entry required!"
-msgstr "Campo necessΓ‘rio!"
-
-#: includes/pages/guest_login.php:319
-msgid "auth.no-password"
-msgstr "Por favor digite uma senha."
-
-#: includes/pages/guest_login.php:323
-msgid "auth.not-found"
-msgstr ""
-"Nenhum usuΓ‘rio foi encontrado. Por favor tente novamente. \n"
-"Se vocΓͺ continuar com problemas, pergunte a um Dispatcher."
-
-#: includes/pages/guest_login.php:327
-msgid "auth.no-nickname"
-msgstr "Por favor digite um apelido."
-
-#: includes/pages/guest_login.php:358 includes/view/User_view.php:101
-msgid "I forgot my password"
-msgstr "Esqueci minha senha"
-
-#: includes/pages/guest_login.php:363 includes/view/User_view.php:103
-msgid "Please note: You have to activate cookies!"
-msgstr "Nota: vocΓͺ precisa habilitar cookies!"
-
-#: includes/pages/guest_login.php:374 includes/view/User_view.php:107
-msgid "What can I do?"
-msgstr "O que posso fazer?"
-
-#: includes/pages/guest_login.php:375 includes/view/User_view.php:108
-msgid "Please read about the jobs you can do to help us."
-msgstr "Por favor leia sobre as tarefas que pode realizar para nos ajudar."
-
-#: includes/pages/guest_login.php:390
-msgid "Please sign up, if you want to help us!"
-msgstr "Se vocΓͺ quer nos ajudar, por favor se registre!"
-
-#: includes/pages/user_messages.php:26
-msgid "Select recipient..."
-msgstr "Selecionar recipiente..."
-
-#: includes/pages/user_messages.php:62
-msgid "mark as read"
-msgstr "marcar como lido"
-
-#: includes/pages/user_messages.php:65
-msgid "delete message"
-msgstr "apagar mensagem"
-
-#: includes/pages/user_messages.php:72
-#, php-format
-msgid "Hello %s, here can you leave messages for other angels"
-msgstr "Oi %s, aqui vocΓͺ pode deixar mensagens para outros anjos."
-
-#: includes/pages/user_messages.php:75
-msgid "New"
-msgstr "Nova"
-
-#: includes/pages/user_messages.php:77
-msgid "Transmitted"
-msgstr "Enviado"
-
-#: includes/pages/user_messages.php:78
-msgid "Recipient"
-msgstr "Recipiente"
-
-#: includes/pages/user_messages.php:90 includes/pages/user_messages.php:106
-msgid "Incomplete call, missing Message ID."
-msgstr "Chamada incompleta, falta o ID da Mensagem."
-
-#: includes/pages/user_messages.php:98 includes/pages/user_messages.php:114
-msgid "No Message found."
-msgstr "Nenhuma mensagem encontrada."
-
-#: includes/pages/user_messages.php:122
-msgid "Transmitting was terminated with an Error."
-msgstr "TransmissΓ£o encerrada com um erro."
-
-#: includes/pages/user_messages.php:127
-msgid "Wrong action."
-msgstr "Ação errada."
-
-#: includes/pages/user_myshifts.php:23
-msgid "Key changed."
-msgstr "Chave modificada."
-
-#: includes/pages/user_myshifts.php:26 includes/view/User_view.php:335
-msgid "Reset API key"
-msgstr "Resetar a chave API"
-
-#: includes/pages/user_myshifts.php:27
-msgid ""
-"If you reset the key, the url to your iCal- and JSON-export and your atom/rss "
-"feed changes! You have to update it in every application using one of these "
-"exports."
-msgstr ""
-"Se vocΓͺ reconfigurar a chave, as urls para seu iCal, a exportação em formato "
-"JSON \n"
-"e seu feed atom/rss serΓ‘ alterada! VocΓͺ precisarΓ‘ atualizΓ‘-las em todas as "
-"aplicaçáes que estiverem \n"
-"usando uma delas."
-
-#: includes/pages/user_myshifts.php:28
-msgid "Continue"
-msgstr "Continuar"
-
-#: includes/pages/user_myshifts.php:60
-msgid "Please enter a freeload comment!"
-msgstr "Por favor insira um comentΓ‘rio freeload!"
-
-#: includes/pages/user_myshifts.php:79
-msgid "Shift saved."
-msgstr "Turno salvo."
-
-#: includes/pages/user_myshifts.php:107
-msgid "Shift canceled."
-msgstr "Turno cancelado."
-
-#: includes/pages/user_myshifts.php:109
-msgid ""
-"It's too late to sign yourself off the shift. If neccessary, ask the "
-"dispatcher to do so."
-msgstr ""
-"EstÑ muito tarde para se retirar deste turno. Se necessÑrio, peça a \n"
-"um dispatcher para removΓͺ-lo."
-
-#: includes/pages/user_news.php:4
-msgid "News comments"
-msgstr "Novos comentΓ‘rios"
-
-#: includes/pages/user_news.php:8
-msgid "News"
-msgstr "Novidades"
-
-#: includes/pages/user_news.php:12
-msgid "Meetings"
-msgstr "Encontros"
-
-#: includes/pages/user_news.php:68
-msgid "Comments"
-msgstr "ComentΓ‘rios"
-
-#: includes/pages/user_news.php:86 includes/pages/user_news.php:127
-msgid "Entry saved."
-msgstr "Entrada salva."
-
-#: includes/pages/user_news.php:104
-msgid "New Comment:"
-msgstr "Novo comentΓ‘rio:"
-
-#: includes/pages/user_news.php:110
-msgid "Invalid request."
-msgstr "Requisição invÑlida."
-
-#: includes/pages/user_news.php:158
-msgid "Create news:"
-msgstr "Criar novidades:"
-
-#: includes/pages/user_questions.php:4 includes/view/Questions_view.php:29
-msgid "Ask the Heaven"
-msgstr "Pergunte ao paraΓso"
-
-#: includes/pages/user_questions.php:27
-msgid "Unable to save question."
-msgstr "NΓ£o foi possΓvel salvar a sua pergunta."
-
-#: includes/pages/user_questions.php:29
-msgid "You question was saved."
-msgstr "Sua pergunta foi salva."
-
-#: includes/pages/user_questions.php:33
-msgid "Please enter a question!"
-msgstr "Por favor digite sua dΓΊvida!"
-
-#: includes/pages/user_questions.php:41
-msgid "Incomplete call, missing Question ID."
-msgstr "Chamada incompletada, falta o ID da pergunta."
-
-#: includes/pages/user_questions.php:50
-msgid "No question found."
-msgstr "Nenhuma dΓΊvida encontrada."
-
-#: includes/view/User_view.php:332
-msgid "Settings"
-msgstr "Configuraçáes"
-
-msgid ""
-"Please enter your planned date of departure. It should be after your planned "
-"arrival date and after buildup start date and before teardown end date."
-msgstr ""
-"Por favor digite sua data de saΓda. Ela deve ser posterior Γ data de "
-"chegada\n"
-"e ao inΓcio da montagem, e anterior Γ data de desmontagem."
-
-msgid "-> not OK. Please try again."
-msgstr "-> nΓ£o OK. Por favor tente novamente."
-
-msgid "Failed setting password."
-msgstr "A alteração da senha falhaou."
-
-#: includes/pages/user_shifts.php:82
-msgid "The administration has not configured any rooms yet."
-msgstr "O administrador nΓ£o configurou nenhuma sala ainda."
-
-#: includes/pages/user_shifts.php:94
-msgid "The administration has not configured any shifts yet."
-msgstr "O administrador nΓ£o configurou nenhum turno ainda."
-
-#: includes/pages/user_shifts.php:104
-msgid ""
-"The administration has not configured any angeltypes yet - or you are not "
-"subscribed to any angeltype."
-msgstr ""
-"O administrador ainda nΓ£o configurou os tipos de anjos - ou vocΓͺ nΓ£o estΓ‘\n"
-"inscrito em nenhum tipo de anjo."
-
-#: includes/pages/user_shifts.php:142
-msgid "occupied"
-msgstr "ocupado"
-
-#: includes/pages/user_shifts.php:146
-msgid "free"
-msgstr "livre"
-
-#: includes/pages/user_shifts.php:165
-msgid "Occupancy"
-msgstr "Ocupação"
-
-#: includes/pages/user_shifts.php:166
-msgid ""
-"The tasks shown here are influenced by the angeltypes you joined already!"
-msgstr ""
-"As tarefas mostradas aqui sΓ£o influenciadas pelos tipos de anjos de que vocΓͺ "
-"jΓ‘ faz parte!"
-
-#: includes/pages/user_shifts.php:166
-msgid "Description of the jobs."
-msgstr "Descrição dos trabalhos."
-
-#: includes/pages/user_shifts.php:168
-msgid "iCal export"
-msgstr "Exportar iCal"
-
-#: includes/pages/user_shifts.php:168
-#, php-format
-msgid ""
-"Export of shown shifts. iCal format or JSON format available (please keep secret, otherwise reset the api key)."
-msgstr ""
-"Exportar os turnos mostrados. formato iCal ou formato JSON disponΓveis (por favor mantenha secreto, ou resete a chave API)."
-
-#: includes/pages/user_shifts.php:169
-msgid "Filter"
-msgstr "Filtro"
-
-#: includes/pages/user_shifts.php:191 includes/view/ShiftTypes_view.php:23
-msgid "All"
-msgstr "Todos"
-
-#: includes/pages/user_shifts.php:192
-msgid "None"
-msgstr "Nenhum"
-
-#: includes/sys_menu.php:139
-msgid "Admin"
-msgstr "Admin"
-
-#: includes/sys_menu.php:163
-msgid "Manage rooms"
-msgstr "Gerenciar salas"
-
-#: includes/sys_template.php:166
-msgid "No data found."
-msgstr "Nenhum dado encontrado."
-
-#: includes/view/AngelTypes_view.php:27 includes/view/AngelTypes_view.php:244
-msgid "Unconfirmed"
-msgstr "NΓ£o confirmado"
-
-#: includes/view/AngelTypes_view.php:29 includes/view/AngelTypes_view.php:33
-msgid "Supporter"
-msgstr "Apoiador"
-
-#: includes/view/AngelTypes_view.php:31 includes/view/AngelTypes_view.php:35
-msgid "Member"
-msgstr "Membro"
-
-#: includes/view/AngelTypes_view.php:42
-#, php-format
-msgid "Do you want to delete angeltype %s?"
-msgstr "VocΓͺ deseja apagar o tipo de anjo %s?"
-
-#: includes/view/AngelTypes_view.php:44 includes/view/ShiftTypes_view.php:15
-#: includes/view/UserAngelTypes_view.php:8
-#: includes/view/UserAngelTypes_view.php:19
-#: includes/view/UserAngelTypes_view.php:30
-#: includes/view/UserAngelTypes_view.php:41
-#: includes/view/UserAngelTypes_view.php:52
-#: includes/view/UserAngelTypes_view.php:82
-msgid "cancel"
-msgstr "cancelar"
-
-#: includes/view/AngelTypes_view.php:67 includes/view/AngelTypes_view.php:269
-msgid "Restricted"
-msgstr "Restrito"
-
-#: includes/view/AngelTypes_view.php:68
-msgid "No Self Sign Up"
-msgstr "Auto inscrição não permitida"
-
-#: includes/view/AngelTypes_view.php:69
-msgid "Requires driver license"
-msgstr "Requer carteira de motorista"
-
-#: includes/view/AngelTypes_view.php:73
-msgid ""
-"Restricted angel types can only be used by an angel if enabled by a "
-"supporter (double opt-in)."
-msgstr ""
-"Tipos de anjo restritos sΓ³ podem ser usados por um anjo quando autorizados "
-"por \n"
-"um apoiador (duplo opt-in)."
-
-#: includes/view/AngelTypes_view.php:74 includes/view/AngelTypes_view.php:205
-#: includes/view/ShiftTypes_view.php:37 includes/view/ShiftTypes_view.php:58
-#: includes/view/Shifts_view.php:92
-msgid "Description"
-msgstr "Descrição"
-
-#: includes/view/AngelTypes_view.php:75 includes/view/ShiftTypes_view.php:38
-msgid "Please use markdown for the description."
-msgstr "Por favor use markdown para a descrição."
-
-#: includes/view/AngelTypes_view.php:90
-msgid "my driving license"
-msgstr "Minha carteira de motorista"
-
-#: includes/view/AngelTypes_view.php:97
-msgid ""
-"This angeltype requires a driver license. Please enter your driver license "
-"information!"
-msgstr ""
-"Esse tipo de anjo requer carteira de motorista. Por favor digite sua "
-"carteira de motorista."
-
-#: includes/view/AngelTypes_view.php:101
-#, php-format
-msgid ""
-"You are unconfirmed for this angeltype. Please go to the introduction for %s "
-"to get confirmed."
-msgstr ""
-"VocΓͺ nΓ£o estΓ‘ confirmado para esse tipo de anjo. Por favor vΓ‘ para a "
-"apresentação para %s\n"
-"para ser confirmado."
-
-#: includes/view/AngelTypes_view.php:140
-msgid "confirm"
-msgstr "confirmar"
-
-#: includes/view/AngelTypes_view.php:141
-msgid "deny"
-msgstr "rejeitar"
-
-#: includes/view/AngelTypes_view.php:157
-msgid "remove"
-msgstr "remover"
-
-#: includes/view/AngelTypes_view.php:179
-msgid "Driver"
-msgstr "Motorista"
-
-#: includes/view/AngelTypes_view.php:180
-msgid "Has car"
-msgstr "Tem carro"
-
-#: includes/view/AngelTypes_view.php:181
-#: includes/view/UserDriverLicenses_view.php:27
-msgid "Car"
-msgstr "Carro"
-
-#: includes/view/AngelTypes_view.php:182
-msgid "3,5t Transporter"
-msgstr "Transporte 3,5t"
-
-#: includes/view/AngelTypes_view.php:183
-msgid "7,5t Truck"
-msgstr "CaminhΓ£o 7,5t"
-
-#: includes/view/AngelTypes_view.php:184
-msgid "12t Truck"
-msgstr "CaminhΓ£o 12t"
-
-#: includes/view/AngelTypes_view.php:185
-#: includes/view/UserDriverLicenses_view.php:31
-msgid "Forklift"
-msgstr "Empilhadeira"
-
-#: includes/view/AngelTypes_view.php:215
-msgid "Supporters"
-msgstr "Apoiadores"
-
-#: includes/view/AngelTypes_view.php:235
-msgid "Members"
-msgstr "Membros"
-
-#: includes/view/AngelTypes_view.php:238
-#: includes/view/UserAngelTypes_view.php:72
-msgid "Add"
-msgstr "Adicionar"
-
-#: includes/view/AngelTypes_view.php:246
-msgid "confirm all"
-msgstr "confirmar todos"
-
-#: includes/view/AngelTypes_view.php:247
-msgid "deny all"
-msgstr "rejeitar todos"
-
-#: includes/view/AngelTypes_view.php:264
-msgid "New angeltype"
-msgstr "Novo tipo de anjo"
-
-#: includes/view/AngelTypes_view.php:270
-msgid "Self Sign Up Allowed"
-msgstr "Auto Inscrição autorizada"
-
-#: includes/view/AngelTypes_view.php:271
-msgid "Membership"
-msgstr "Membro"
-
-#: includes/view/AngelTypes_view.php:296
-msgid ""
-"This angeltype is restricted by double-opt-in by a team supporter. Please "
-"show up at the according introduction meetings."
-msgstr ""
-"Esse tipo de anjo Γ© restrito por um opt-in duplo por um time de apoio. Por "
-"favor\n"
-"compareça de acordo com os encontros de introdução."
-
-#: includes/view/AngelTypes_view.php:317
-msgid "FAQ"
-msgstr "FAQ"
-
-#: includes/view/AngelTypes_view.php:319
-msgid ""
-"Here is the list of teams and their tasks. If you have questions, read the "
-"FAQ."
-msgstr ""
-"Aqui estΓ‘ uma lista dos times e suas tarefas. Se vocΓͺ tem dΓΊvidas, leia a\n"
-"FAQ."
-
-#: includes/view/EventConfig_view.php:10 includes/view/EventConfig_view.php:18
-#, php-format
-msgid "Welcome to the %s!"
-msgstr "Bem vindo a %s!"
-
-#: includes/view/EventConfig_view.php:24
-msgid "Buildup starts"
-msgstr "InΓcio da montagem"
-
-#: includes/view/EventConfig_view.php:26 includes/view/EventConfig_view.php:34
-#: includes/view/EventConfig_view.php:42 includes/view/EventConfig_view.php:50
-#: includes/view/EventConfig_view.php:67 includes/view/EventConfig_view.php:72
-#: includes/view/EventConfig_view.php:77 includes/view/Shifts_view.php:68
-#: includes/view/Shifts_view.php:76
-msgid "Y-m-d"
-msgstr "d/m/Y"
-
-#: includes/view/EventConfig_view.php:32
-msgid "Event starts"
-msgstr "O evento começa em"
-
-#: includes/view/EventConfig_view.php:40
-msgid "Event ends"
-msgstr "O evento termina em"
-
-#: includes/view/EventConfig_view.php:48
-msgid "Teardown ends"
-msgstr "Desmontagem termina"
-
-#: includes/view/EventConfig_view.php:67
-#, php-format
-msgid "%s, from %s to %s"
-msgstr "%s, de %s para %s"
-
-#: includes/view/EventConfig_view.php:72
-#, php-format
-msgid "%s, starting %s"
-msgstr "%s, começando %s"
-
-#: includes/view/EventConfig_view.php:77
-#, php-format
-msgid "Event from %s to %s"
-msgstr "Evento de %s para %s"
-
-#: includes/view/EventConfig_view.php:106
-msgid "Event Name"
-msgstr "Nome do evento"
-
-#: includes/view/EventConfig_view.php:107
-msgid "Event Name is shown on the start page."
-msgstr "Nome do evento Γ© mostrado na pΓ‘gina inicial."
-
-#: includes/view/EventConfig_view.php:108
-msgid "Event Welcome Message"
-msgstr "Mensagem de boas vindas do evento"
-
-#: includes/view/EventConfig_view.php:109
-msgid ""
-"Welcome message is shown after successful registration. You can use markdown."
-msgstr ""
-"A mensagem de boas vindas Γ© mostrada apΓ³s a inscrição. VocΓͺ pode usar "
-"markdown."
-
-#: includes/view/EventConfig_view.php:112
-msgid "Buildup date"
-msgstr "Data da montagem"
-
-#: includes/view/EventConfig_view.php:113
-msgid "Event start date"
-msgstr "Data de inΓcio do evento"
-
-#: includes/view/EventConfig_view.php:116
-msgid "Teardown end date"
-msgstr "Data da desmontagem"
-
-#: includes/view/EventConfig_view.php:117
-msgid "Event end date"
-msgstr "Data de tΓ©rmino do evento"
-
-#: includes/view/Questions_view.php:17
-msgid "Open questions"
-msgstr "DΓΊvidas abertas"
-
-#: includes/view/Questions_view.php:31
-msgid "Your Question:"
-msgstr "Sua dΓΊvida:"
-
-#: includes/view/ShiftCalendarRenderer.php:209 includes/view/User_view.php:367
-msgid "Time"
-msgstr "Hora"
-
-#: includes/view/ShiftCalendarRenderer.php:248
-msgid "Your shift"
-msgstr "Seu turno"
-
-#: includes/view/ShiftCalendarRenderer.php:249
-msgid "Help needed"
-msgstr "Necessita ajuda"
-
-#: includes/view/ShiftCalendarRenderer.php:250
-msgid "Other angeltype needed / collides with my shifts"
-msgstr "Outro tipo de anjo necessΓ‘rio / colide com seus turnos"
-
-#: includes/view/ShiftCalendarRenderer.php:251
-msgid "Shift is full"
-msgstr "O turno estΓ‘ lotado"
-
-#: includes/view/ShiftCalendarRenderer.php:252
-msgid "Shift running/ended"
-msgstr "Turno em andamento/finalizado"
-
-#: includes/view/ShiftCalendarShiftRenderer.php:96
-msgid "Add more angels"
-msgstr "Adicionar mais anjos"
-
-#: includes/view/ShiftCalendarShiftRenderer.php:127
-#, php-format
-msgid "%d helper needed"
-msgid_plural "%d helpers needed"
-msgstr[0] "%d necessita de ajuda"
-msgstr[1] "%d necessitam de ajuda"
-
-#: includes/view/ShiftCalendarShiftRenderer.php:132
-#: includes/view/Shifts_view.php:23
-msgid "Sign up"
-msgstr "Registrar"
-
-#: includes/view/ShiftCalendarShiftRenderer.php:137
-msgid "ended"
-msgstr "encerrado"
-
-#: includes/view/ShiftCalendarShiftRenderer.php:146
-#: includes/view/Shifts_view.php:25
-#, php-format
-msgid "Become %s"
-msgstr "Tornar-se %s"
-
-#: includes/view/ShiftEntry_view.php:18 includes/view/User_view.php:267
-#: includes/view/User_view.php:269
-msgid "Freeloaded"
-msgstr "Freeloaded"
-
-#: includes/view/ShiftEntry_view.php:19
-msgid "Freeload comment (Only for shift coordination):"
-msgstr "ComentÑrio freeload (Apenas para coordenação de turno):"
-
-#: includes/view/ShiftEntry_view.php:22
-msgid "Edit shift entry"
-msgstr "Editar entrada de turno"
-
-#: includes/view/ShiftEntry_view.php:25
-msgid "Angel:"
-msgstr "Anjo:"
-
-#: includes/view/ShiftEntry_view.php:26
-msgid "Date, Duration:"
-msgstr "Data, Duração:"
-
-#: includes/view/ShiftEntry_view.php:27
-msgid "Location:"
-msgstr "Local:"
-
-#: includes/view/ShiftEntry_view.php:28
-msgid "Title:"
-msgstr "TΓtulo:"
-
-#: includes/view/ShiftEntry_view.php:29
-msgid "Type:"
-msgstr "Tipo:"
-
-#: includes/view/ShiftEntry_view.php:30
-msgid "Comment (for your eyes only):"
-msgstr "ComentΓ‘rio (apenas para ler):"
-
-#: includes/view/ShiftTypes_view.php:13
-#, php-format
-msgid "Do you want to delete shifttype %s?"
-msgstr "VocΓͺ quer apagar o turno %s?"
-
-#: includes/view/ShiftTypes_view.php:29
-msgid "Edit shifttype"
-msgstr "Editar tipo de turno"
-
-#: includes/view/ShiftTypes_view.php:29
-msgid "Create shifttype"
-msgstr "Criar tipo de turno"
-
-#: includes/view/ShiftTypes_view.php:48
-#, php-format
-msgid "for team %s"
-msgstr "para o time %s"
-
-#: includes/view/ShiftTypes_view.php:75
-msgid "New shifttype"
-msgstr "Novo tipo de turno"
-
-#: includes/view/Shifts_view.php:7
-#, php-format
-msgid "created at %s by %s"
-msgstr "criado em %s por %s"
-
-#: includes/view/Shifts_view.php:10
-#, php-format
-msgid "edited at %s by %s"
-msgstr "editado em %s por %s"
-
-#: includes/view/Shifts_view.php:52
-msgid "This shift collides with one of your shifts."
-msgstr "Esse turno colide com um dos seus outros turnos."
-
-#: includes/view/Shifts_view.php:53
-msgid "You are signed up for this shift."
-msgstr "VocΓͺ foi designado para esse turno."
-
-#: includes/view/Shifts_view.php:82 includes/view/User_view.php:368
-msgid "Location"
-msgstr "Local"
-
-#: includes/view/UserAngelTypes_view.php:6
-#, php-format
-msgid "Do you really want to add supporter rights for %s to %s?"
-msgstr "VocΓͺ realmente quer dar permissΓ£o de apoiador de %s para %s?"
-
-#: includes/view/UserAngelTypes_view.php:6
-#, php-format
-msgid "Do you really want to remove supporter rights for %s from %s?"
-msgstr "VocΓͺ realmente quer remover a permissΓ£o de apoiador de %s para %s?"
-
-#: includes/view/UserAngelTypes_view.php:17
-#, php-format
-msgid "Do you really want to deny all users for %s?"
-msgstr "VocΓͺ realmente quer negar todos os usuΓ‘rios para %s?"
-
-#: includes/view/UserAngelTypes_view.php:28
-#, php-format
-msgid "Do you really want to confirm all users for %s?"
-msgstr "VocΓͺ realmente quer confirmar todos os usuΓ‘rios para %s?"
-
-#: includes/view/UserAngelTypes_view.php:39
-#, php-format
-msgid "Do you really want to confirm %s for %s?"
-msgstr "VocΓͺ realmente quer confirmar %s para %s?"
-
-#: includes/view/UserAngelTypes_view.php:50
-#, php-format
-msgid "Do you really want to delete %s from %s?"
-msgstr "VocΓͺ realmente quer apagar %s de %s?"
-
-#: includes/view/UserAngelTypes_view.php:71
-msgid "User"
-msgstr "UsuΓ‘rio"
-
-#: includes/view/UserAngelTypes_view.php:80
-#, php-format
-msgid "Do you really want to add %s to %s?"
-msgstr "VocΓͺ realmente quer adicionar %s em %s?"
-
-#: includes/view/UserAngelTypes_view.php:83
-msgid "save"
-msgstr "salvar"
-
-#: includes/view/UserDriverLicenses_view.php:17
-msgid "Back to profile"
-msgstr "Voltar para o perfil"
-
-#: includes/view/UserDriverLicenses_view.php:21
-msgid "Privacy"
-msgstr "Privacidade"
-
-#: includes/view/UserDriverLicenses_view.php:21
-msgid ""
-"Your driving license information is only visible for supporters and admins."
-msgstr ""
-"Os dados da sua carteira de motorista sΓ£o apenas visΓveis para os apoiadores "
-"e os admins."
-
-#: includes/view/UserDriverLicenses_view.php:22
-msgid "I am willing to drive a car for the event"
-msgstr "Eu desejo dirigir carros para o evento"
-
-#: includes/view/UserDriverLicenses_view.php:25
-msgid ""
-"I have my own car with me and am willing to use it for the event (You'll get "
-"reimbursed for fuel)"
-msgstr ""
-"Eu tenho meu prΓ³prio carro e estou disposto a usΓ‘-lo no evento\n"
-"(VocΓͺ terΓ‘ o combustΓvel reembolsado)"
-
-#: includes/view/UserDriverLicenses_view.php:26
-msgid "Driver license"
-msgstr "Carteira de motorista"
-
-#: includes/view/UserDriverLicenses_view.php:28
-msgid "Transporter 3,5t"
-msgstr "Transportador 3,5t"
-
-#: includes/view/UserDriverLicenses_view.php:29
-msgid "Truck 7,5t"
-msgstr "CaminhΓ£o 7,5t"
-
-#: includes/view/UserDriverLicenses_view.php:30
-msgid "Truck 12t"
-msgstr "CaminhΓ£o 12t"
-
-#: includes/view/User_view.php:7
-msgid "Please select..."
-msgstr "Por favor selecione..."
-
-#: includes/view/User_view.php:38
-msgid "Here you can change your user details."
-msgstr "Aqui vocΓͺ pode mudar os seus detalhes de usuΓ‘rio."
-
-#: includes/view/User_view.php:44
-msgid "Planned date of departure"
-msgstr "Data planejada para saΓda"
-
-#: includes/view/User_view.php:55
-msgid "Please visit the angeltypes page to manage your angeltypes."
-msgstr ""
-"Por favor visite a pΓ‘gina de tipos de anjo para gerenciar os tipos de anjo"
-
-#: includes/view/User_view.php:61
-msgid "Here you can change your password."
-msgstr "Aqui vocΓͺ pode mudar sua senha."
-
-#: includes/view/User_view.php:62
-msgid "Old password:"
-msgstr "Senha antiga:"
-
-#: includes/view/User_view.php:63
-msgid "New password:"
-msgstr "Nova senha:"
-
-#: includes/view/User_view.php:64
-msgid "Password confirmation:"
-msgstr "Confirmação de senha:"
-
-#: includes/view/User_view.php:88
-msgid "Registration successful"
-msgstr "Registrado com sucesso"
-
-#: includes/view/User_view.php:126
-msgid ""
-"Do you really want to delete the user including all his shifts and every "
-"other piece of his data?"
-msgstr ""
-"VocΓͺ realmente quer apagar o usuΓ‘rio, incluindo todos seus turnos e todos\n"
-"os seus dados?"
-
-#: includes/view/User_view.php:128
-msgid "Your password"
-msgstr "Sua senha"
-
-#: includes/view/User_view.php:143
-#, php-format
-msgid "Angel should receive at least %d vouchers."
-msgstr "Um anjo deve receber no mΓnimo %d vouchers."
-
-#: includes/view/User_view.php:145
-msgid "Number of vouchers given out"
-msgstr "NΓΊmero de vouchers dados"
-
-#: includes/view/User_view.php:159
-msgid "m/d/Y h:i a"
-msgstr "d/m/Y H:i"
-
-#: includes/view/User_view.php:178
-msgid "New user"
-msgstr "Novo usuΓ‘rio"
-
-#: includes/view/User_view.php:182
-msgid "Prename"
-msgstr "Nome"
-
-#: includes/view/User_view.php:185 includes/view/User_view.php:350
-msgid "Arrived"
-msgstr "Chegou"
-
-#: includes/view/User_view.php:186
-msgid "Voucher"
-msgstr "Voucher"
-
-#: includes/view/User_view.php:187
-msgid "Freeloads"
-msgstr "Freeloads"
-
-#: includes/view/User_view.php:188 includes/view/User_view.php:352
-msgid "Active"
-msgstr "Ativo"
-
-#: includes/view/User_view.php:190 includes/view/User_view.php:353
-msgid "T-Shirt"
-msgstr "Camiseta"
-
-#: includes/view/User_view.php:192
-msgid "Last login"
-msgstr "Γltimo login"
-
-#: includes/view/User_view.php:209
-msgid "Free"
-msgstr "Livre"
-
-#: includes/view/User_view.php:214 includes/view/User_view.php:216
-#, php-format
-msgid "Next shift %c"
-msgstr "PrΓ³ximo turno %c"
-
-#: includes/view/User_view.php:221
-#, php-format
-msgid "Shift starts %c"
-msgstr "Turno inicia em %c"
-
-#: includes/view/User_view.php:223
-#, php-format
-msgid "Shift ends %c"
-msgstr "Turno termina em %c"
-
-#: includes/view/User_view.php:280
-msgid "sign off"
-msgstr "sair"
-
-#: includes/view/User_view.php:305
-msgid "Sum:"
-msgstr "Soma:"
-
-#: includes/view/User_view.php:329
-msgid "driving license"
-msgstr "carteira de motorista"
-
-#: includes/view/User_view.php:331
-msgid "Edit vouchers"
-msgstr "Editar vouchers"
-
-#: includes/view/User_view.php:333
-msgid "iCal Export"
-msgstr "Exportar iCal"
-
-#: includes/view/User_view.php:334
-msgid "JSON Export"
-msgstr "Exportar em formato JSON"
-
-#: includes/view/User_view.php:347
-msgid "User state"
-msgstr "Status"
-
-#: includes/view/User_view.php:350
-#, php-format
-msgid "Arrived at %s"
-msgstr "Chegous Γ s %s"
-
-#: includes/view/User_view.php:350
-#, php-format
-msgid "Not arrived (Planned: %s)"
-msgstr "NΓ£o chegou (Planejado: %s)"
-
-#: includes/view/User_view.php:350
-msgid "Not arrived"
-msgstr "NΓ£o chegou"
-
-#: includes/view/User_view.php:351
-#, php-format
-msgid "Got %s voucher"
-msgid_plural "Got %s vouchers"
-msgstr[0] "Einen Voucher bekommen"
-msgstr[1] "%s Voucher bekommen"
-
-#: includes/view/User_view.php:351
-msgid "Got no vouchers"
-msgstr "Pegou voucher %s"
-
-#: includes/view/User_view.php:360
-msgid "Rights"
-msgstr "PermissΓ΅es"
-
-#: includes/view/User_view.php:369
-msgid "Name & workmates"
-msgstr "Nome & colegas"
-
-#: includes/view/User_view.php:370
-msgid "Comment"
-msgstr "Comentar"
-
-#: includes/view/User_view.php:371
-msgid "Action"
-msgstr "Ação"
-
-#: includes/view/User_view.php:373
-#, php-format
-msgid "Your night shifts between %d and %d am count twice."
-msgstr "Os seus turnos noturnos entre %dh e %dh contam como dois."
-
-#: includes/view/User_view.php:374
-#, php-format
-msgid ""
-"Go to the shifts table to sign yourself up for some "
-"shifts."
-msgstr ""
-"VΓ‘ para a tabela de turnos para se inscrever em alguns\n"
-"turnos."
-
-#: includes/view/User_view.php:384
-msgid ""
-"We will send you an e-mail with a password recovery link. Please use the "
-"email address you used for registration."
-msgstr ""
-"Nós enviaremos um email com um link para recuperação de senha. Por favor use "
-"o \n"
-"endereço de email informado no seu registro."
-
-#: includes/view/User_view.php:387
-msgid "Recover"
-msgstr "Recuperar"
-
-#: includes/view/User_view.php:398
-msgid "Please enter a new password."
-msgstr "Por favor digite uma nova senha."
-
-#: includes/view/User_view.php:447
-msgid ""
-"Please enter your planned date of departure on your settings page to give us "
-"a feeling for teardown capacities."
-msgstr ""
-"Por favor digite sua data planejada de saΓda na sua pΓ‘gina de configuraçáes "
-"para\n"
-"termos uma noção da nossa capacidade de desmontagem."
-
-#: includes/view/User_view.php:457
-#, php-format
-msgid ""
-"You freeloaded at least %s shifts. Shift signup is locked. Please go to "
-"heavens desk to be unlocked again."
-msgstr ""
-"VocΓͺ deixou de participar de pelo menos %s dos turnos. O registro em turnos "
-"estΓ‘ suspenso.\n"
-"Por favor vΓ‘ atΓ© a mesa do paraΓso para ser desbloqueado novamente."
-
-#: includes/view/User_view.php:468
-msgid ""
-"You are not marked as arrived. Please go to heaven's desk, get your angel "
-"badge and/or tell them that you arrived already."
-msgstr ""
-"Sua chegada nΓ£o foi marcada. Por favor vΓ‘ atΓ© a mesa do paraΓso, pegue sua "
-"credencial\n"
-"de anjo e/ou informe que vocΓͺ jΓ‘ chegou."
-
-#: includes/view/User_view.php:478
-msgid "You need to specify a tshirt size in your settings!"
-msgstr "VocΓͺ precisa especificar o tamanho de camiseta nas suas configuraçáes!"
-
-#: includes/view/User_view.php:488
-msgid ""
-"You need to specify a DECT phone number in your settings! If you don't have "
-"a DECT phone, just enter \"-\"."
-msgstr ""
-"VocΓͺ precisa especificar um nΓΊmero DECT de telefone nas suas configuracΓ΅es!\n"
-"Se vocΓͺ nΓ£o tem um telefone DECT, apenas digite \\-\\."
-
-#: public/index.php:155
-msgid "No Access"
-msgstr "Sem acesso"
-
-#: public/index.php:156
-msgid ""
-"You don't have permission to view this page. You probably have to sign in or "
-"register in order to gain access!"
-msgstr ""
-"VocΓͺ nΓ£o tem permissΓ£o para ver essa pΓ‘gina. VocΓͺ provavelmente terΓ‘ que "
-"fazer login ou se registrar para ganhar acesso!"
-
-#~ msgid "Registration is disabled."
-#~ msgstr "Registros estΓ£o desabilitados."
-
-#~ msgid "Please enter your planned date of arrival."
-#~ msgstr "Por favor digite seu horario planificado de chagada "
-
-#~ msgid "Password could not be updated."
-#~ msgstr "Nao foi possivel atualizar a senha"
-
-#~ msgid "We got no information about the event right now."
-#~ msgstr "Nao tem info sobre o evento agora"
-
-#~ msgid "from %s to %s"
-#~ msgstr "desde %s ate %s"
-
-#~ msgid "Please enter your planned date of departure."
-#~ msgstr "Por favor pone seu horario planificado de ida"
-
-#~ msgid "Please select a user."
-#~ msgstr "Seleciona um usuario"
-
-#~ msgid "Unable to load user."
-#~ msgstr "Nao foi possivel carregar o usuario"
-
-#~ msgid "Entries"
-#~ msgstr "Entradas"
-
-#~ msgid "Use new style if possible"
-#~ msgstr "Usa umo estilo novo se possivel"
-
-#~ msgid "Coordinator"
-#~ msgstr "Coordinador"
-
-#~ msgid "Coordinators"
-#~ msgstr "Coordinadores"
-
-#~ msgid " vouchers."
-#~ msgstr " vouchers."
-
-#~ msgid ""
-#~ "This is a automatically calculated MINIMUM value, you can of course give "
-#~ "out more if appropriate!"
-#~ msgstr ""
-#~ "Esso e' calucula automaticamente o valor MINIMO, voce pode claramente "
-#~ "mudar isso com umo mais appropriado! "
-
-#~ msgid "You have been signed off from the shift."
-#~ msgstr "Voce se desconnecto do seu turno"
-
-#~ msgid "planned departure"
-#~ msgstr "saida planejada"
-
-#~ msgid "Tasks"
-#~ msgstr "tarefas"
-
-#~ msgid "User didnt got vouchers."
-#~ msgstr "O usuario nao tem vouchers."
-
-#~ msgid "Remove vouchers"
-#~ msgstr "Apaga voucher"
-
-#~ msgid ""
-#~ "This shift is running now or ended already. Please contact a dispatcher "
-#~ "to join the shift."
-#~ msgstr ""
-#~ "Esse turno esta ativo agora o ja acabou. Por favor contata o coordinador "
-#~ "para partecipar nesse turno"
-
-#~ msgid ""
-#~ "You already subscribed to shift in the same timeslot. Please contact a "
-#~ "dispatcher to join the shift."
-#~ msgstr ""
-#~ "Voce ja se registrou al turno no mesmo timeslot. Por favor contata o "
-#~ "coordinador para partecipar a esse turno."
-
-#~ msgid ""
-#~ "Hello %s, here you can change your personal settings i.e. password, color "
-#~ "settings etc."
-#~ msgstr ""
-#~ "Oi %s, aqui pode mudar as tuas configuraçeos pessoal (i.e. senha, "
-#~ "cor, ...)"
-
-#~ msgid "Name/Description:"
-#~ msgstr "Nome/Descriçao:"
-
-#~ msgid "Timeslot"
-#~ msgstr "Timeslot"
-
-#~ msgid "The first wants to join %s."
-#~ msgstr "O primeiro que quer partecipar %s"
-
-#~ msgid "Groups"
-#~ msgstr "Grupos"
-
-#~ msgid "ICQ"
-#~ msgstr "ICQ"
-
-#~ msgid "You are not confirmed for this angel type."
-#~ msgstr "Voce nao ta confirmado por esse tipo de anjo."
-
-#~ msgid "Exports"
-#~ msgstr "Esporta"
-
-#~ msgid "Add new angeltype"
-#~ msgstr "Adicione um novo tipo de anjo"
-
-#~ msgid "Language"
-#~ msgstr "Idioma"
-
-#~ msgid "You have %s new message."
-#~ msgid_plural "You have %s new messages."
-#~ msgstr[0] "Voce tem %s novo message"
-#~ msgstr[1] ""
-
-#~ msgid ""
-#~ "These are your shifts.
Please try to appear 15 minutes before "
-#~ "your shift begins!
You can remove yourself from a shift up to %d "
-#~ "hours before it starts."
-#~ msgstr ""
-#~ "Esses som teu turnos.
Por favor tenta chegar 15 minudos antes "
-#~ "que seu turno comença!
Voce pode se tirar desse turno ate %d horas "
-#~ "antes dele començar."
-
-#~ msgid "Page:"
-#~ msgstr "Pagina"
-
-#~ msgid "Message:"
-#~ msgstr "Messagem:"
-
-#~ msgid "Wakeup"
-#~ msgstr "Wakeup"
-
-#~ msgid "Incomplete call, missing wake-up ID."
-#~ msgstr "chamada incompleta, falta o wake-up ID"
-
-#~ msgid "Wake-up call deleted."
-#~ msgstr "wake-up chamada apagada"
-
-#~ msgid "No wake-up found."
-#~ msgstr "Nao encontrei nenhum wake-up"
-
-#~ msgid ""
-#~ "Hello %s, here you can register for a wake-up call. Simply say when and "
-#~ "where the angel should come to wake you."
-#~ msgstr ""
-#~ "Oi %s, aqui voce pode se registrar para a chamada wake-up. So tem que "
-#~ "dizer quando e onde os anjos tem que chegar para te acordar (wake up)"
-
-#~ msgid "All ordered wake-up calls, next first."
-#~ msgstr "Todos os ordem wake-up, o proximo primeiro"
-
-#~ msgid "Place"
-#~ msgstr "Lugar"
-
-#~ msgid "Notes"
-#~ msgstr "Notas"
-
-#~ msgid "Schedule a new wake-up here:"
-#~ msgstr "Planifica um novo wake-up aqui:"
-
-#~ msgid "User %s confirmed as %s."
-#~ msgstr "Usuario %s confirmado como %s"
-
-#~ msgid ""
-#~ "Resistance is futile! Your biological and physical parameters will be "
-#~ "added to our collectiv! Assimilating angel:"
-#~ msgstr ""
-#~ "Resistir e' inΓΊtil! Seus parΓ’metros biolΓ³gico e fΓsico serΓ£o adicionados "
-#~ "dentro do nosso coletivo! Anjo assimilado: "
-
-#~ msgid "Confirmed all."
-#~ msgstr "Tudo confirmado."
-
-#~ msgid "asdf"
-#~ msgstr "asdf"
diff --git a/resources/views/admin/locations/edit.twig b/resources/views/admin/locations/edit.twig
new file mode 100644
index 000000000..f30fb4377
--- /dev/null
+++ b/resources/views/admin/locations/edit.twig
@@ -0,0 +1,66 @@
+{% extends 'admin/locations/index.twig' %}
+{% import 'macros/base.twig' as m %}
+{% import 'macros/form.twig' as f %}
+
+{% block title %}{{ location ? __('location.edit.title') : __('location.create.title') }}{% endblock %}
+
+{% block row_content %}
+
+{% endblock %}
diff --git a/resources/views/admin/locations/index.twig b/resources/views/admin/locations/index.twig
new file mode 100644
index 000000000..b32dc4a30
--- /dev/null
+++ b/resources/views/admin/locations/index.twig
@@ -0,0 +1,81 @@
+{% extends 'layouts/app.twig' %}
+{% import 'macros/base.twig' as m %}
+{% import 'macros/form.twig' as f %}
+
+{% block title %}{{ __('location.locations') }}{% endblock %}
+
+{% block content %}
+
+
+ {% if not is_index|default(false) %}
+ {{ m.button(m.icon('chevron-left'), location
+ ? url('/locations', {'action': 'view', 'location_id': location.id})
+ : url('/admin/locations'), 'secondary', 'sm', __('general.back')) }}
+ {% endif %}
+
+ {{ block('title') }}
+
+ {% if is_index|default(false) %}
+ {{ m.button(m.icon('plus-lg'), url('/admin/locations/edit'), 'secondary') }}
+ {% endif %}
+
+
+ {% include 'layouts/parts/messages.twig' %}
+
+
+
+ {% block row_content %}
+
+
+
+
+
+ {{ __('general.name') }} |
+ {{ __('general.dect') }} |
+ {{ __('location.map_url') }} |
+ |
+
+
+
+
+ {% for location in locations %}
+
+
+ {{ m.icon('pin-map-fill') }}
+
+ {{ location.name }}
+
+ |
+
+ {{ m.iconBool(location.dect) }} |
+
+ {{ m.iconBool(location.map_url) }} |
+
+
+
+
+ {{ m.button(m.icon('pencil'), url('/admin/locations/edit/' ~ location.id), null, 'sm', __('form.edit')) }}
+
+
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endblock %}
+
+
+
+{% endblock %}
diff --git a/resources/views/admin/log.twig b/resources/views/admin/log.twig
index e7bc240c2..87ea55cbd 100644
--- a/resources/views/admin/log.twig
+++ b/resources/views/admin/log.twig
@@ -2,11 +2,11 @@
{% import 'macros/base.twig' as m %}
{% import 'macros/form.twig' as f %}
-{% set title %}{% block title %}{{ __('log.log') }}{% endblock %}{% endset %}
+{% block title %}{{ __('log.log') }}{% endblock %}
{% block content %}
-
{{ block('title') }}
+
{{ block('title') }} ({{ entries|length }})
@@ -14,16 +14,39 @@
+ {% if not has_permission_to('logs.all') %}
+
+ {{ m.alert(__('log.only_own')) }}
+
+ {% endif %}
+
{{ __('log.time') }} |
{{ __('log.level') }} |
+ {{ __('general.user') }} |
{{ __('log.message') }} |
{% for entry in entries %}
@@ -44,10 +67,11 @@
{%- endif %}
- {{ entry.created_at.format(__('Y-m-d H:i')) }} |
-
+ | {{ entry.created_at.format(__('general.datetime')) }} |
+
{{ entry.level|capitalize }}
|
+ {% if entry.user %}{{ m.user(entry.user) }}{% endif %} |
{{ entry.message|nl2br }} |
{% endfor %}
diff --git a/resources/views/admin/rooms/edit.twig b/resources/views/admin/rooms/edit.twig
deleted file mode 100644
index 43df6d23e..000000000
--- a/resources/views/admin/rooms/edit.twig
+++ /dev/null
@@ -1,66 +0,0 @@
-{% extends 'admin/rooms/index.twig' %}
-{% import 'macros/base.twig' as m %}
-{% import 'macros/form.twig' as f %}
-
-{% block title %}{{ room ? __('room.edit.title') : __('room.create.title') }}{% endblock %}
-
-{% block row_content %}
-
-{% endblock %}
diff --git a/resources/views/admin/schedule/edit.twig b/resources/views/admin/schedule/edit.twig
index 335b34e98..f30f9a4fe 100644
--- a/resources/views/admin/schedule/edit.twig
+++ b/resources/views/admin/schedule/edit.twig
@@ -4,26 +4,75 @@
{% block title %}{{ schedule ? __('schedule.edit.title') : __('schedule.import.title') }}{% endblock %}
+{% block content_title %}
+ {{ m.button(m.icon('chevron-left'), url('/admin/schedule'), 'secondary', 'sm', __('general.back')) }}
+ {{ block('title') }}
+{% endblock %}
+
{% block row_content %}
{% if schedule and schedule.updated_at %}
-
{{ __('schedule.last_update', [schedule.updated_at.format(__('Y-m-d H:i'))]) }}
+
{{ __('schedule.last_update', [schedule.updated_at.format(__('general.datetime'))]) }}
{% endif %}