Release 2.56 (#5909)

This commit is contained in:
Kevin Papst
2026-04-25 09:58:43 +02:00
committed by GitHub
parent 01cb14a3da
commit 087350ab72
14 changed files with 477 additions and 162 deletions

View File

@@ -55,8 +55,8 @@ body:
options: options:
- "8.5" - "8.5"
- "8.4" - "8.4"
- "8.2"
- "8.3" - "8.3"
- "8.2"
- "8.1" - "8.1"
- Unknown - Unknown
- Other (please mention below) - Other (please mention below)

View File

@@ -22,7 +22,7 @@ version-resolver:
- 'translation' - 'translation'
default: patch default: patch
template: | template: |
**Compatible with PHP 8.1 to 8.5** **Compatible with PHP 8.2 to 8.5**
$CHANGES $CHANGES

View File

@@ -19,7 +19,7 @@ jobs:
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy: strategy:
matrix: matrix:
php: ['8.1', '8.2', '8.3', '8.4', '8.5'] php: ['8.2', '8.3', '8.4', '8.5']
name: Integration (${{ matrix.php }}) name: Integration (${{ matrix.php }})
steps: steps:

View File

@@ -29,7 +29,7 @@ and so much more.
### Requirements ### Requirements
- PHP 8.1.3 minimum with support for 8.2, 8.3, 8.4, 8.5 - PHP 8.2 minimum with support for 8.3, 8.4, 8.5
- MariaDB / MySQL: oldest maintained LTS release (MariaDB >= [10.6](https://endoflife.date/mariadb) or MySQL >= [8.4](https://endoflife.date/mysql)) or newer - MariaDB / MySQL: oldest maintained LTS release (MariaDB >= [10.6](https://endoflife.date/mariadb) or MySQL >= [8.4](https://endoflife.date/mysql)) or newer
- A webserver and subdomain (subdirectory is not supported) - A webserver and subdomain (subdirectory is not supported)
- PHP extensions: `gd`, `intl`, `json`, `mbstring`, `pdo`, `tokenizer`, `xml`, `xsl`, `zip` - PHP extensions: `gd`, `intl`, `json`, `mbstring`, `pdo`, `tokenizer`, `xml`, `xsl`, `zip`

View File

@@ -8,6 +8,15 @@ you can upgrade your Kimai installation to the latest stable release.
Check below if there are more version specific steps required, which need to be executed after the normal update process. Check below if there are more version specific steps required, which need to be executed after the normal update process.
Perform EACH version specific task between your version and the new one, otherwise you risk data inconsistency or a broken installation. Perform EACH version specific task between your version and the new one, otherwise you risk data inconsistency or a broken installation.
## [2.56.0](https://github.com/kimai/kimai/releases/tag/2.56.0)
The required minimum PHP version is now 8.2, read https://www.php.net/supported-versions.php
If you are still using PHP 8.1, please be aware it is EOL and does not receive any security updates.
If you have to upgrade to a newer version, do yourself the favor and upgrade directly to PHP 8.5.
The requirement for 8.2 is an intermediate solution for the near future, and the requirement will be raised to 8.5 rather sooner than later.
## [2.0.30](https://github.com/kimai/kimai/releases/tag/2.0.30) ## [2.0.30](https://github.com/kimai/kimai/releases/tag/2.0.30)
The `DATABASE_URL` in your environment settings (e.g. [.env](https://github.com/kimai/kimai/issues/4246), [docker-compose.yaml](https://github.com/tobybatch/kimai2/issues/531) or webserver config) The `DATABASE_URL` in your environment settings (e.g. [.env](https://github.com/kimai/kimai/issues/4246), [docker-compose.yaml](https://github.com/tobybatch/kimai2/issues/531) or webserver config)

View File

@@ -14,7 +14,7 @@
} }
], ],
"require": { "require": {
"php": "8.1.*||8.2.*||8.3.*||8.4.*||8.5.*", "php": "8.2.*||8.3.*||8.4.*||8.5.*",
"ext-gd": "*", "ext-gd": "*",
"ext-intl": "*", "ext-intl": "*",
"ext-json": "*", "ext-json": "*",
@@ -117,7 +117,7 @@
}, },
"optimize-autoloader": true, "optimize-autoloader": true,
"platform": { "platform": {
"php": "8.1.3" "php": "8.2"
}, },
"preferred-install": { "preferred-install": {
"*": "dist" "*": "dist"

396
composer.lock generated
View File

@@ -4,25 +4,25 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "81e3162783fcc7f01c10601aeb09b48f", "content-hash": "9408273b8cfa9c509c6e483245818e8e",
"packages": [ "packages": [
{ {
"name": "azuyalabs/yasumi", "name": "azuyalabs/yasumi",
"version": "2.9.0", "version": "2.11.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/azuyalabs/yasumi.git", "url": "https://github.com/azuyalabs/yasumi.git",
"reference": "36005a0796b64bc07257f39c11c42f147fe5320f" "reference": "e24bc345d2dd0b9425ff19abf7f11574bbb1d7be"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/azuyalabs/yasumi/zipball/36005a0796b64bc07257f39c11c42f147fe5320f", "url": "https://api.github.com/repos/azuyalabs/yasumi/zipball/e24bc345d2dd0b9425ff19abf7f11574bbb1d7be",
"reference": "36005a0796b64bc07257f39c11c42f147fe5320f", "reference": "e24bc345d2dd0b9425ff19abf7f11574bbb1d7be",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"php": ">=8.1" "php": ">=8.2"
}, },
"require-dev": { "require-dev": {
"azuyalabs/php-cs-fixer-config": "^0.3", "azuyalabs/php-cs-fixer-config": "^0.3",
@@ -30,7 +30,7 @@
"mikey179/vfsstream": "^1.6", "mikey179/vfsstream": "^1.6",
"phpstan/phpstan": "^2.1", "phpstan/phpstan": "^2.1",
"phpstan/phpstan-deprecation-rules": "^2.0", "phpstan/phpstan-deprecation-rules": "^2.0",
"phpunit/phpunit": "^8.5 || ^9.6" "phpunit/phpunit": "^11.5"
}, },
"suggest": { "suggest": {
"ext-calendar": "For calculating the date of Easter" "ext-calendar": "For calculating the date of Easter"
@@ -77,7 +77,7 @@
"type": "other" "type": "other"
} }
], ],
"time": "2025-12-29T16:13:54+00:00" "time": "2026-03-30T13:35:38+00:00"
}, },
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@@ -1663,22 +1663,22 @@
}, },
{ {
"name": "easybill/zugferd-php", "name": "easybill/zugferd-php",
"version": "v2.1.1", "version": "v2.3.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/easybill/zugferd-php.git", "url": "https://github.com/easybill/zugferd-php.git",
"reference": "376749138f5ecd216b73b5cdd5d4473f2a2d3252" "reference": "fba2a504feb58ae2b3a19da5a0c051ce8fe13895"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/easybill/zugferd-php/zipball/376749138f5ecd216b73b5cdd5d4473f2a2d3252", "url": "https://api.github.com/repos/easybill/zugferd-php/zipball/fba2a504feb58ae2b3a19da5a0c051ce8fe13895",
"reference": "376749138f5ecd216b73b5cdd5d4473f2a2d3252", "reference": "fba2a504feb58ae2b3a19da5a0c051ce8fe13895",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-dom": "*", "ext-dom": "*",
"jms/serializer": "^3.16", "jms/serializer": "^3.16",
"php": "^8.1" "php": "^8.2"
}, },
"require-dev": { "require-dev": {
"ext-libxml": "*", "ext-libxml": "*",
@@ -1721,9 +1721,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/easybill/zugferd-php/issues", "issues": "https://github.com/easybill/zugferd-php/issues",
"source": "https://github.com/easybill/zugferd-php/tree/v2.1.1" "source": "https://github.com/easybill/zugferd-php/tree/v2.3.1"
}, },
"time": "2024-11-07T08:28:44+00:00" "time": "2025-09-13T13:57:46+00:00"
}, },
{ {
"name": "egulias/email-validator", "name": "egulias/email-validator",
@@ -2947,31 +2947,32 @@
}, },
{ {
"name": "maennchen/zipstream-php", "name": "maennchen/zipstream-php",
"version": "3.1.1", "version": "3.1.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git", "url": "https://github.com/maennchen/ZipStream-PHP.git",
"reference": "6187e9cc4493da94b9b63eb2315821552015fca9" "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/6187e9cc4493da94b9b63eb2315821552015fca9", "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"reference": "6187e9cc4493da94b9b63eb2315821552015fca9", "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-zlib": "*", "ext-zlib": "*",
"php-64bit": "^8.1" "php-64bit": "^8.2"
}, },
"require-dev": { "require-dev": {
"brianium/paratest": "^7.7",
"ext-zip": "*", "ext-zip": "*",
"friendsofphp/php-cs-fixer": "^3.16", "friendsofphp/php-cs-fixer": "^3.16",
"guzzlehttp/guzzle": "^7.5", "guzzlehttp/guzzle": "^7.5",
"mikey179/vfsstream": "^1.6", "mikey179/vfsstream": "^1.6",
"php-coveralls/php-coveralls": "^2.5", "php-coveralls/php-coveralls": "^2.5",
"phpunit/phpunit": "^10.0", "phpunit/phpunit": "^11.0",
"vimeo/psalm": "^5.0" "vimeo/psalm": "^6.0"
}, },
"suggest": { "suggest": {
"guzzlehttp/psr7": "^2.4", "guzzlehttp/psr7": "^2.4",
@@ -3012,7 +3013,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/maennchen/ZipStream-PHP/issues", "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.1" "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
}, },
"funding": [ "funding": [
{ {
@@ -3020,7 +3021,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-10-10T12:33:01+00:00" "time": "2025-01-27T12:07:53+00:00"
}, },
{ {
"name": "markbaker/complex", "name": "markbaker/complex",
@@ -3468,42 +3469,45 @@
}, },
{ {
"name": "nelmio/api-doc-bundle", "name": "nelmio/api-doc-bundle",
"version": "v5.7.1", "version": "v5.10.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nelmio/NelmioApiDocBundle.git", "url": "https://github.com/nelmio/NelmioApiDocBundle.git",
"reference": "772d26a9d940c9a8d173f75f0fdbaab47c1c87f2" "reference": "212d490a85589ddce0f2dc683bef89bc62485340"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/772d26a9d940c9a8d173f75f0fdbaab47c1c87f2", "url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/212d490a85589ddce0f2dc683bef89bc62485340",
"reference": "772d26a9d940c9a8d173f75f0fdbaab47c1c87f2", "reference": "212d490a85589ddce0f2dc683bef89bc62485340",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"phpdocumentor/reflection-docblock": "^5.0", "phpdocumentor/reflection-docblock": "^5.0 || ^6.0",
"phpdocumentor/type-resolver": "^1.8.2", "phpdocumentor/type-resolver": "^1.8.2 || ^2.0",
"psr/cache": "^1.0 || ^2.0 || ^3.0", "psr/cache": "^1.0 || ^2.0 || ^3.0",
"psr/container": "^1.0 || ^2.0", "psr/container": "^1.0 || ^2.0",
"psr/log": "^1.0 || ^2.0 || ^3.0", "psr/log": "^1.0 || ^2.0 || ^3.0",
"symfony/config": "^6.4 || ^7.1", "symfony/config": "^6.4 || ^7.2 || ^8.0",
"symfony/console": "^6.4 || ^7.1", "symfony/console": "^6.4 || ^7.2 || ^8.0",
"symfony/dependency-injection": "^6.4 || ^7.1", "symfony/dependency-injection": "^6.4 || ^7.2 || ^8.0",
"symfony/deprecation-contracts": "^2.1 || ^3", "symfony/deprecation-contracts": "^2.1 || ^3",
"symfony/framework-bundle": "^6.4 || ^7.1", "symfony/framework-bundle": "^6.4 || ^7.2 || ^8.0",
"symfony/http-foundation": "^6.4 || ^7.1", "symfony/http-foundation": "^6.4 || ^7.2 || ^8.0",
"symfony/http-kernel": "^6.4 || ^7.1", "symfony/http-kernel": "^6.4 || ^7.2 || ^8.0",
"symfony/options-resolver": "^6.4 || ^7.1", "symfony/options-resolver": "^6.4 || ^7.2 || ^8.0",
"symfony/property-info": "^6.4 || ^7.1", "symfony/property-info": "^6.4 || ^7.2 || ^8.0",
"symfony/routing": "^6.4 || ^7.1", "symfony/routing": "^6.4 || ^7.2 || ^8.0",
"zircote/swagger-php": "^4.11.1 || ^5.0" "symfony/type-info": "^7.2 || ^8.0",
"zircote/swagger-php": "^4.11.1 || ^5.0 || ^6.0"
}, },
"conflict": { "conflict": {
"symfony/property-info": "6.4.32 || 7.3.10 || 7.4.4 || 8.0.4",
"zircote/swagger-php": "4.8.7 || 5.5.0" "zircote/swagger-php": "4.8.7 || 5.5.0"
}, },
"require-dev": { "require-dev": {
"api-platform/core": "^3.2", "api-platform/core": "^3.2 || ^4.0",
"doctrine/inflector": "^2.0",
"friendsofphp/php-cs-fixer": "^3.52", "friendsofphp/php-cs-fixer": "^3.52",
"friendsofsymfony/rest-bundle": "^3.2.0", "friendsofsymfony/rest-bundle": "^3.2.0",
"jms/serializer": "^3.32", "jms/serializer": "^3.32",
@@ -3513,25 +3517,22 @@
"phpstan/phpstan-strict-rules": "^2.0", "phpstan/phpstan-strict-rules": "^2.0",
"phpstan/phpstan-symfony": "^2.0", "phpstan/phpstan-symfony": "^2.0",
"phpunit/phpunit": "^10.5", "phpunit/phpunit": "^10.5",
"symfony/asset": "^6.4 || ^7.1", "symfony/asset": "^6.4 || ^7.2 || ^8.0",
"symfony/browser-kit": "^6.4 || ^7.1", "symfony/browser-kit": "^6.4 || ^7.2 || ^8.0",
"symfony/cache": "^6.4 || ^7.1", "symfony/cache": "^6.4 || ^7.2 || ^8.0",
"symfony/dom-crawler": "^6.4 || ^7.1", "symfony/dom-crawler": "^6.4 || ^7.2 || ^8.0",
"symfony/expression-language": "^6.4 || ^7.1", "symfony/expression-language": "^6.4 || ^7.2 || ^8.0",
"symfony/finder": "^6.4 || ^7.1", "symfony/finder": "^6.4 || ^7.2 || ^8.0",
"symfony/form": "^6.4 || ^7.1", "symfony/form": "^6.4 || ^7.2 || ^8.0",
"symfony/phpunit-bridge": "^6.4 || ^7.1", "symfony/phpunit-bridge": "^6.4 || ^7.2 || ^8.0",
"symfony/property-access": "^6.4 || ^7.1", "symfony/security-csrf": "^6.4 || ^7.2 || ^8.0",
"symfony/security-csrf": "^6.4 || ^7.1", "symfony/security-http": "^6.4 || ^7.2 || ^8.0",
"symfony/security-http": "^6.4 || ^7.1", "symfony/serializer": "^6.4 || ^7.2 || ^8.0",
"symfony/serializer": "^6.4 || ^7.1", "symfony/translation": "^6.4 || ^7.2 || ^8.0",
"symfony/stopwatch": "^6.4 || ^7.1", "symfony/twig-bundle": "^6.4 || ^7.2 || ^8.0",
"symfony/templating": "^6.4 || ^7.1", "symfony/uid": "^6.4 || ^7.2 || ^8.0",
"symfony/translation": "^6.4 || ^7.1", "symfony/validator": "^6.4 || ^7.2 || ^8.0",
"symfony/twig-bundle": "^6.4 || ^7.1", "willdurand/hateoas-bundle": "^2.7 || ^3.0",
"symfony/uid": "^6.4 || ^7.1",
"symfony/validator": "^6.4 || ^7.1",
"willdurand/hateoas-bundle": "^2.7",
"willdurand/negotiation": "^3.0" "willdurand/negotiation": "^3.0"
}, },
"suggest": { "suggest": {
@@ -3579,7 +3580,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/nelmio/NelmioApiDocBundle/issues", "issues": "https://github.com/nelmio/NelmioApiDocBundle/issues",
"source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v5.7.1" "source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v5.10.0"
}, },
"funding": [ "funding": [
{ {
@@ -3587,7 +3588,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-11-13T10:32:15+00:00" "time": "2026-04-10T14:26:01+00:00"
}, },
{ {
"name": "nelmio/cors-bundle", "name": "nelmio/cors-bundle",
@@ -3778,16 +3779,16 @@
}, },
{ {
"name": "openspout/openspout", "name": "openspout/openspout",
"version": "v4.25.0", "version": "v4.28.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/openspout/openspout.git", "url": "https://github.com/openspout/openspout.git",
"reference": "519affe730d92e1598720a6467227fc28550f0e6" "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/openspout/openspout/zipball/519affe730d92e1598720a6467227fc28550f0e6", "url": "https://api.github.com/repos/openspout/openspout/zipball/ab05a09fe6fce57c90338f83280648a9786ce36b",
"reference": "519affe730d92e1598720a6467227fc28550f0e6", "reference": "ab05a09fe6fce57c90338f83280648a9786ce36b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3797,17 +3798,17 @@
"ext-libxml": "*", "ext-libxml": "*",
"ext-xmlreader": "*", "ext-xmlreader": "*",
"ext-zip": "*", "ext-zip": "*",
"php": "~8.1.0 || ~8.2.0 || ~8.3.0" "php": "~8.2.0 || ~8.3.0 || ~8.4.0"
}, },
"require-dev": { "require-dev": {
"ext-zlib": "*", "ext-zlib": "*",
"friendsofphp/php-cs-fixer": "^3.64.0", "friendsofphp/php-cs-fixer": "^3.68.3",
"infection/infection": "^0.29.6", "infection/infection": "^0.29.10",
"phpbench/phpbench": "^1.3.1", "phpbench/phpbench": "^1.4.0",
"phpstan/phpstan": "^1.12.4", "phpstan/phpstan": "^2.1.2",
"phpstan/phpstan-phpunit": "^1.4.0", "phpstan/phpstan-phpunit": "^2.0.4",
"phpstan/phpstan-strict-rules": "^1.6.1", "phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "^10.5.20 || ^11.3.6" "phpunit/phpunit": "^11.5.4"
}, },
"suggest": { "suggest": {
"ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)", "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)",
@@ -3855,7 +3856,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/openspout/openspout/issues", "issues": "https://github.com/openspout/openspout/issues",
"source": "https://github.com/openspout/openspout/tree/v4.25.0" "source": "https://github.com/openspout/openspout/tree/v4.28.5"
}, },
"funding": [ "funding": [
{ {
@@ -3867,7 +3868,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-09-24T09:03:42+00:00" "time": "2025-01-30T13:51:11+00:00"
}, },
{ {
"name": "pagerfanta/pagerfanta", "name": "pagerfanta/pagerfanta",
@@ -4316,16 +4317,16 @@
}, },
{ {
"name": "phpoffice/phpspreadsheet", "name": "phpoffice/phpspreadsheet",
"version": "2.4.4", "version": "2.4.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "78bf6f0b4945ab31f1935741324ef3f0bf59a6fe" "reference": "ec7815be350e03df90f3e2ace92653fa6cb4327c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/78bf6f0b4945ab31f1935741324ef3f0bf59a6fe", "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/ec7815be350e03df90f3e2ace92653fa6cb4327c",
"reference": "78bf6f0b4945ab31f1935741324ef3f0bf59a6fe", "reference": "ec7815be350e03df90f3e2ace92653fa6cb4327c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4416,9 +4417,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.4.4" "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.4.5"
}, },
"time": "2026-04-10T03:20:38+00:00" "time": "2026-04-19T05:48:49+00:00"
}, },
{ {
"name": "phpoffice/phpword", "name": "phpoffice/phpword",
@@ -4929,6 +4930,68 @@
}, },
"time": "2021-10-29T13:26:27+00:00" "time": "2021-10-29T13:26:27+00:00"
}, },
{
"name": "radebatz/type-info-extras",
"version": "1.0.7",
"source": {
"type": "git",
"url": "https://github.com/DerManoMann/type-info-extras.git",
"reference": "95a524a74a61648b44e355cb33d38db4b17ef5ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DerManoMann/type-info-extras/zipball/95a524a74a61648b44e355cb33d38db4b17ef5ce",
"reference": "95a524a74a61648b44e355cb33d38db4b17ef5ce",
"shasum": ""
},
"require": {
"php": ">=8.2",
"phpstan/phpdoc-parser": "^2.0",
"symfony/type-info": "^7.3.8 || ^7.4.1 || ^8.0 || ^8.1-@dev"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.70",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^11.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Radebatz\\TypeInfoExtras\\": "src"
},
"exclude-from-classmap": [
"/tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Martin Rademacher",
"email": "mano@radebatz.org"
}
],
"description": "Extras for symfony/type-info",
"homepage": "http://radebatz.net/mano/",
"keywords": [
"component",
"symfony",
"type-info",
"types"
],
"support": {
"issues": "https://github.com/DerManoMann/type-info-extras/issues",
"source": "https://github.com/DerManoMann/type-info-extras/tree/1.0.7"
},
"time": "2026-03-06T22:40:29+00:00"
},
{ {
"name": "robrichards/xmlseclibs", "name": "robrichards/xmlseclibs",
"version": "3.1.5", "version": "3.1.5",
@@ -5259,16 +5322,16 @@
}, },
{ {
"name": "smalot/pdfparser", "name": "smalot/pdfparser",
"version": "v2.12.4", "version": "v2.12.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/smalot/pdfparser.git", "url": "https://github.com/smalot/pdfparser.git",
"reference": "028d7cc0ceff323bc001d763caa2bbdf611866c4" "reference": "2cfa0d92bd557875c9f52a75fde0e8392302a354"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/smalot/pdfparser/zipball/028d7cc0ceff323bc001d763caa2bbdf611866c4", "url": "https://api.github.com/repos/smalot/pdfparser/zipball/2cfa0d92bd557875c9f52a75fde0e8392302a354",
"reference": "028d7cc0ceff323bc001d763caa2bbdf611866c4", "reference": "2cfa0d92bd557875c9f52a75fde0e8392302a354",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5304,9 +5367,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/smalot/pdfparser/issues", "issues": "https://github.com/smalot/pdfparser/issues",
"source": "https://github.com/smalot/pdfparser/tree/v2.12.4" "source": "https://github.com/smalot/pdfparser/tree/v2.12.5"
}, },
"time": "2026-03-10T15:39:47+00:00" "time": "2026-04-17T11:37:58+00:00"
}, },
{ {
"name": "spomky-labs/otphp", "name": "spomky-labs/otphp",
@@ -9747,6 +9810,89 @@
], ],
"time": "2026-01-05T12:44:39+00:00" "time": "2026-01-05T12:44:39+00:00"
}, },
{
"name": "symfony/type-info",
"version": "v7.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/type-info.git",
"reference": "6bf34da885ff5143a3dfd8f1b863bb8ab95f50bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/type-info/zipball/6bf34da885ff5143a3dfd8f1b863bb8ab95f50bd",
"reference": "6bf34da885ff5143a3dfd8f1b863bb8ab95f50bd",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/container": "^1.1|^2.0",
"symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
"phpstan/phpdoc-parser": "<1.30"
},
"require-dev": {
"phpstan/phpdoc-parser": "^1.30|^2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\TypeInfo\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mathias Arlaud",
"email": "mathias.arlaud@gmail.com"
},
{
"name": "Baptiste LEDUC",
"email": "baptiste.leduc@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Extracts PHP types information.",
"homepage": "https://symfony.com",
"keywords": [
"PHPStan",
"phpdoc",
"symfony",
"type"
],
"support": {
"source": "https://github.com/symfony/type-info/tree/v7.4.8"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-03-24T13:12:05+00:00"
},
{ {
"name": "symfony/validator", "name": "symfony/validator",
"version": "v6.4.36", "version": "v6.4.36",
@@ -10650,23 +10796,23 @@
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "1.12.1", "version": "2.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozarts/assert.git", "url": "https://github.com/webmozarts/assert.git",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68" "reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", "url": "https://api.github.com/repos/webmozarts/assert/zipball/eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
"reference": "9be6926d8b485f55b9229203f962b51ed377ba68", "reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-ctype": "*", "ext-ctype": "*",
"ext-date": "*", "ext-date": "*",
"ext-filter": "*", "ext-filter": "*",
"php": "^7.2 || ^8.0" "php": "^8.2"
}, },
"suggest": { "suggest": {
"ext-intl": "", "ext-intl": "",
@@ -10676,7 +10822,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.10-dev" "dev-feature/2-0": "2.0-dev"
} }
}, },
"autoload": { "autoload": {
@@ -10692,6 +10838,10 @@
{ {
"name": "Bernhard Schussek", "name": "Bernhard Schussek",
"email": "bschussek@gmail.com" "email": "bschussek@gmail.com"
},
{
"name": "Woody Gilk",
"email": "woody.gilk@gmail.com"
} }
], ],
"description": "Assertions to validate method input/output with nice error messages.", "description": "Assertions to validate method input/output with nice error messages.",
@@ -10702,9 +10852,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/webmozarts/assert/issues", "issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.12.1" "source": "https://github.com/webmozarts/assert/tree/2.3.0"
}, },
"time": "2025-10-29T15:56:20+00:00" "time": "2026-04-11T10:33:05+00:00"
}, },
{ {
"name": "willdurand/jsonp-callback-validator", "name": "willdurand/jsonp-callback-validator",
@@ -10807,24 +10957,25 @@
}, },
{ {
"name": "zircote/swagger-php", "name": "zircote/swagger-php",
"version": "5.8.3", "version": "6.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/zircote/swagger-php.git", "url": "https://github.com/zircote/swagger-php.git",
"reference": "098223019f764a16715f64089a58606096719c98" "reference": "9447c1f45b5ae93185caea9a0c8e298399188a25"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/098223019f764a16715f64089a58606096719c98", "url": "https://api.github.com/repos/zircote/swagger-php/zipball/9447c1f45b5ae93185caea9a0c8e298399188a25",
"reference": "098223019f764a16715f64089a58606096719c98", "reference": "9447c1f45b5ae93185caea9a0c8e298399188a25",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"nikic/php-parser": "^4.19 || ^5.0", "nikic/php-parser": "^4.19 || ^5.0",
"php": ">=7.4", "php": ">=8.2",
"phpstan/phpdoc-parser": "^2.0", "phpstan/phpdoc-parser": "^2.0",
"psr/log": "^1.1 || ^2.0 || ^3.0", "psr/log": "^1.1 || ^2.0 || ^3.0",
"radebatz/type-info-extras": "^1.0.2",
"symfony/deprecation-contracts": "^2 || ^3", "symfony/deprecation-contracts": "^2 || ^3",
"symfony/finder": "^5.0 || ^6.0 || ^7.0 || ^8.0", "symfony/finder": "^5.0 || ^6.0 || ^7.0 || ^8.0",
"symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0" "symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0"
@@ -10836,14 +10987,9 @@
"composer/package-versions-deprecated": "^1.11", "composer/package-versions-deprecated": "^1.11",
"doctrine/annotations": "^2.0", "doctrine/annotations": "^2.0",
"friendsofphp/php-cs-fixer": "^3.62.0", "friendsofphp/php-cs-fixer": "^3.62.0",
"phpstan/phpstan": "^1.6 || ^2.0", "phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^9.0", "phpunit/phpunit": "^11.5",
"rector/rector": "^1.0 || ^2.3.1", "rector/rector": "^2.3.1"
"vimeo/psalm": "^4.30 || ^5.0"
},
"suggest": {
"doctrine/annotations": "^2.0",
"radebatz/type-info-extras": "^1.0.2"
}, },
"bin": [ "bin": [
"bin/openapi" "bin/openapi"
@@ -10851,7 +10997,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "5.x-dev" "dev-master": "6.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -10889,7 +11035,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/zircote/swagger-php/issues", "issues": "https://github.com/zircote/swagger-php/issues",
"source": "https://github.com/zircote/swagger-php/tree/5.8.3" "source": "https://github.com/zircote/swagger-php/tree/6.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -10897,7 +11043,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2026-03-02T00:47:18+00:00" "time": "2026-02-28T06:42:58+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [
@@ -11804,11 +11950,11 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "2.1.48", "version": "2.1.51",
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/231397213efb7c0a066ee024b5c3c87f2d3adfa0", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc3b523c45e714c70de2ac5113b958223b55dc59",
"reference": "231397213efb7c0a066ee024b5c3c87f2d3adfa0", "reference": "dc3b523c45e714c70de2ac5113b958223b55dc59",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11853,7 +11999,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2026-04-15T20:24:19+00:00" "time": "2026-04-21T18:22:01+00:00"
}, },
{ {
"name": "phpstan/phpstan-deprecation-rules", "name": "phpstan/phpstan-deprecation-rules",
@@ -11907,16 +12053,16 @@
}, },
{ {
"name": "phpstan/phpstan-doctrine", "name": "phpstan/phpstan-doctrine",
"version": "2.0.20", "version": "2.0.21",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan-doctrine.git", "url": "https://github.com/phpstan/phpstan-doctrine.git",
"reference": "72f4f7a02d6c98d9101e8616e0488bc0a785196d" "reference": "81dac0ee4363c2359128aec844df31efb215dddc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/72f4f7a02d6c98d9101e8616e0488bc0a785196d", "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/81dac0ee4363c2359128aec844df31efb215dddc",
"reference": "72f4f7a02d6c98d9101e8616e0488bc0a785196d", "reference": "81dac0ee4363c2359128aec844df31efb215dddc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11977,9 +12123,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan-doctrine/issues", "issues": "https://github.com/phpstan/phpstan-doctrine/issues",
"source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.20" "source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.21"
}, },
"time": "2026-03-13T13:44:51+00:00" "time": "2026-04-17T13:00:39+00:00"
}, },
{ {
"name": "phpstan/phpstan-phpunit", "name": "phpstan/phpstan-phpunit",
@@ -14524,7 +14670,7 @@
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": "8.1.*||8.2.*||8.3.*||8.4.*||8.5.*", "php": "8.2.*||8.3.*||8.4.*||8.5.*",
"ext-gd": "*", "ext-gd": "*",
"ext-intl": "*", "ext-intl": "*",
"ext-json": "*", "ext-json": "*",
@@ -14540,7 +14686,7 @@
"ext-simplexml": "*" "ext-simplexml": "*"
}, },
"platform-overrides": { "platform-overrides": {
"php": "8.1.3" "php": "8.2"
}, },
"plugin-api-version": "2.9.0" "plugin-api-version": "2.9.0"
} }

View File

@@ -67,5 +67,7 @@ nelmio_api_doc:
swagger_ui_config: [] swagger_ui_config: []
# https://redocly.com/docs/redoc/config/ # https://redocly.com/docs/redoc/config/
redocly_config: [] redocly_config: []
# https://scalar.com/products/api-references/configuration
scalar_config: []
# https://docs.stoplight.io/docs/elements/b074dc47b2826-elements-configuration-options # https://docs.stoplight.io/docs/elements/b074dc47b2826-elements-configuration-options
stoplight_config: { basePath: '/api/doc', router: 'memory', logo: '/touch-icon-192x192.png', hideInternal: true } stoplight_config: { basePath: '/api/doc', router: 'memory', logo: '/touch-icon-192x192.png', hideInternal: true }

180
kimai.sh
View File

@@ -6,13 +6,106 @@
# To improve this script across platforms I need your feedback! # To improve this script across platforms I need your feedback!
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
function verbose() {
if [[ "${IS_VERBOSE}" == "1" ]]; then
echo "$@"
fi
}
function flush_cache() {
rm -rf var/cache/* 2>&1
}
function reload_cache() {
flush_cache
bin/console cache:warmup
}
function composer_is_phar() {
[[ "${KIMAI_COMPOSER}" == *.phar ]]
}
function find_command_path() {
which "$1" 2>/dev/null
}
function resolve_executable() {
local executable="$1"
if [[ -z "${executable}" || "${executable}" == */* || "${executable}" == *.phar ]]; then
echo "${executable}"
return
fi
local resolved
resolved="$(find_command_path "${executable}")"
if [[ -n "${resolved}" ]]; then
echo "${resolved}"
else
echo "${executable}"
fi
}
function composer_exists() {
if composer_is_phar; then
[[ -f "${KIMAI_COMPOSER}" ]]
elif [[ "${KIMAI_COMPOSER}" == */* ]]; then
[[ -x "${KIMAI_COMPOSER}" ]]
else
command -v "${KIMAI_COMPOSER}" >/dev/null 2>&1
fi
}
function run_composer() {
#export COMPOSER_ALLOW_SUPERUSER=1
if composer_is_phar; then
"$KIMAI_PHP" "$KIMAI_COMPOSER" "$@"
else
"$KIMAI_COMPOSER" "$@"
fi
}
function confirm_update() {
local version="$1"
local answer
echo "About to update Kimai to version ${version}."
read -r -p "Continue? [y/N] " answer
if [[ ! "${answer}" =~ ^[Yy]([Ee][Ss])?$ ]]; then
echo "Update cancelled."
exit 1
fi
}
function update_kimai() { function update_kimai() {
if [[ "$1" =~ ^([0-9]+\.){2,3}[0-9]+$ ]]; then if [[ "$1" == "latest" ]]; then
if ! command -v sort >/dev/null 2>&1 || ! command -v tail >/dev/null 2>&1; then
echo "we could not detect the latest kimai version due to missing commands: sort, tail"
exit 1
fi
git fetch --tags
export VERSION="$(git tag --list | sort -V | tail -n 1)"
if [ -z "$VERSION" ]; then
echo "Failed loading Kimai version"
exit 1
fi
elif [[ "$1" =~ ^([0-9]+\.){2,3}[0-9]+$ ]]; then
export VERSION=$1 export VERSION=$1
else else
echo "You need to supply a full Kimai version like: \"2.24.0\"" echo "You need to supply a full Kimai version like: \"2.24.0\""
exit 1 exit 1
fi fi
git fetch --tags
if ! git rev-parse --verify --quiet "refs/tags/$VERSION" >/dev/null; then
echo "Requested Kimai version does not exist: $VERSION"
exit 1
fi
confirm_update "$VERSION"
git checkout -- composer.json git checkout -- composer.json
git checkout -- composer.lock git checkout -- composer.lock
git checkout -- symfony.lock git checkout -- symfony.lock
@@ -23,10 +116,10 @@ function update_kimai() {
fi fi
rm -rf var/sessions/ 2>&1 rm -rf var/sessions/ 2>&1
rm -rf var/cache/* 2>&1 flush_cache
git fetch --tags
git checkout "$VERSION" git checkout "$VERSION"
$KIMAI_PHP "$KIMAI_COMPOSER" install --no-dev --optimize-autoloader run_composer install --no-dev --optimize-autoloader || exit 1
$KIMAI_PHP bin/console kimai:install $KIMAI_PHP bin/console kimai:install
@@ -39,11 +132,22 @@ function update_kimai() {
function install_plugins() { function install_plugins() {
# detect if there are additional plugins that we need to install # detect if there are additional plugins that we need to install
packages="$($PHP bin/console kimai:plugin --composer)" local packages_output
export PACKAGES=$packages local -a packages
if [ -n "$PACKAGES" ]; then
$KIMAI_PHP "$KIMAI_COMPOSER" require "$PACKAGES" if ! packages_output="$($KIMAI_PHP bin/console kimai:plugin --composer)"; then
$KIMAI_PHP bin/console kimai:plugins --install echo "Failed loading plugin list from kimai:plugin --composer"
exit 1
fi
read -r -a packages <<< "$packages_output"
if [[ ${#packages[@]} -gt 0 ]]; then
verbose "Installing Composer plugins: ${packages[*]}"
run_composer require "${packages[@]} --update-no-dev --optimize-autoloader" || exit 1
$KIMAI_PHP bin/console kimai:plugins --install || exit 1
else
verbose "No Composer plugins detected."
fi fi
} }
@@ -53,6 +157,21 @@ function set_permission() {
chmod -R g+rw var/ chmod -R g+rw var/
} }
# ---------------------------------------------------------
# runtime logic below
export IS_VERBOSE=0
POSITIONAL_ARGS=()
for arg in "$@"; do
if [[ "${arg}" == "-v" ]]; then
export IS_VERBOSE=1
else
POSITIONAL_ARGS+=("${arg}")
fi
done
set -- "${POSITIONAL_ARGS[@]}"
if [[ -z "${KIMAI_USER}" ]]; then if [[ -z "${KIMAI_USER}" ]]; then
export KIMAI_USER="" export KIMAI_USER=""
fi fi
@@ -62,19 +181,36 @@ if [[ -z "${KIMAI_GROUP}" ]]; then
fi fi
if [[ -z "${KIMAI_PHP}" ]]; then if [[ -z "${KIMAI_PHP}" ]]; then
export KIMAI_PHP="php" php_path="$(find_command_path php)"
if [[ -n "${php_path}" ]]; then
export KIMAI_PHP="${php_path}"
else
export KIMAI_PHP="php"
fi
else
export KIMAI_PHP="$(resolve_executable "${KIMAI_PHP}")"
fi fi
if [[ -z "${KIMAI_COMPOSER}" ]]; then if [[ -z "${KIMAI_COMPOSER}" ]]; then
export KIMAI_COMPOSER="composer" composer_path="$(find_command_path composer)"
if [[ -n "${composer_path}" ]]; then
export KIMAI_COMPOSER="${composer_path}"
else
export KIMAI_COMPOSER="composer"
fi
else
export KIMAI_COMPOSER="$(resolve_executable "${KIMAI_COMPOSER}")"
fi fi
cd "$(dirname "$0")" || { echo "Cannot change working directory."; exit 1; } cd "$(dirname "$0")" || { echo "Cannot change working directory."; exit 1; }
# we need a few commands installed in order for this script to complete # we need a few commands installed in order for this script to complete
command -v $KIMAI_COMPOSER >/dev/null 2>&1 || { echo >&2 "Update requires 'composer' but it's not installed."; exit 1; } composer_exists || { echo >&2 "Update requires 'composer' but it's not installed or not executable."; exit 1; }
command -v git >/dev/null 2>&1 || { echo >&2 "Update requires 'git' but it's not installed."; exit 1; } command -v git >/dev/null 2>&1 || { echo >&2 "Update requires 'git' but it's not installed."; exit 1; }
command -v $KIMAI_PHP >/dev/null 2>&1 || { echo >&2 "Update requires 'php' but it's not installed."; exit 1; } command -v "$KIMAI_PHP" >/dev/null 2>&1 || { echo >&2 "Update requires 'php' but it's not installed."; exit 1; }
verbose "Using PHP: $KIMAI_PHP"
verbose "Using Composer: $KIMAI_COMPOSER"
if [[ -n $1 ]]; then if [[ -n $1 ]]; then
if [ "$1" == 'update' ]; then if [ "$1" == 'update' ]; then
@@ -83,9 +219,12 @@ if [[ -n $1 ]]; then
elif [ "$1" == 'permission' ]; then elif [ "$1" == 'permission' ]; then
set_permission set_permission
exit exit
elif [ "$1" == 'plugins' ]; then elif [ "$1" == 'plugins' ] || [ "$1" == 'plugin' ]; then
install_plugins install_plugins
exit exit
elif [ "$1" == 'cache' ]; then
reload_cache
exit
else else
echo "" echo ""
echo ">> Unknown command: $1" echo ">> Unknown command: $1"
@@ -95,9 +234,13 @@ fi
echo "" echo ""
echo "This script has the following sub-commands:" echo "This script has the following sub-commands:"
echo "" echo ""
echo "$0 update <version> - Install Kimai version <version>" echo "$0 update - Update Kimai to the latest version"
echo "$0 update <version> - Update Kimai to the given version <version>"
echo "$0 permission - Fix file permissions" echo "$0 permission - Fix file permissions"
echo "$0 plugins - Install plugins from var/packages/*.zip" echo "$0 plugin[s] - Install available plugins from var/packages/*.zip"
echo "$0 cache - Clear application cache"
echo ""
echo "Append -v anywhere in the command to enable verbose output"
echo "" echo ""
echo "Use the following environment variables to customize the runtime:" echo "Use the following environment variables to customize the runtime:"
echo "" echo ""
@@ -109,8 +252,9 @@ echo "KIMAI_NO_PERMS - Skip changing permissions"
echo "" echo ""
echo "Examples:" echo "Examples:"
echo "" echo ""
echo "$0 2.24.0" echo "$0 -v update"
echo "KIMAI_PHP=/usr/bin/php8.3 $0 2.24.0" echo "$0 update 2.54.0 -v"
echo "KIMAI_PHP=/usr/bin/php8.3 $0 2.54.0"
echo "KIMAI_PHP=/usr/bin/php8.3 KIMAI_COMPOSER=/tmp/composer.phar $0 2.24.0" echo "KIMAI_PHP=/usr/bin/php8.3 KIMAI_COMPOSER=/tmp/composer.phar $0 2.24.0"
echo "KIMAI_PHP=php8.3 KIMAI_GROUP=httpd $0 2.24.0" echo "KIMAI_PHP=php8.3 KIMAI_GROUP=httpd $0 2.24.0"
echo "KIMAI_NO_PERMS=1 KIMAI_PHP=/usr/bin/php8.3 $0 2.24.0" echo "KIMAI_NO_PERMS=1 KIMAI_PHP=/usr/bin/php8.3 $0 2.24.0"

View File

@@ -17,11 +17,11 @@ final class Constants
/** /**
* The current release version * The current release version
*/ */
public const VERSION = '2.55.0'; public const VERSION = '2.56.0';
/** /**
* The current release: major * 10000 + minor * 100 + patch * The current release: major * 10000 + minor * 100 + patch
*/ */
public const VERSION_ID = 25500; public const VERSION_ID = 25600;
/** /**
* The software name * The software name
*/ */

View File

@@ -36,7 +36,6 @@ class SpoutSpreadsheet implements SpreadsheetPackage
private readonly ?string $locale = null, private readonly ?string $locale = null,
) )
{ {
$this->writer->setCreator(Constants::SOFTWARE);
} }
/** /**
@@ -138,6 +137,10 @@ class SpoutSpreadsheet implements SpreadsheetPackage
public function save(): void public function save(): void
{ {
if ($this->writer instanceof XLSXWriter) {
$this->writer->setCreator(Constants::SOFTWARE);
}
$this->writer->close(); $this->writer->close();
} }
} }

View File

@@ -1,3 +1,23 @@
{%- macro duration(timesheet, options) -%}
<span
{%- if options and options.title is defined %} data-replacer="duration" data-title="true"{% endif -%}
{%- if not timesheet.end %} data-since="{{ timesheet.begin is null ? '' : timesheet.begin.format(constant('DATE_ISO8601')) }}"{% endif -%}
{# TODO calculate break and add as data-duration #}
class="duration {% if options and options.class is defined %} {{ options.class }}{% endif %}">
{{- timesheet.begin is null ? 0|duration : timesheet|duration -}}
</span>
{% endmacro %}
{%- macro duration_seconds(seconds, options) -%}
<span
{%- if options and options.title is defined %} data-replacer="duration" data-title="true" {% endif -%}
{%- if options and options.active is defined and options.active %} data-since="{{ create_date('- '~seconds~' seconds').format(constant('DATE_ISO8601')) }}" {% endif -%}
{# TODO calculate break and add as data-duration #}
class="duration {% if options and options.class is defined %} {{ options.class }}{% endif %}">
{{- seconds|duration -}}
</span>
{% endmacro %}
{%- macro search_filter(route, options) -%} {%- macro search_filter(route, options) -%}
{% set opts = {'performSearch': 1} %} {% set opts = {'performSearch': 1} %}
{% if options.begin is defined and options.end is defined %} {% if options.begin is defined and options.end is defined %}

View File

@@ -105,11 +105,7 @@
&dash; &dash;
{% endif %} {% endif %}
{% elseif column == 'duration' %} {% elseif column == 'duration' %}
{% if entry.end %} {{ widgets.duration(entry) }}
{{ entry.duration|duration }}
{% else %}
<i data-since="{{ entry.begin.format(constant('DATE_ISO8601')) }}">{{ entry|duration }}</i>
{% endif %}
{% elseif column == 'break' %} {% elseif column == 'break' %}
{{ entry.break|duration }} {{ entry.break|duration }}
{% elseif column == 'hourlyRate' %} {% elseif column == 'hourlyRate' %}

View File

@@ -2506,11 +2506,6 @@ parameters:
count: 1 count: 1
path: Widget/Type/MoreTest.php path: Widget/Type/MoreTest.php
-
message: "#^Cannot access offset 'financialBegin' on mixed\\.$#"
count: 2
path: Widget/Type/PaginatedWorkingTimeChartTest.php
- -
message: "#^Parameter \\#2 \\$array of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertArrayHasKey\\(\\) expects array\\|ArrayAccess, mixed given\\.$#" message: "#^Parameter \\#2 \\$array of static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertArrayHasKey\\(\\) expects array\\|ArrayAccess, mixed given\\.$#"
count: 2 count: 2