From 8eeb9c120a674532a75622b0ba322e4bd1f50a04 Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Wed, 3 Jan 2024 00:28:35 +0100 Subject: [PATCH] Release 2.8.0 (#4508) --- .github/workflows/lockfiles.yaml | 2 +- composer.json | 3 +- composer.lock | 560 +++++++++--------- config/packages/framework.yaml | 8 +- src/API/ActionsController.php | 11 +- src/API/ActivityController.php | 18 +- src/API/ConfigurationController.php | 4 +- src/API/CustomerController.php | 18 +- src/API/Model/CalendarEvent.php | 12 +- src/API/ProjectController.php | 18 +- src/API/StatusController.php | 8 +- src/API/TagController.php | 8 +- src/API/TeamController.php | 29 +- src/API/TimesheetController.php | 30 +- src/API/UserController.php | 12 +- src/Constants.php | 4 +- src/Controller/AbstractController.php | 10 - .../CustomerMonthlyProjectsController.php | 2 + .../Reporting/ReportUsersMonthController.php | 2 + .../Reporting/ReportUsersWeekController.php | 2 + .../Reporting/ReportUsersYearController.php | 2 + symfony.lock | 3 - .../reporting/user_list_period_data.html.twig | 38 +- translations/messages.de.xlf | 4 + translations/messages.en.xlf | 4 + translations/validators.de.xlf | 2 +- translations/validators.en.xlf | 2 +- 27 files changed, 409 insertions(+), 407 deletions(-) diff --git a/.github/workflows/lockfiles.yaml b/.github/workflows/lockfiles.yaml index 41998c67..746d9d30 100644 --- a/.github/workflows/lockfiles.yaml +++ b/.github/workflows/lockfiles.yaml @@ -19,5 +19,5 @@ jobs: uses: xalvarez/prevent-file-change-action@v1 with: githubToken: ${{ secrets.GITHUB_TOKEN }} - pattern: .*.lock + pattern: .*\.lock$ trustedAuthors: kevinpapst, dependabot diff --git a/composer.json b/composer.json index 9dc7dac9..a12207bb 100644 --- a/composer.json +++ b/composer.json @@ -43,7 +43,7 @@ "onelogin/php-saml": "^4.0", "pagerfanta/pagerfanta": "^3.0", "phpoffice/phpspreadsheet": "^1.16", - "phpoffice/phpword": "^1.0", + "phpoffice/phpword": "1.1.*", "psr/container": "^2.0", "psr/log": "^3.0", "scheb/2fa-backup-code": "^6.2", @@ -174,6 +174,7 @@ "bin/console lint:container", "bin/console lint:yaml config --parse-tags", "bin/console lint:twig templates --show-deprecations", + "bin/console doctrine:schema:validate --skip-sync -vvv --no-interaction", "bin/console lint:xliff translations" ], "tests": "vendor/bin/phpunit tests/", diff --git a/composer.lock b/composer.lock index 598c153f..804572e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a307b9a36c22711439283a3e5bc3249c", + "content-hash": "7b0ed62d4f9b4d06a6748c700fd04238", "packages": [ { "name": "azuyalabs/yasumi", @@ -1464,16 +1464,16 @@ }, { "name": "doctrine/orm", - "version": "2.17.1", + "version": "2.17.2", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "1a4fe6e0bb67762370937a7e6cee3da40a9122d1" + "reference": "393679a4795e49b0b3ac317dce84d0f8888f2b77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/1a4fe6e0bb67762370937a7e6cee3da40a9122d1", - "reference": "1a4fe6e0bb67762370937a7e6cee3da40a9122d1", + "url": "https://api.github.com/repos/doctrine/orm/zipball/393679a4795e49b0b3ac317dce84d0f8888f2b77", + "reference": "393679a4795e49b0b3ac317dce84d0f8888f2b77", "shasum": "" }, "require": { @@ -1506,10 +1506,10 @@ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.2", - "symfony/cache": "^4.4 || ^5.4 || ^6.0", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0", - "vimeo/psalm": "4.30.0 || 5.15.0" + "symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0", + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "vimeo/psalm": "4.30.0 || 5.16.0" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1559,9 +1559,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.17.1" + "source": "https://github.com/doctrine/orm/tree/2.17.2" }, - "time": "2023-11-17T06:25:40+00:00" + "time": "2023-12-20T21:47:52+00:00" }, { "name": "doctrine/persistence", @@ -2583,16 +2583,16 @@ }, { "name": "league/csv", - "version": "9.13.0", + "version": "9.14.0", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "3690cc71bfe8dc3b6daeef356939fac95348f0a8" + "reference": "34bf0df7340b60824b9449b5c526fcc3325070d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/3690cc71bfe8dc3b6daeef356939fac95348f0a8", - "reference": "3690cc71bfe8dc3b6daeef356939fac95348f0a8", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/34bf0df7340b60824b9449b5c526fcc3325070d5", + "reference": "34bf0df7340b60824b9449b5c526fcc3325070d5", "shasum": "" }, "require": { @@ -2668,7 +2668,7 @@ "type": "github" } ], - "time": "2023-12-16T11:03:20+00:00" + "time": "2023-12-29T07:34:53+00:00" }, { "name": "lorenzo/pinky", @@ -3246,64 +3246,64 @@ }, { "name": "nelmio/api-doc-bundle", - "version": "v4.12.0", + "version": "v4.15.1", "source": { "type": "git", "url": "https://github.com/nelmio/NelmioApiDocBundle.git", - "reference": "b9fc542143a4c38dc1a302b798a1caeb7d33484f" + "reference": "bef8b654ed410d16bf1086e2319ab215e5f36193" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/b9fc542143a4c38dc1a302b798a1caeb7d33484f", - "reference": "b9fc542143a4c38dc1a302b798a1caeb7d33484f", + "url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/bef8b654ed410d16bf1086e2319ab215e5f36193", + "reference": "bef8b654ed410d16bf1086e2319ab215e5f36193", "shasum": "" }, "require": { - "doctrine/annotations": "^2.0", "ext-json": "*", "php": ">=7.2", "phpdocumentor/reflection-docblock": "^3.1|^4.0|^5.0", "psr/cache": "^1.0|^2.0|^3.0", "psr/container": "^1.0|^2.0", "psr/log": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4.24|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/options-resolver": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", + "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/framework-bundle": "^5.4.24|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/options-resolver": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", "zircote/swagger-php": "^4.2.15" }, - "conflict": { - "symfony/framework-bundle": "4.2.7" - }, "require-dev": { - "api-platform/core": "^2.7.0|^3@dev", + "api-platform/core": "^2.7.0|^3", "composer/package-versions-deprecated": "1.11.99.1", + "doctrine/annotations": "^2.0", "friendsofsymfony/rest-bundle": "^2.8|^3.0", "jms/serializer": "^1.14|^3.0", - "jms/serializer-bundle": "^2.3|^3.0|^4.0|^5.0@beta", + "jms/serializer-bundle": "^2.3|^3.0|^4.0|^5.0", + "phpunit/phpunit": "^8.5|^9.6", "sensio/framework-extra-bundle": "^5.4|^6.0", - "symfony/asset": "^5.4|^6.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/cache": "^5.4|^6.0", + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/cache": "^5.4|^6.0|^7.0", "symfony/deprecation-contracts": "^2.1|^3", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/phpunit-bridge": "^5.4.23", - "symfony/property-access": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/templating": "^5.4|^6.0", - "symfony/twig-bundle": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/phpunit-bridge": "^6.4", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/templating": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/validator": "^5.4|^6.0|^7.0", "willdurand/hateoas-bundle": "^1.0|^2.0" }, "suggest": { "api-platform/core": "For using an API oriented framework.", + "doctrine/annotations": "For using doctrine annotations", "friendsofsymfony/rest-bundle": "For using the parameters annotations.", "jms/serializer-bundle": "For describing your models.", "symfony/asset": "For using the Swagger UI.", @@ -3352,9 +3352,9 @@ ], "support": { "issues": "https://github.com/nelmio/NelmioApiDocBundle/issues", - "source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v4.12.0" + "source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v4.15.1" }, - "time": "2023-06-16T10:39:21+00:00" + "time": "2024-01-02T14:56:33+00:00" }, { "name": "nelmio/cors-bundle", @@ -5016,16 +5016,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a" + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/ac2d25f97b17eec6e19760b6b9962a4f7c44356a", - "reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a", + "url": "https://api.github.com/repos/symfony/cache/zipball/14a75869bbb41cb35bc5d9d322473928c6f3f978", + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978", "shasum": "" }, "require": { @@ -5092,7 +5092,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.0" + "source": "https://github.com/symfony/cache/tree/v6.4.2" }, "funding": [ { @@ -5108,7 +5108,7 @@ "type": "tidelift" } ], - "time": "2023-11-24T19:28:07+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/cache-contracts", @@ -5188,16 +5188,16 @@ }, { "name": "symfony/clock", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "48102bcc56b26d453c7f5e7f72829abc9df25a16" + "reference": "0639710e65f73cc504167958ea29be6de5c7177a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/48102bcc56b26d453c7f5e7f72829abc9df25a16", - "reference": "48102bcc56b26d453c7f5e7f72829abc9df25a16", + "url": "https://api.github.com/repos/symfony/clock/zipball/0639710e65f73cc504167958ea29be6de5c7177a", + "reference": "0639710e65f73cc504167958ea29be6de5c7177a", "shasum": "" }, "require": { @@ -5242,7 +5242,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v6.4.0" + "source": "https://github.com/symfony/clock/tree/v6.4.2" }, "funding": [ { @@ -5258,7 +5258,7 @@ "type": "tidelift" } ], - "time": "2023-10-13T14:46:14+00:00" + "time": "2023-12-27T00:32:33+00:00" }, { "name": "symfony/config", @@ -5337,16 +5337,16 @@ }, { "name": "symfony/console", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd" + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a550a7c99daeedef3f9d23fb82e3531525ff11fd", - "reference": "a550a7c99daeedef3f9d23fb82e3531525ff11fd", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", "shasum": "" }, "require": { @@ -5411,7 +5411,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.1" + "source": "https://github.com/symfony/console/tree/v6.4.2" }, "funding": [ { @@ -5427,7 +5427,7 @@ "type": "tidelift" } ], - "time": "2023-11-30T10:54:28+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/css-selector", @@ -5496,16 +5496,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f88ff6428afbeb17cc648c8003bd608534750baf" + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f88ff6428afbeb17cc648c8003bd608534750baf", - "reference": "f88ff6428afbeb17cc648c8003bd608534750baf", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/226ea431b1eda6f0d9f5a4b278757171960bb195", + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195", "shasum": "" }, "require": { @@ -5557,7 +5557,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.1" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.2" }, "funding": [ { @@ -5573,7 +5573,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:56:37+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/deprecation-contracts", @@ -5644,16 +5644,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "bd181daf2851821c3aef20b779d37002cfd2e833" + "reference": "da33f27c1dd9946afecfd1585b867551df71bf53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/bd181daf2851821c3aef20b779d37002cfd2e833", - "reference": "bd181daf2851821c3aef20b779d37002cfd2e833", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/da33f27c1dd9946afecfd1585b867551df71bf53", + "reference": "da33f27c1dd9946afecfd1585b867551df71bf53", "shasum": "" }, "require": { @@ -5732,7 +5732,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.0" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.2" }, "funding": [ { @@ -5748,20 +5748,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T08:40:20+00:00" + "time": "2023-12-27T00:32:33+00:00" }, { "name": "symfony/dotenv", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "d0d584a91422ddaa2c94317200d4c4e5b935555f" + "reference": "835f8d2d1022934ac038519de40b88158798c96f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/d0d584a91422ddaa2c94317200d4c4e5b935555f", - "reference": "d0d584a91422ddaa2c94317200d4c4e5b935555f", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/835f8d2d1022934ac038519de40b88158798c96f", + "reference": "835f8d2d1022934ac038519de40b88158798c96f", "shasum": "" }, "require": { @@ -5806,7 +5806,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.0" + "source": "https://github.com/symfony/dotenv/tree/v6.4.2" }, "funding": [ { @@ -5822,7 +5822,7 @@ "type": "tidelift" } ], - "time": "2023-10-26T18:19:48+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/error-handler", @@ -5901,16 +5901,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6" + "reference": "e95216850555cd55e71b857eb9d6c2674124603a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a", + "reference": "e95216850555cd55e71b857eb9d6c2674124603a", "shasum": "" }, "require": { @@ -5961,7 +5961,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.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.2" }, "funding": [ { @@ -5977,7 +5977,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T06:52:43+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6057,16 +6057,16 @@ }, { "name": "symfony/expression-language", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "6c8b12f1e5ee5d91b812fb8628fca86e2fe5d152" + "reference": "7d63ccd5331d4164961776eced5524e891e30ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/6c8b12f1e5ee5d91b812fb8628fca86e2fe5d152", - "reference": "6c8b12f1e5ee5d91b812fb8628fca86e2fe5d152", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/7d63ccd5331d4164961776eced5524e891e30ad3", + "reference": "7d63ccd5331d4164961776eced5524e891e30ad3", "shasum": "" }, "require": { @@ -6101,7 +6101,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v6.4.0" + "source": "https://github.com/symfony/expression-language/tree/v6.4.2" }, "funding": [ { @@ -6117,7 +6117,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T06:52:43+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/filesystem", @@ -6248,16 +6248,16 @@ }, { "name": "symfony/flex", - "version": "v2.4.2", + "version": "v2.4.3", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "67ee785f1aedada76461de7a7ec10cd7f8ff8d36" + "reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/67ee785f1aedada76461de7a7ec10cd7f8ff8d36", - "reference": "67ee785f1aedada76461de7a7ec10cd7f8ff8d36", + "url": "https://api.github.com/repos/symfony/flex/zipball/6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1", + "reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1", "shasum": "" }, "require": { @@ -6293,7 +6293,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.4.2" + "source": "https://github.com/symfony/flex/tree/v2.4.3" }, "funding": [ { @@ -6309,7 +6309,7 @@ "type": "tidelift" } ], - "time": "2023-12-05T14:09:35+00:00" + "time": "2024-01-02T11:08:32+00:00" }, { "name": "symfony/form", @@ -6410,16 +6410,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "ac22d760bf9ff4440a1b6c7caef34d38b44290aa" + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ac22d760bf9ff4440a1b6c7caef34d38b44290aa", - "reference": "ac22d760bf9ff4440a1b6c7caef34d38b44290aa", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c26a221e0462027d1f9d4a802ed63f8ab07a43d0", + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0", "shasum": "" }, "require": { @@ -6447,7 +6447,7 @@ "symfony/asset": "<5.4", "symfony/asset-mapper": "<6.4", "symfony/clock": "<6.3", - "symfony/console": "<5.4", + "symfony/console": "<5.4|>=7.0", "symfony/dom-crawler": "<6.4", "symfony/dotenv": "<5.4", "symfony/form": "<5.4", @@ -6538,7 +6538,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.1" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.2" }, "funding": [ { @@ -6554,20 +6554,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T16:35:22+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/http-client", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "5c584530b77aa10ae216989ffc48b4bedc9c0b29" + "reference": "fc0944665bd932cf32a7b8a1d009466afc16528f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/5c584530b77aa10ae216989ffc48b4bedc9c0b29", - "reference": "5c584530b77aa10ae216989ffc48b4bedc9c0b29", + "url": "https://api.github.com/repos/symfony/http-client/zipball/fc0944665bd932cf32a7b8a1d009466afc16528f", + "reference": "fc0944665bd932cf32a7b8a1d009466afc16528f", "shasum": "" }, "require": { @@ -6631,7 +6631,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.0" + "source": "https://github.com/symfony/http-client/tree/v6.4.2" }, "funding": [ { @@ -6647,7 +6647,7 @@ "type": "tidelift" } ], - "time": "2023-11-28T20:55:58+00:00" + "time": "2023-12-02T12:49:56+00:00" }, { "name": "symfony/http-client-contracts", @@ -6729,16 +6729,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771" + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/44a6d39a9cc11e154547d882d5aac1e014440771", - "reference": "44a6d39a9cc11e154547d882d5aac1e014440771", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", "shasum": "" }, "require": { @@ -6786,7 +6786,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.4.0" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.2" }, "funding": [ { @@ -6802,20 +6802,20 @@ "type": "tidelift" } ], - "time": "2023-11-20T16:41:16+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b" + "reference": "13e8387320b5942d0dc408440c888e2d526efef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2953274c16a229b3933ef73a6898e18388e12e1b", - "reference": "2953274c16a229b3933ef73a6898e18388e12e1b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", + "reference": "13e8387320b5942d0dc408440c888e2d526efef4", "shasum": "" }, "require": { @@ -6899,7 +6899,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.1" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.2" }, "funding": [ { @@ -6915,20 +6915,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T17:02:02+00:00" + "time": "2023-12-30T15:31:44+00:00" }, { "name": "symfony/intl", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "41d16f0294b9ca6e5540728580c65cfa3848fbf5" + "reference": "4f45148f7eb984ef12b1f7e123205ab904828839" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/41d16f0294b9ca6e5540728580c65cfa3848fbf5", - "reference": "41d16f0294b9ca6e5540728580c65cfa3848fbf5", + "url": "https://api.github.com/repos/symfony/intl/zipball/4f45148f7eb984ef12b1f7e123205ab904828839", + "reference": "4f45148f7eb984ef12b1f7e123205ab904828839", "shasum": "" }, "require": { @@ -6981,7 +6981,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.4.0" + "source": "https://github.com/symfony/intl/tree/v6.4.2" }, "funding": [ { @@ -6997,20 +6997,20 @@ "type": "tidelift" } ], - "time": "2023-10-28T23:12:08+00:00" + "time": "2023-12-26T18:38:00+00:00" }, { "name": "symfony/mailer", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba" + "reference": "6da89e5c9202f129717a770a03183fb140720168" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", - "reference": "ca8dcf8892cdc5b4358ecf2528429bb5e706f7ba", + "url": "https://api.github.com/repos/symfony/mailer/zipball/6da89e5c9202f129717a770a03183fb140720168", + "reference": "6da89e5c9202f129717a770a03183fb140720168", "shasum": "" }, "require": { @@ -7061,7 +7061,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.4.0" + "source": "https://github.com/symfony/mailer/tree/v6.4.2" }, "funding": [ { @@ -7077,7 +7077,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T18:02:22+00:00" + "time": "2023-12-19T09:12:31+00:00" }, { "name": "symfony/mime", @@ -8043,16 +8043,16 @@ }, { "name": "symfony/rate-limiter", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/rate-limiter.git", - "reference": "b598ae785a3b3ee932c1fb638b1df86f0d36f81e" + "reference": "c32471a8ebe613f6856db4b0544fcf5429d12511" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/rate-limiter/zipball/b598ae785a3b3ee932c1fb638b1df86f0d36f81e", - "reference": "b598ae785a3b3ee932c1fb638b1df86f0d36f81e", + "url": "https://api.github.com/repos/symfony/rate-limiter/zipball/c32471a8ebe613f6856db4b0544fcf5429d12511", + "reference": "c32471a8ebe613f6856db4b0544fcf5429d12511", "shasum": "" }, "require": { @@ -8094,7 +8094,7 @@ "rate-limiter" ], "support": { - "source": "https://github.com/symfony/rate-limiter/tree/v6.4.0" + "source": "https://github.com/symfony/rate-limiter/tree/v6.4.2" }, "funding": [ { @@ -8110,20 +8110,20 @@ "type": "tidelift" } ], - "time": "2023-11-10T07:41:05+00:00" + "time": "2023-12-30T09:55:02+00:00" }, { "name": "symfony/routing", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40" + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0c95c164fdba18b12523b75e64199ca3503e6d40", - "reference": "0c95c164fdba18b12523b75e64199ca3503e6d40", + "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", "shasum": "" }, "require": { @@ -8177,7 +8177,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.1" + "source": "https://github.com/symfony/routing/tree/v6.4.2" }, "funding": [ { @@ -8193,7 +8193,7 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:54:37+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/runtime", @@ -8276,16 +8276,16 @@ }, { "name": "symfony/security-bundle", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "4fd31b7cb2a18f62c5a8588b82a44fd240b41a9e" + "reference": "97d4fb6dbee700937738036ec54b0fcb0641d7d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/4fd31b7cb2a18f62c5a8588b82a44fd240b41a9e", - "reference": "4fd31b7cb2a18f62c5a8588b82a44fd240b41a9e", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/97d4fb6dbee700937738036ec54b0fcb0641d7d6", + "reference": "97d4fb6dbee700937738036ec54b0fcb0641d7d6", "shasum": "" }, "require": { @@ -8368,7 +8368,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/security-bundle/tree/v6.4.2" }, "funding": [ { @@ -8384,7 +8384,7 @@ "type": "tidelift" } ], - "time": "2023-10-31T14:46:20+00:00" + "time": "2023-12-24T09:11:31+00:00" }, { "name": "symfony/security-core", @@ -8629,16 +8629,16 @@ }, { "name": "symfony/serializer", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "7ead272e62c9567df619ef3c49809bf934ddbc1f" + "reference": "f87ea9d7bfd4cf2f7b72be554607e6c96e6664af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/7ead272e62c9567df619ef3c49809bf934ddbc1f", - "reference": "7ead272e62c9567df619ef3c49809bf934ddbc1f", + "url": "https://api.github.com/repos/symfony/serializer/zipball/f87ea9d7bfd4cf2f7b72be554607e6c96e6664af", + "reference": "f87ea9d7bfd4cf2f7b72be554607e6c96e6664af", "shasum": "" }, "require": { @@ -8707,7 +8707,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.1" + "source": "https://github.com/symfony/serializer/tree/v6.4.2" }, "funding": [ { @@ -8723,25 +8723,25 @@ "type": "tidelift" } ], - "time": "2023-12-01T14:54:37+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/b3313c2dbffaf71c8de2934e2ea56ed2291a3838", - "reference": "b3313c2dbffaf71c8de2934e2ea56ed2291a3838", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -8789,7 +8789,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -8805,7 +8805,7 @@ "type": "tidelift" } ], - "time": "2023-07-30T20:28:31+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/stopwatch", @@ -8871,16 +8871,16 @@ }, { "name": "symfony/string", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809" + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/b45fcf399ea9c3af543a92edf7172ba21174d809", - "reference": "b45fcf399ea9c3af543a92edf7172ba21174d809", + "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", "shasum": "" }, "require": { @@ -8937,7 +8937,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.0" + "source": "https://github.com/symfony/string/tree/v6.4.2" }, "funding": [ { @@ -8953,20 +8953,20 @@ "type": "tidelift" } ], - "time": "2023-11-28T20:41:49+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/translation", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37" + "reference": "a2ab2ec1a462e53016de8e8d5e8912bfd62ea681" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", - "reference": "b1035dbc2a344b21f8fa8ac451c7ecec4ea45f37", + "url": "https://api.github.com/repos/symfony/translation/zipball/a2ab2ec1a462e53016de8e8d5e8912bfd62ea681", + "reference": "a2ab2ec1a462e53016de8e8d5e8912bfd62ea681", "shasum": "" }, "require": { @@ -9032,7 +9032,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.0" + "source": "https://github.com/symfony/translation/tree/v6.4.2" }, "funding": [ { @@ -9048,20 +9048,20 @@ "type": "tidelift" } ], - "time": "2023-11-29T08:14:36+00:00" + "time": "2023-12-18T09:25:29+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.4.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + "reference": "06450585bf65e978026bda220cdebca3f867fde7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", + "reference": "06450585bf65e978026bda220cdebca3f867fde7", "shasum": "" }, "require": { @@ -9110,7 +9110,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" }, "funding": [ { @@ -9126,20 +9126,20 @@ "type": "tidelift" } ], - "time": "2023-07-25T15:08:44+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf" + "reference": "97af829e4733125ee70e806694d56165c60b4ee1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf", - "reference": "142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/97af829e4733125ee70e806694d56165c60b4ee1", + "reference": "97af829e4733125ee70e806694d56165c60b4ee1", "shasum": "" }, "require": { @@ -9219,7 +9219,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.0" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.2" }, "funding": [ { @@ -9235,7 +9235,7 @@ "type": "tidelift" } ], - "time": "2023-11-25T08:25:13+00:00" + "time": "2023-12-15T12:36:48+00:00" }, { "name": "symfony/twig-bundle", @@ -9323,16 +9323,16 @@ }, { "name": "symfony/validator", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "33e1f3bb76ef70e3170e12f878aefb9c69b0fc4c" + "reference": "15fe2c6ed815b06b6b8636d8ba3ef9807ee1a75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/33e1f3bb76ef70e3170e12f878aefb9c69b0fc4c", - "reference": "33e1f3bb76ef70e3170e12f878aefb9c69b0fc4c", + "url": "https://api.github.com/repos/symfony/validator/zipball/15fe2c6ed815b06b6b8636d8ba3ef9807ee1a75c", + "reference": "15fe2c6ed815b06b6b8636d8ba3ef9807ee1a75c", "shasum": "" }, "require": { @@ -9399,7 +9399,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.0" + "source": "https://github.com/symfony/validator/tree/v6.4.2" }, "funding": [ { @@ -9415,20 +9415,20 @@ "type": "tidelift" } ], - "time": "2023-11-29T07:47:42+00:00" + "time": "2023-12-29T16:34:12+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", "shasum": "" }, "require": { @@ -9484,7 +9484,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.0" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" }, "funding": [ { @@ -9500,20 +9500,20 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:28:32+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "2d08ca6b9cc704dce525615d1e6d1788734f36d9" + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/2d08ca6b9cc704dce525615d1e6d1788734f36d9", - "reference": "2d08ca6b9cc704dce525615d1e6d1788734f36d9", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5fe9a0021b8d35e67d914716ec8de50716a68e7e", + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e", "shasum": "" }, "require": { @@ -9559,7 +9559,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.1" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.2" }, "funding": [ { @@ -9575,7 +9575,7 @@ "type": "tidelift" } ], - "time": "2023-11-30T10:32:10+00:00" + "time": "2023-12-27T08:18:35+00:00" }, { "name": "symfony/webpack-encore-bundle", @@ -10340,16 +10340,16 @@ }, { "name": "zircote/swagger-php", - "version": "4.8.1", + "version": "4.8.2", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "2a2ae434965f5c497713e05d1398fc9476dfdeb0" + "reference": "a70a5dc5db26183c86f589ff3d76fb11e141fc58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/2a2ae434965f5c497713e05d1398fc9476dfdeb0", - "reference": "2a2ae434965f5c497713e05d1398fc9476dfdeb0", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/a70a5dc5db26183c86f589ff3d76fb11e141fc58", + "reference": "a70a5dc5db26183c86f589ff3d76fb11e141fc58", "shasum": "" }, "require": { @@ -10415,9 +10415,9 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/4.8.1" + "source": "https://github.com/zircote/swagger-php/tree/4.8.2" }, - "time": "2023-12-11T08:35:08+00:00" + "time": "2023-12-19T19:59:07+00:00" } ], "packages-dev": [ @@ -10798,16 +10798,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01" + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", - "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", + "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", "shasum": "" }, "require": { @@ -10833,11 +10833,6 @@ "ext-mbstring": "Required for multibyte Unicode string functionality." }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "v1.21-dev" - } - }, "autoload": { "psr-4": { "Faker\\": "src/Faker/" @@ -10860,22 +10855,22 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" }, - "time": "2023-06-12T08:44:38+00:00" + "time": "2024-01-02T13:46:09+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.41.1", + "version": "v3.45.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6" + "reference": "c0daa33cb2533cd73f48dde1c70c2afa3e7953b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6", - "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/c0daa33cb2533cd73f48dde1c70c2afa3e7953b5", + "reference": "c0daa33cb2533cd73f48dde1c70c2afa3e7953b5", "shasum": "" }, "require": { @@ -10905,8 +10900,7 @@ "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", - "phpunit/phpunit": "^9.6", - "symfony/phpunit-bridge": "^6.3.8 || ^7.0", + "phpunit/phpunit": "^9.6 || ^10.5.5", "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { @@ -10945,7 +10939,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.45.0" }, "funding": [ { @@ -10953,7 +10947,7 @@ "type": "github" } ], - "time": "2023-12-10T19:59:27+00:00" + "time": "2023-12-30T02:07:07+00:00" }, { "name": "masterminds/html5", @@ -11424,16 +11418,16 @@ }, { "name": "phpstan/phpstan-symfony", - "version": "1.3.5", + "version": "1.3.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-symfony.git", - "reference": "27ff6339f83796a7e0dd963cf445cd3c456fc620" + "reference": "34b3c43684834f6a20aa51af8d455480d9de8b88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/27ff6339f83796a7e0dd963cf445cd3c456fc620", - "reference": "27ff6339f83796a7e0dd963cf445cd3c456fc620", + "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/34b3c43684834f6a20aa51af8d455480d9de8b88", + "reference": "34b3c43684834f6a20aa51af8d455480d9de8b88", "shasum": "" }, "require": { @@ -11490,29 +11484,29 @@ "description": "Symfony Framework extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-symfony/issues", - "source": "https://github.com/phpstan/phpstan-symfony/tree/1.3.5" + "source": "https://github.com/phpstan/phpstan-symfony/tree/1.3.6" }, - "time": "2023-10-30T14:52:15+00:00" + "time": "2023-12-22T11:22:34+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.29", + "version": "9.2.30", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", - "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "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.15", + "nikic/php-parser": "^4.18 || ^5.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -11562,7 +11556,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" }, "funding": [ { @@ -11570,7 +11564,7 @@ "type": "github" } ], - "time": "2023-09-19T04:57:46+00:00" + "time": "2023-12-22T06:47:57+00:00" }, { "name": "phpunit/php-file-iterator", @@ -12158,20 +12152,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": { @@ -12203,7 +12197,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": [ { @@ -12211,7 +12205,7 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-12-22T06:19:30+00:00" }, { "name": "sebastian/diff", @@ -12485,20 +12479,20 @@ }, { "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": { @@ -12530,7 +12524,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": [ { @@ -12538,7 +12532,7 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-12-22T06:20:34+00:00" }, { "name": "sebastian/object-enumerator", @@ -13090,16 +13084,16 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v6.4.1", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "cca5373a41d45edbeaf38b7b67f376da2205ff95" + "reference": "bd0455b7888e4adac29cf175d819c51f88fed942" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/cca5373a41d45edbeaf38b7b67f376da2205ff95", - "reference": "cca5373a41d45edbeaf38b7b67f376da2205ff95", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/bd0455b7888e4adac29cf175d819c51f88fed942", + "reference": "bd0455b7888e4adac29cf175d819c51f88fed942", "shasum": "" }, "require": { @@ -13151,7 +13145,7 @@ "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.1" + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.2" }, "funding": [ { @@ -13167,20 +13161,20 @@ "type": "tidelift" } ], - "time": "2023-12-01T09:25:07+00:00" + "time": "2023-12-19T09:12:31+00:00" }, { "name": "symfony/process", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa" + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/191703b1566d97a5425dc969e4350d32b8ef17aa", - "reference": "191703b1566d97a5425dc969e4350d32b8ef17aa", + "url": "https://api.github.com/repos/symfony/process/zipball/c4b1ef0bc80533d87a2e969806172f1c2a980241", + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241", "shasum": "" }, "require": { @@ -13212,7 +13206,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.0" + "source": "https://github.com/symfony/process/tree/v6.4.2" }, "funding": [ { @@ -13228,20 +13222,20 @@ "type": "tidelift" } ], - "time": "2023-11-17T21:06:49+00:00" + "time": "2023-12-22T16:42:54+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.0", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "14752d3fb77c3c69b6cee7c03c06e2d6494a196b" + "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/14752d3fb77c3c69b6cee7c03c06e2d6494a196b", - "reference": "14752d3fb77c3c69b6cee7c03c06e2d6494a196b", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/38462d16856740ec0d1ba2cb902eebf09100dde2", + "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2", "shasum": "" }, "require": { @@ -13294,7 +13288,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.2" }, "funding": [ { @@ -13310,7 +13304,7 @@ "type": "tidelift" } ], - "time": "2023-11-07T14:57:07+00:00" + "time": "2023-12-27T08:18:35+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index cad3a437..9848d766 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -1,9 +1,12 @@ framework: # Deprecations for 7.0 handle_all_throwables: true - # cannot be disabled, because of https://github.com/nelmio/NelmioApiDocBundle/pull/2164 annotations: - enabled: true + enabled: false + + serializer: + enable_attributes: true + # --------------------------- exceptions: @@ -32,6 +35,7 @@ framework: validation: email_validation_mode: html5 + enable_attributes: true when@dev: framework: diff --git a/src/API/ActionsController.php b/src/API/ActionsController.php index e561d0e5..03d1e56d 100644 --- a/src/API/ActionsController.php +++ b/src/API/ActionsController.php @@ -15,14 +15,13 @@ use App\Entity\Customer; use App\Entity\Project; use App\Entity\Timesheet; use App\Event\PageActionsEvent; -use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\Translation\TranslatorInterface; @@ -73,7 +72,7 @@ final class ActionsController extends BaseApiController #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet ID to fetch', required: true)] #[OA\Parameter(name: 'view', in: 'path', description: 'View to display the actions at (e.g. index, custom)', required: true)] #[OA\Parameter(name: 'locale', in: 'path', description: 'Language to translate the action title to (e.g. de, en)', required: true)] - #[Rest\Get(path: '/timesheet/{id}/{view}/{locale}', name: 'get_timesheet_actions', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/timesheet/{id}/{view}/{locale}', name: 'get_timesheet_actions', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getTimesheetActions(Timesheet $timesheet, string $view, string $locale): Response @@ -93,7 +92,7 @@ final class ActionsController extends BaseApiController #[OA\Parameter(name: 'id', in: 'path', description: 'Activity ID to fetch', required: true)] #[OA\Parameter(name: 'view', in: 'path', description: 'View to display the actions at (e.g. index, custom)', required: true)] #[OA\Parameter(name: 'locale', in: 'path', description: 'Language to translate the action title to (e.g. de, en)', required: true)] - #[Rest\Get(path: '/activity/{id}/{view}/{locale}', name: 'get_activity_actions', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/activity/{id}/{view}/{locale}', name: 'get_activity_actions', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getActivityActions(Activity $activity, string $view, string $locale): Response @@ -113,7 +112,7 @@ final class ActionsController extends BaseApiController #[OA\Parameter(name: 'id', in: 'path', description: 'Project ID to fetch', required: true)] #[OA\Parameter(name: 'view', in: 'path', description: 'View to display the actions at (e.g. index, custom)', required: true)] #[OA\Parameter(name: 'locale', in: 'path', description: 'Language to translate the action title to (e.g. de, en)', required: true)] - #[Rest\Get(path: '/project/{id}/{view}/{locale}', name: 'get_project_actions', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/project/{id}/{view}/{locale}', name: 'get_project_actions', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getProjectActions(Project $project, string $view, string $locale): Response @@ -133,7 +132,7 @@ final class ActionsController extends BaseApiController #[OA\Parameter(name: 'id', in: 'path', description: 'Customer ID to fetch', required: true)] #[OA\Parameter(name: 'view', in: 'path', description: 'View to display the actions at (e.g. index, custom)', required: true)] #[OA\Parameter(name: 'locale', in: 'path', description: 'Language to translate the action title to (e.g. de, en)', required: true)] - #[Rest\Get(path: '/customer/{id}/{view}/{locale}', name: 'get_customer_actions', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/customer/{id}/{view}/{locale}', name: 'get_customer_actions', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getCustomerActions(Customer $customer, string $view, string $locale): Response diff --git a/src/API/ActivityController.php b/src/API/ActivityController.php index fe72917e..b1b652ff 100644 --- a/src/API/ActivityController.php +++ b/src/API/ActivityController.php @@ -30,7 +30,7 @@ use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/activities')] @@ -55,7 +55,7 @@ final class ActivityController extends BaseApiController * Returns a collection of activities (which are visible to the user) */ #[OA\Response(response: 200, description: 'Returns a collection of activities', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/ActivityCollection')))] - #[Rest\Get(path: '', name: 'get_activities')] + #[Route(methods: ['GET'], path: '', name: 'get_activities')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'project', requirements: '\d+', strict: true, nullable: true, description: 'Project ID to filter activities')] @@ -125,7 +125,7 @@ final class ActivityController extends BaseApiController */ #[OA\Response(response: 200, description: 'Returns one activity entity', content: new OA\JsonContent(ref: '#/components/schemas/ActivityEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Activity ID to fetch', required: true)] - #[Rest\Get(path: '/{id}', name: 'get_activity', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}', name: 'get_activity', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getAction(Activity $activity): Response @@ -141,7 +141,7 @@ final class ActivityController extends BaseApiController */ #[OA\Post(description: 'Creates a new activity and returns it afterwards', responses: [new OA\Response(response: 200, description: 'Returns the new created activity', content: new OA\JsonContent(ref: '#/components/schemas/ActivityEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/ActivityEditForm'))] - #[Rest\Post(path: '', name: 'post_activity')] + #[Route(methods: ['POST'], path: '', name: 'post_activity')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postAction(Request $request): Response @@ -184,7 +184,7 @@ final class ActivityController extends BaseApiController #[OA\Patch(description: 'Update an existing activity, you can pass all or just a subset of all attributes', responses: [new OA\Response(response: 200, description: 'Returns the updated activity', content: new OA\JsonContent(ref: '#/components/schemas/ActivityEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/ActivityEditForm'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Activity ID to update', required: true)] - #[Rest\Patch(path: '/{id}', name: 'patch_activity', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_activity', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function patchAction(Request $request, Activity $activity): Response @@ -221,7 +221,7 @@ final class ActivityController extends BaseApiController #[IsGranted('edit', 'activity')] #[OA\Response(response: 200, description: 'Sets the value of an existing/configured meta-field. You cannot create unknown meta-fields, if the given name is not a configured meta-field, this will return an exception.', content: new OA\JsonContent(ref: '#/components/schemas/ActivityEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Activity record ID to set the meta-field value for', required: true)] - #[Rest\Patch(path: '/{id}/meta', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/meta', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\RequestParam(name: 'name', strict: true, nullable: false, description: 'The meta-field name')] @@ -254,7 +254,7 @@ final class ActivityController extends BaseApiController #[IsGranted('edit', 'activity')] #[OA\Response(response: 200, description: 'Returns a collection of activity rate entities', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/ActivityRate')))] #[OA\Parameter(name: 'id', in: 'path', description: 'The activity whose rates will be returned', required: true)] - #[Rest\Get(path: '/{id}/rates', name: 'get_activity_rates', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}/rates', name: 'get_activity_rates', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getRatesAction(Activity $activity): Response @@ -276,7 +276,7 @@ final class ActivityController extends BaseApiController #[OA\Parameter(name: 'rateId', in: 'path', description: 'The rate to remove', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}/rates/{rateId}', name: 'delete_activity_rate', requirements: ['id' => '\d+', 'rateId' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}/rates/{rateId}', name: 'delete_activity_rate', requirements: ['id' => '\d+', 'rateId' => '\d+'])] public function deleteRateAction(Activity $activity, #[MapEntity(mapping: ['rateId' => 'id'])] ActivityRate $rate): Response { if ($rate->getActivity() !== $activity) { @@ -297,7 +297,7 @@ final class ActivityController extends BaseApiController #[OA\Post(responses: [new OA\Response(response: 200, description: 'Returns the new created rate', content: new OA\JsonContent(ref: '#/components/schemas/ActivityRate'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The activity to add the rate for', required: true)] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/ActivityRateForm'))] - #[Rest\Post(path: '/{id}/rates', name: 'post_activity_rate', requirements: ['id' => '\d+'])] + #[Route(methods: ['POST'], path: '/{id}/rates', name: 'post_activity_rate', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postRateAction(Activity $activity, Request $request): Response diff --git a/src/API/ConfigurationController.php b/src/API/ConfigurationController.php index 6db094d5..a02438ec 100644 --- a/src/API/ConfigurationController.php +++ b/src/API/ConfigurationController.php @@ -11,13 +11,13 @@ namespace App\API; use App\API\Model\TimesheetConfig; use App\Configuration\SystemConfiguration; -use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[IsGranted('IS_AUTHENTICATED_REMEMBERED')] @@ -32,7 +32,7 @@ final class ConfigurationController extends BaseApiController * Returns the timesheet configuration */ #[OA\Response(response: 200, description: 'Returns the instance specific timesheet configuration', content: new OA\JsonContent(ref: new Model(type: TimesheetConfig::class)))] - #[Rest\Get(path: '/config/timesheet')] + #[Route(methods: ['GET'], path: '/config/timesheet')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function timesheetConfigAction(SystemConfiguration $configuration): Response diff --git a/src/API/CustomerController.php b/src/API/CustomerController.php index 55cab78d..6daf608e 100644 --- a/src/API/CustomerController.php +++ b/src/API/CustomerController.php @@ -30,7 +30,7 @@ use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/customers')] @@ -55,7 +55,7 @@ final class CustomerController extends BaseApiController * Returns a collection of customers (which are visible to the user) */ #[OA\Response(response: 200, description: 'Returns a collection of customers', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/CustomerCollection')))] - #[Rest\Get(path: '', name: 'get_customers')] + #[Route(methods: ['GET'], path: '', name: 'get_customers')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'visible', requirements: '1|2|3', default: 1, strict: true, nullable: true, description: 'Visibility status to filter customers: 1=visible, 2=hidden, 3=both')] @@ -102,7 +102,7 @@ final class CustomerController extends BaseApiController * Returns one customer */ #[OA\Response(response: 200, description: 'Returns one customer entity', content: new OA\JsonContent(ref: '#/components/schemas/CustomerEntity'))] - #[Rest\Get(path: '/{id}', name: 'get_customer', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}', name: 'get_customer', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getAction(Customer $customer): Response @@ -118,7 +118,7 @@ final class CustomerController extends BaseApiController */ #[OA\Post(description: 'Creates a new customer and returns it afterwards', responses: [new OA\Response(response: 200, description: 'Returns the new created customer', content: new OA\JsonContent(ref: '#/components/schemas/CustomerEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/CustomerEditForm'))] - #[Rest\Post(path: '', name: 'post_customer')] + #[Route(methods: ['POST'], path: '', name: 'post_customer')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postAction(Request $request, CustomerService $customerService): Response @@ -161,7 +161,7 @@ final class CustomerController extends BaseApiController #[OA\Patch(description: 'Update an existing customer, you can pass all or just a subset of all attributes', responses: [new OA\Response(response: 200, description: 'Returns the updated customer', content: new OA\JsonContent(ref: '#/components/schemas/CustomerEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/CustomerEditForm'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Customer ID to update', required: true)] - #[Rest\Patch(path: '/{id}', name: 'patch_customer', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_customer', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function patchAction(Request $request, Customer $customer): Response @@ -198,7 +198,7 @@ final class CustomerController extends BaseApiController #[IsGranted('edit', 'customer')] #[OA\Response(response: 200, description: 'Sets the value of an existing/configured meta-field. You cannot create unknown meta-fields, if the given name is not a configured meta-field, this will return an exception.', content: new OA\JsonContent(ref: '#/components/schemas/CustomerEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Customer record ID to set the meta-field value for', required: true)] - #[Rest\Patch(path: '/{id}/meta', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/meta', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\RequestParam(name: 'name', strict: true, nullable: false, description: 'The meta-field name')] @@ -231,7 +231,7 @@ final class CustomerController extends BaseApiController #[IsGranted('edit', 'customer')] #[OA\Response(response: 200, description: 'Returns a collection of customer rate entities', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/CustomerRate')))] #[OA\Parameter(name: 'id', in: 'path', description: 'The customer whose rates will be returned', required: true)] - #[Rest\Get(path: '/{id}/rates', name: 'get_customer_rates', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}/rates', name: 'get_customer_rates', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getRatesAction(Customer $customer): Response @@ -253,7 +253,7 @@ final class CustomerController extends BaseApiController #[OA\Parameter(name: 'rateId', in: 'path', description: 'The rate to remove', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}/rates/{rateId}', name: 'delete_customer_rate', requirements: ['id' => '\d+', 'rateId' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}/rates/{rateId}', name: 'delete_customer_rate', requirements: ['id' => '\d+', 'rateId' => '\d+'])] public function deleteRateAction(Customer $customer, #[MapEntity(mapping: ['rateId' => 'id'])] CustomerRate $rate): Response { if ($rate->getCustomer() !== $customer) { @@ -274,7 +274,7 @@ final class CustomerController extends BaseApiController #[OA\Post(responses: [new OA\Response(response: 200, description: 'Returns the new created rate', content: new OA\JsonContent(ref: '#/components/schemas/CustomerRate'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The customer to add the rate for', required: true)] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/CustomerRateForm'))] - #[Rest\Post(path: '/{id}/rates', name: 'post_customer_rate', requirements: ['id' => '\d+'])] + #[Route(methods: ['POST'], path: '/{id}/rates', name: 'post_customer_rate', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postRateAction(Customer $customer, Request $request): Response diff --git a/src/API/Model/CalendarEvent.php b/src/API/Model/CalendarEvent.php index d6d59612..d637570c 100644 --- a/src/API/Model/CalendarEvent.php +++ b/src/API/Model/CalendarEvent.php @@ -48,15 +48,15 @@ final class CalendarEvent */ #[Serializer\Expose] #[Serializer\Groups(['Default'])] - #[Serializer\Type(name: 'DateTime')] - private \DateTimeInterface $start; // @phpstan-ignore-line + #[Serializer\Type(name: 'DateTimeImmutable')] + private \DateTimeImmutable $start; // @phpstan-ignore-line /** * Calendar entry end date */ #[Serializer\Expose] #[Serializer\Groups(['Default'])] - #[Serializer\Type(name: 'DateTime')] - private \DateTimeInterface $end; // @phpstan-ignore-line + #[Serializer\Type(name: 'DateTimeImmutable')] + private \DateTimeImmutable $end; // @phpstan-ignore-line public function setTitle(string $title): void { @@ -65,12 +65,12 @@ final class CalendarEvent public function setStart(\DateTimeInterface $start): void { - $this->start = $start; + $this->start = \DateTimeImmutable::createFromInterface($start); } public function setEnd(\DateTimeInterface $end): void { - $this->end = $end; + $this->end = \DateTimeImmutable::createFromInterface($end); } public function setColor(?string $color): void diff --git a/src/API/ProjectController.php b/src/API/ProjectController.php index 89e636cf..ef57aa05 100644 --- a/src/API/ProjectController.php +++ b/src/API/ProjectController.php @@ -31,7 +31,7 @@ use Psr\EventDispatcher\EventDispatcherInterface; use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Validator\Constraints; @@ -58,7 +58,7 @@ final class ProjectController extends BaseApiController * Returns a collection of projects (which are visible to the user) */ #[OA\Response(response: 200, description: 'Returns a collection of projects', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/ProjectCollection')))] - #[Rest\Get(path: '', name: 'get_projects')] + #[Route(methods: ['GET'], path: '', name: 'get_projects')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'customer', requirements: '\d+', strict: true, nullable: true, description: 'Customer ID to filter projects')] @@ -156,7 +156,7 @@ final class ProjectController extends BaseApiController * Returns one project */ #[OA\Response(response: 200, description: 'Returns one project entity', content: new OA\JsonContent(ref: '#/components/schemas/ProjectEntity'))] - #[Rest\Get(path: '/{id}', name: 'get_project', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}', name: 'get_project', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getAction(Project $project): Response @@ -172,7 +172,7 @@ final class ProjectController extends BaseApiController */ #[OA\Post(description: 'Creates a new project and returns it afterwards', responses: [new OA\Response(response: 200, description: 'Returns the new created project', content: new OA\JsonContent(ref: '#/components/schemas/ProjectEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/ProjectEditForm'))] - #[Rest\Post(path: '', name: 'post_project')] + #[Route(methods: ['POST'], path: '', name: 'post_project')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postAction(Request $request): Response @@ -214,7 +214,7 @@ final class ProjectController extends BaseApiController #[OA\Patch(description: 'Update an existing project, you can pass all or just a subset of all attributes', responses: [new OA\Response(response: 200, description: 'Returns the updated project', content: new OA\JsonContent(ref: '#/components/schemas/ProjectEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/ProjectEditForm'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Project ID to update', required: true)] - #[Rest\Patch(path: '/{id}', name: 'patch_project', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_project', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function patchAction(Request $request, Project $project): Response @@ -253,7 +253,7 @@ final class ProjectController extends BaseApiController #[IsGranted('edit', 'project')] #[OA\Response(response: 200, description: 'Sets the value of an existing/configured meta-field. You cannot create unknown meta-fields, if the given name is not a configured meta-field, this will return an exception.', content: new OA\JsonContent(ref: '#/components/schemas/ProjectEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Project record ID to set the meta-field value for', required: true)] - #[Rest\Patch(path: '/{id}/meta', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/meta', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\RequestParam(name: 'name', strict: true, nullable: false, description: 'The meta-field name')] @@ -286,7 +286,7 @@ final class ProjectController extends BaseApiController #[IsGranted('edit', 'project')] #[OA\Response(response: 200, description: 'Returns a collection of project rate entities', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/ProjectRate')))] #[OA\Parameter(name: 'id', in: 'path', description: 'The project whose rates will be returned', required: true)] - #[Rest\Get(path: '/{id}/rates', name: 'get_project_rates', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}/rates', name: 'get_project_rates', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getRatesAction(Project $project): Response @@ -308,7 +308,7 @@ final class ProjectController extends BaseApiController #[OA\Parameter(name: 'rateId', in: 'path', description: 'The rate to remove', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}/rates/{rateId}', name: 'delete_project_rate', requirements: ['id' => '\d+', 'rateId' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}/rates/{rateId}', name: 'delete_project_rate', requirements: ['id' => '\d+', 'rateId' => '\d+'])] public function deleteRateAction(Project $project, #[MapEntity(mapping: ['rateId' => 'id'])] ProjectRate $rate): Response { if ($rate->getProject() !== $project) { @@ -329,7 +329,7 @@ final class ProjectController extends BaseApiController #[OA\Post(responses: [new OA\Response(response: 200, description: 'Returns the new created rate', content: new OA\JsonContent(ref: '#/components/schemas/ProjectRate'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The project to add the rate for', required: true)] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/ProjectRateForm'))] - #[Rest\Post(path: '/{id}/rates', name: 'post_project_rate', requirements: ['id' => '\d+'])] + #[Route(methods: ['POST'], path: '/{id}/rates', name: 'post_project_rate', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postRateAction(Project $project, Request $request): Response diff --git a/src/API/StatusController.php b/src/API/StatusController.php index 65a403f0..0ae04f0e 100644 --- a/src/API/StatusController.php +++ b/src/API/StatusController.php @@ -12,13 +12,13 @@ namespace App\API; use App\API\Model\Plugin; use App\API\Model\Version; use App\Plugin\PluginManager; -use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[IsGranted('IS_AUTHENTICATED_REMEMBERED')] @@ -33,7 +33,7 @@ final class StatusController extends BaseApiController * A testing route for the API */ #[OA\Response(response: 200, description: "A simple route that returns a 'pong', which you can use for testing the API", content: new OA\JsonContent(example: "{'message': 'pong'}"))] - #[Rest\Get(path: '/ping')] + #[Route(methods: ['GET'], path: '/ping')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function pingAction(): Response @@ -47,7 +47,7 @@ final class StatusController extends BaseApiController * Returns information about the Kimai release */ #[OA\Response(response: 200, description: 'Returns version information about the current release', content: new OA\JsonContent(ref: new Model(type: Version::class)))] - #[Rest\Get(path: '/version')] + #[Route(methods: ['GET'], path: '/version')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function versionAction(): Response @@ -59,7 +59,7 @@ final class StatusController extends BaseApiController * Returns information about installed Plugins */ #[OA\Response(response: 200, description: 'Returns a list of plugin names and versions', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: new Model(type: Plugin::class))))] - #[Rest\Get(path: '/plugins')] + #[Route(methods: ['GET'], path: '/plugins')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function pluginAction(PluginManager $pluginManager): Response diff --git a/src/API/TagController.php b/src/API/TagController.php index 4769941e..70599e63 100644 --- a/src/API/TagController.php +++ b/src/API/TagController.php @@ -20,7 +20,7 @@ use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/tags')] @@ -40,7 +40,7 @@ final class TagController extends BaseApiController * Fetch all existing tags */ #[OA\Response(response: 200, description: 'Returns the collection of all existing tags as string array', content: new OA\JsonContent(type: 'array', items: new OA\Items(type: 'string')))] - #[Rest\Get(name: 'get_tags')] + #[Route(methods: ['GET'], name: 'get_tags')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'name', strict: true, nullable: true, description: 'Search term to filter tag list')] @@ -61,7 +61,7 @@ final class TagController extends BaseApiController */ #[OA\Post(description: 'Creates a new tag and returns it afterwards', responses: [new OA\Response(response: 200, description: 'Returns the new created tag', content: new OA\JsonContent(ref: '#/components/schemas/TagEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/TagEditForm'))] - #[Rest\Post(name: 'post_tag')] + #[Route(methods: ['POST'], name: 'post_tag')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postAction(Request $request): Response @@ -99,7 +99,7 @@ final class TagController extends BaseApiController #[OA\Parameter(name: 'id', in: 'path', description: 'Tag ID to delete', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}', name: 'delete_tag')] + #[Route(methods: ['DELETE'], path: '/{id}', name: 'delete_tag')] public function deleteAction(Tag $tag): Response { $this->repository->deleteTag($tag); diff --git a/src/API/TeamController.php b/src/API/TeamController.php index eed13902..51597648 100644 --- a/src/API/TeamController.php +++ b/src/API/TeamController.php @@ -19,7 +19,6 @@ use App\Repository\ActivityRepository; use App\Repository\CustomerRepository; use App\Repository\ProjectRepository; use App\Repository\TeamRepository; -use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; @@ -28,7 +27,7 @@ use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/teams')] @@ -49,7 +48,7 @@ final class TeamController extends BaseApiController */ #[IsGranted('view_team')] #[OA\Response(response: 200, description: 'Returns the collection of teams', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/TeamCollection')))] - #[Rest\Get(path: '', name: 'get_teams')] + #[Route(methods: ['GET'], path: '', name: 'get_teams')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function cgetAction(): Response @@ -67,7 +66,7 @@ final class TeamController extends BaseApiController */ #[IsGranted('view_team')] #[OA\Response(response: 200, description: 'Returns one team entity', content: new OA\JsonContent(ref: '#/components/schemas/Team'))] - #[Rest\Get(path: '/{id}', name: 'get_team', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}', name: 'get_team', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getAction(Team $team): Response @@ -86,7 +85,7 @@ final class TeamController extends BaseApiController #[OA\Parameter(name: 'id', in: 'path', description: 'Team ID to delete', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}', name: 'delete_team', requirements: ['id' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}', name: 'delete_team', requirements: ['id' => '\d+'])] public function deleteAction(Team $team): Response { $this->repository->deleteTeam($team); @@ -102,7 +101,7 @@ final class TeamController extends BaseApiController #[IsGranted('create_team')] #[OA\Post(description: 'Creates a new team and returns it afterwards', responses: [new OA\Response(response: 200, description: 'Returns the new created team', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/TeamEditForm'))] - #[Rest\Post(path: '', name: 'post_team')] + #[Route(methods: ['POST'], path: '', name: 'post_team')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postAction(Request $request): Response @@ -134,7 +133,7 @@ final class TeamController extends BaseApiController #[OA\Patch(description: 'Update an existing team, you can pass all or just a subset of all attributes (passing members will replace all existing ones)', responses: [new OA\Response(response: 200, description: 'Returns the updated team', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/TeamEditForm'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Team ID to update', required: true)] - #[Rest\Patch(path: '/{id}', name: 'patch_team', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_team', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function patchAction(Request $request, Team $team): Response @@ -174,7 +173,7 @@ final class TeamController extends BaseApiController #[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new user to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team which will receive the new member', required: true)] #[OA\Parameter(name: 'userId', in: 'path', description: 'The team member to add (User ID)', required: true)] - #[Rest\Post(path: '/{id}/members/{userId}', name: 'post_team_member', requirements: ['id' => '\d+', 'userId' => '\d+'])] + #[Route(methods: ['POST'], path: '/{id}/members/{userId}', name: 'post_team_member', requirements: ['id' => '\d+', 'userId' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postMemberAction(Team $team, #[MapEntity(mapping: ['userId' => 'id'])] User $member): Response @@ -202,7 +201,7 @@ final class TeamController extends BaseApiController #[OA\Parameter(name: 'userId', in: 'path', description: 'The team member to remove (User ID)', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}/members/{userId}', name: 'delete_team_member', requirements: ['id' => '\d+', 'userId' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}/members/{userId}', name: 'delete_team_member', requirements: ['id' => '\d+', 'userId' => '\d+'])] public function deleteMemberAction(Team $team, #[MapEntity(mapping: ['userId' => 'id'])] User $member): Response { if (!$member->isInTeam($team)) { @@ -230,7 +229,7 @@ final class TeamController extends BaseApiController #[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new customer to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team that is granted access', required: true)] #[OA\Parameter(name: 'customerId', in: 'path', description: 'The customer to grant acecess to (Customer ID)', required: true)] - #[Rest\Post(path: '/{id}/customers/{customerId}', name: 'post_team_customer', requirements: ['id' => '\d+', 'customerId' => '\d+'])] + #[Route(methods: ['POST'], path: '/{id}/customers/{customerId}', name: 'post_team_customer', requirements: ['id' => '\d+', 'customerId' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postCustomerAction(Team $team, #[MapEntity(mapping: ['customerId' => 'id'])] Customer $customer, CustomerRepository $customerRepository): Response @@ -257,7 +256,7 @@ final class TeamController extends BaseApiController #[OA\Parameter(name: 'customerId', in: 'path', description: 'The customer to remove (Customer ID)', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}/customers/{customerId}', name: 'delete_team_customer', requirements: ['id' => '\d+', 'customerId' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}/customers/{customerId}', name: 'delete_team_customer', requirements: ['id' => '\d+', 'customerId' => '\d+'])] public function deleteCustomerAction(Team $team, #[MapEntity(mapping: ['customerId' => 'id'])] Customer $customer, CustomerRepository $customerRepository): Response { if (!$team->hasCustomer($customer)) { @@ -280,7 +279,7 @@ final class TeamController extends BaseApiController #[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new project to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team that is granted access', required: true)] #[OA\Parameter(name: 'projectId', in: 'path', description: 'The project to grant acecess to (Project ID)', required: true)] - #[Rest\Post(path: '/{id}/projects/{projectId}', name: 'post_team_project', requirements: ['id' => '\d+', 'projectId' => '\d+'])] + #[Route(methods: ['POST'], path: '/{id}/projects/{projectId}', name: 'post_team_project', requirements: ['id' => '\d+', 'projectId' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postProjectAction(Team $team, #[MapEntity(mapping: ['projectId' => 'id'])] Project $project, ProjectRepository $projectRepository): Response @@ -307,7 +306,7 @@ final class TeamController extends BaseApiController #[OA\Parameter(name: 'projectId', in: 'path', description: 'The project to remove (Project ID)', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}/projects/{projectId}', name: 'delete_team_project', requirements: ['id' => '\d+', 'projectId' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}/projects/{projectId}', name: 'delete_team_project', requirements: ['id' => '\d+', 'projectId' => '\d+'])] public function deleteProjectAction(Team $team, #[MapEntity(mapping: ['projectId' => 'id'])] Project $project, ProjectRepository $projectRepository): Response { if (!$team->hasProject($project)) { @@ -330,7 +329,7 @@ final class TeamController extends BaseApiController #[OA\Post(responses: [new OA\Response(response: 200, description: 'Adds a new activity to a team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team that is granted access', required: true)] #[OA\Parameter(name: 'activityId', in: 'path', description: 'The activity to grant acecess to (Activity ID)', required: true)] - #[Rest\Post(path: '/{id}/activities/{activityId}', name: 'post_team_activity', requirements: ['id' => '\d+', 'activityId' => '\d+'])] + #[Route(methods: ['POST'], path: '/{id}/activities/{activityId}', name: 'post_team_activity', requirements: ['id' => '\d+', 'activityId' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postActivityAction(Team $team, #[MapEntity(mapping: ['activityId' => 'id'])] Activity $activity, ActivityRepository $activityRepository): Response @@ -357,7 +356,7 @@ final class TeamController extends BaseApiController #[OA\Parameter(name: 'activityId', in: 'path', description: 'The activity to remove (Activity ID)', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}/activities/{activityId}', name: 'delete_team_activity', requirements: ['id' => '\d+', 'activityId' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}/activities/{activityId}', name: 'delete_team_activity', requirements: ['id' => '\d+', 'activityId' => '\d+'])] public function deleteActivityAction(Team $team, #[MapEntity(mapping: ['activityId' => 'id'])] Activity $activity, ActivityRepository $activityRepository): Response { if (!$team->hasActivity($activity)) { diff --git a/src/API/TimesheetController.php b/src/API/TimesheetController.php index 8e2fa9e5..9952a64a 100644 --- a/src/API/TimesheetController.php +++ b/src/API/TimesheetController.php @@ -38,7 +38,7 @@ use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Validator\Constraints; @@ -72,7 +72,7 @@ final class TimesheetController extends BaseApiController */ #[IsGranted(new Expression("is_granted('view_own_timesheet') or is_granted('view_other_timesheet')"))] #[OA\Response(response: 200, description: 'Returns a collection of timesheet records. The datetime fields are given in the users local time including the timezone offset (ISO-8601).', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/TimesheetCollection')))] - #[Rest\Get(path: '', name: 'get_timesheets')] + #[Route(methods: ['GET'], path: '', name: 'get_timesheets')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'user', requirements: '\d+|all', strict: true, nullable: true, description: "User ID to filter timesheets. Needs permission 'view_other_timesheet', pass 'all' to fetch data for all user (default: current user)")] @@ -273,7 +273,7 @@ final class TimesheetController extends BaseApiController #[IsGranted('view', 'timesheet')] #[OA\Response(response: 200, description: 'Returns one timesheet record. Be aware that the datetime fields are given in the users local time including the timezone offset via ISO 8601.', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to fetch', required: true)] - #[Rest\Get(path: '/{id}', name: 'get_timesheet', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}', name: 'get_timesheet', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getAction(Timesheet $timesheet): Response @@ -290,7 +290,7 @@ final class TimesheetController extends BaseApiController #[IsGranted('create_own_timesheet')] #[OA\Post(description: 'Creates a new timesheet record for the current user and returns it afterwards.', responses: [new OA\Response(response: 200, description: 'Returns the new created timesheet', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEditForm'))] - #[Rest\Post(path: '', name: 'post_timesheet')] + #[Route(methods: ['POST'], path: '', name: 'post_timesheet')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'full', strict: true, nullable: true, description: 'Allows to fetch fully serialized objects including subresources (TimesheetExpanded). Allowed values: true (default: false)')] @@ -346,7 +346,7 @@ final class TimesheetController extends BaseApiController #[OA\Patch(description: 'Update an existing timesheet record, you can pass all or just a subset of the attributes.', responses: [new OA\Response(response: 200, description: 'Returns the updated timesheet', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to update', required: true)] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEditForm'))] - #[Rest\Patch(path: '/{id}', name: 'patch_timesheet', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_timesheet', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function patchAction(Request $request, Timesheet $timesheet): Response @@ -392,7 +392,7 @@ final class TimesheetController extends BaseApiController #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to delete', required: true)] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Rest\Delete(path: '/{id}', name: 'delete_timesheet', requirements: ['id' => '\d+'])] + #[Route(methods: ['DELETE'], path: '/{id}', name: 'delete_timesheet', requirements: ['id' => '\d+'])] public function deleteAction(Timesheet $timesheet): Response { $this->service->deleteTimesheet($timesheet); @@ -407,7 +407,7 @@ final class TimesheetController extends BaseApiController */ #[IsGranted('view_own_timesheet')] #[OA\Response(response: 200, description: 'Returns the collection of recent user activities (always the latest entry of a unique working set grouped by customer, project and activity)', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/TimesheetCollectionExpanded')))] - #[Rest\Get(path: '/recent', name: 'recent_timesheet')] + #[Route(methods: ['GET'], path: '/recent', name: 'recent_timesheet')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'begin', requirements: [new Constraints\DateTime(format: 'Y-m-d\TH:i:s')], strict: true, nullable: true, description: 'Only records after this date will be included. Default: today - 1 year (format: HTML5)')] @@ -443,7 +443,7 @@ final class TimesheetController extends BaseApiController */ #[IsGranted('view_own_timesheet')] #[OA\Response(response: 200, description: 'Returns the collection of active timesheet records for the current user', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/TimesheetCollectionExpanded')))] - #[Rest\Get(path: '/active', name: 'active_timesheet')] + #[Route(methods: ['GET'], path: '/active', name: 'active_timesheet')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function activeAction(): Response @@ -468,8 +468,8 @@ final class TimesheetController extends BaseApiController #[IsGranted('stop', 'timesheet')] #[OA\Response(response: 200, description: 'Stops an active timesheet record and returns it afterwards.', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to stop', required: true)] - #[Rest\Get(path: '/{id}/stop', name: 'stop_timesheet_get', requirements: ['id' => '\d+'])] - #[Rest\Patch(path: '/{id}/stop', name: 'stop_timesheet', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}/stop', name: 'stop_timesheet_get', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/stop', name: 'stop_timesheet', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function stopAction(Timesheet $timesheet): Response @@ -488,8 +488,8 @@ final class TimesheetController extends BaseApiController #[IsGranted('start', 'timesheet')] #[OA\Response(response: 200, description: 'Restarts a timesheet record for the same customer, project, activity combination. The current user will be the owner of the new record. Kimai tries to stop running records, which is expected to fail depending on the configured rules. Data will be copied from the original record if requested.', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to restart', required: true)] - #[Rest\Get(path: '/{id}/restart', name: 'restart_timesheet_get', requirements: ['id' => '\d+'])] - #[Rest\Patch(path: '/{id}/restart', name: 'restart_timesheet', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}/restart', name: 'restart_timesheet_get', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/restart', name: 'restart_timesheet', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\RequestParam(name: 'copy', requirements: 'all', strict: true, nullable: true, description: 'Whether data should be copied to the new entry. Allowed values: all (default: nothing is copied)')] @@ -551,7 +551,7 @@ final class TimesheetController extends BaseApiController #[IsGranted('duplicate', 'timesheet')] #[OA\Response(response: 200, description: 'Duplicates a timesheet record, resetting the export state only.', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to duplicate', required: true)] - #[Rest\Patch(path: '/{id}/duplicate', name: 'duplicate_timesheet', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/duplicate', name: 'duplicate_timesheet', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function duplicateAction(Timesheet $timesheet): Response @@ -574,7 +574,7 @@ final class TimesheetController extends BaseApiController #[IsGranted('edit_export', 'timesheet')] #[OA\Response(response: 200, description: 'Switches the exported state on the record and therefor locks / unlocks it for further updates. Needs edit_export_*_timesheet permission.', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to switch export state', required: true)] - #[Rest\Patch(path: '/{id}/export', name: 'export_timesheet', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/export', name: 'export_timesheet', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function exportAction(Timesheet $timesheet): Response @@ -599,7 +599,7 @@ final class TimesheetController extends BaseApiController #[IsGranted('edit', 'timesheet')] #[OA\Response(response: 200, description: 'Sets the value of an existing/configured meta-field. You cannot create unknown meta-fields, if the given name is not a configured meta-field, this will return an exception.', content: new OA\JsonContent(ref: '#/components/schemas/TimesheetEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to set the meta-field value for', required: true)] - #[Rest\Patch(path: '/{id}/meta', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}/meta', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\RequestParam(name: 'name', strict: true, nullable: false, description: 'The meta-field name')] diff --git a/src/API/UserController.php b/src/API/UserController.php index 5f8ee6b1..a1474386 100644 --- a/src/API/UserController.php +++ b/src/API/UserController.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; -use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/users')] @@ -54,7 +54,7 @@ final class UserController extends BaseApiController */ #[IsGranted('view_user')] #[OA\Response(response: 200, description: 'Returns the collection of users. Required permission: view_user', content: new OA\JsonContent(type: 'array', items: new OA\Items(ref: '#/components/schemas/UserCollection')))] - #[Rest\Get(path: '', name: 'get_users')] + #[Route(methods: ['GET'], path: '', name: 'get_users')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] #[Rest\QueryParam(name: 'visible', requirements: '1|2|3', default: 1, strict: true, nullable: true, description: 'Visibility status to filter users: 1=visible, 2=hidden, 3=all')] @@ -107,7 +107,7 @@ final class UserController extends BaseApiController #[IsGranted('view', 'profile')] #[OA\Response(response: 200, description: 'Return one user entity.', content: new OA\JsonContent(ref: '#/components/schemas/UserEntity'))] #[OA\Parameter(name: 'id', in: 'path', description: 'User ID to fetch', required: true)] - #[Rest\Get(path: '/{id}', name: 'get_user', requirements: ['id' => '\d+'])] + #[Route(methods: ['GET'], path: '/{id}', name: 'get_user', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function getAction(User $profile, EventDispatcherInterface $dispatcher): Response @@ -126,7 +126,7 @@ final class UserController extends BaseApiController * Return the current user entity */ #[OA\Response(response: 200, description: 'Return the current user entity.', content: new OA\JsonContent(ref: '#/components/schemas/UserEntity'))] - #[Rest\Get(path: '/me', name: 'me_user')] + #[Route(methods: ['GET'], path: '/me', name: 'me_user')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function meAction(): Response @@ -143,7 +143,7 @@ final class UserController extends BaseApiController #[IsGranted('create_user')] #[OA\Post(description: 'Creates a new user and returns it afterwards')] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/UserCreateForm'))] - #[Rest\Post(path: '', name: 'post_user')] + #[Route(methods: ['POST'], path: '', name: 'post_user')] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function postAction(Request $request): Response @@ -197,7 +197,7 @@ final class UserController extends BaseApiController #[OA\Patch(description: 'Update an existing user, you can pass all or just a subset of all attributes (passing roles will replace all existing ones)', responses: [new OA\Response(response: 200, description: 'Returns the updated user', content: new OA\JsonContent(ref: '#/components/schemas/UserEntity'))])] #[OA\RequestBody(required: true, content: new OA\JsonContent(ref: '#/components/schemas/UserEditForm'))] #[OA\Parameter(name: 'id', in: 'path', description: 'User ID to update', required: true)] - #[Rest\Patch(path: '/{id}', name: 'patch_user', requirements: ['id' => '\d+'])] + #[Route(methods: ['PATCH'], path: '/{id}', name: 'patch_user', requirements: ['id' => '\d+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] public function patchAction(Request $request, User $profile): Response diff --git a/src/Constants.php b/src/Constants.php index 879187b6..a1394d2d 100644 --- a/src/Constants.php +++ b/src/Constants.php @@ -17,11 +17,11 @@ class Constants /** * The current release version */ - public const VERSION = '2.7.0'; + public const VERSION = '2.8.0'; /** * The current release: major * 10000 + minor * 100 + patch */ - public const VERSION_ID = 20700; + public const VERSION_ID = 20800; /** * The software name */ diff --git a/src/Controller/AbstractController.php b/src/Controller/AbstractController.php index 8f6c0b44..c88d7986 100644 --- a/src/Controller/AbstractController.php +++ b/src/Controller/AbstractController.php @@ -159,11 +159,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv /** * Adds a fully translated (both $message and all keys in $parameter) flash message to the stack. * - * @param string $type - * @param string $message * @param array $parameter - * @return void - * @throws \Exception */ private function addFlashTranslated(string $type, string $message, array $parameter = []): void { @@ -183,9 +179,6 @@ abstract class AbstractController extends BaseAbstractController implements Serv /** * Handles exception flash messages for failed update/create actions. - * @param \Exception $exception - * @param FormInterface $form - * @return void */ protected function handleFormUpdateException(\Exception $exception, FormInterface $form): void { @@ -262,10 +255,7 @@ abstract class AbstractController extends BaseAbstractController implements Serv } /** - * @param FormInterface $form - * @param Request $request * @param array $filterParams parameter names, which should not be saved (neither session, nor database) - * @return bool * @throws \Exception */ protected function handleSearch(FormInterface $form, Request $request, array $filterParams = []): bool diff --git a/src/Controller/Reporting/CustomerMonthlyProjectsController.php b/src/Controller/Reporting/CustomerMonthlyProjectsController.php index f0a8ca84..0d1a8ba6 100644 --- a/src/Controller/Reporting/CustomerMonthlyProjectsController.php +++ b/src/Controller/Reporting/CustomerMonthlyProjectsController.php @@ -16,6 +16,7 @@ use App\Reporting\CustomerMonthlyProjects\CustomerMonthlyProjects; use App\Reporting\CustomerMonthlyProjects\CustomerMonthlyProjectsForm; use App\Reporting\CustomerMonthlyProjects\CustomerMonthlyProjectsRepository; use App\Repository\Query\UserQuery; +use App\Repository\Query\VisibilityInterface; use App\Repository\UserRepository; use PhpOffice\PhpSpreadsheet\Reader\Html; use Symfony\Component\HttpFoundation\Request; @@ -58,6 +59,7 @@ final class CustomerMonthlyProjectsController extends AbstractController $dateTimeFactory = $this->getDateTimeFactory(); $query = new UserQuery(); + $query->setVisibility(VisibilityInterface::SHOW_BOTH); $query->setSystemAccount(false); $query->setCurrentUser($currentUser); $allUsers = $userRepository->getUsersForQuery($query); diff --git a/src/Controller/Reporting/ReportUsersMonthController.php b/src/Controller/Reporting/ReportUsersMonthController.php index 087e4231..56992faa 100644 --- a/src/Controller/Reporting/ReportUsersMonthController.php +++ b/src/Controller/Reporting/ReportUsersMonthController.php @@ -16,6 +16,7 @@ use App\Model\DailyStatistic; use App\Reporting\MonthlyUserList\MonthlyUserList; use App\Reporting\MonthlyUserList\MonthlyUserListForm; use App\Repository\Query\UserQuery; +use App\Repository\Query\VisibilityInterface; use App\Repository\UserRepository; use App\Timesheet\TimesheetStatisticService; use PhpOffice\PhpSpreadsheet\Reader\Html; @@ -68,6 +69,7 @@ final class ReportUsersMonthController extends AbstractController $form->submit($request->query->all(), false); $query = new UserQuery(); + $query->setVisibility(VisibilityInterface::SHOW_BOTH); $query->setSystemAccount(false); $query->setCurrentUser($currentUser); diff --git a/src/Controller/Reporting/ReportUsersWeekController.php b/src/Controller/Reporting/ReportUsersWeekController.php index 4b20c7d9..f0d812b4 100644 --- a/src/Controller/Reporting/ReportUsersWeekController.php +++ b/src/Controller/Reporting/ReportUsersWeekController.php @@ -16,6 +16,7 @@ use App\Model\DailyStatistic; use App\Reporting\WeeklyUserList\WeeklyUserList; use App\Reporting\WeeklyUserList\WeeklyUserListForm; use App\Repository\Query\UserQuery; +use App\Repository\Query\VisibilityInterface; use App\Repository\UserRepository; use App\Timesheet\TimesheetStatisticService; use PhpOffice\PhpSpreadsheet\Reader\Html; @@ -68,6 +69,7 @@ final class ReportUsersWeekController extends AbstractController $form->submit($request->query->all(), false); $query = new UserQuery(); + $query->setVisibility(VisibilityInterface::SHOW_BOTH); $query->setSystemAccount(false); $query->setCurrentUser($currentUser); diff --git a/src/Controller/Reporting/ReportUsersYearController.php b/src/Controller/Reporting/ReportUsersYearController.php index 88e308a2..32bb6e86 100644 --- a/src/Controller/Reporting/ReportUsersYearController.php +++ b/src/Controller/Reporting/ReportUsersYearController.php @@ -17,6 +17,7 @@ use App\Model\MonthlyStatistic; use App\Reporting\YearlyUserList\YearlyUserList; use App\Reporting\YearlyUserList\YearlyUserListForm; use App\Repository\Query\UserQuery; +use App\Repository\Query\VisibilityInterface; use App\Repository\UserRepository; use App\Timesheet\TimesheetStatisticService; use PhpOffice\PhpSpreadsheet\Reader\Html; @@ -75,6 +76,7 @@ final class ReportUsersYearController extends AbstractController $form->submit($request->query->all(), false); $query = new UserQuery(); + $query->setVisibility(VisibilityInterface::SHOW_BOTH); $query->setSystemAccount(false); $query->setCurrentUser($currentUser); diff --git a/symfony.lock b/symfony.lock index 6aebb4f6..4cc98547 100644 --- a/symfony.lock +++ b/symfony.lock @@ -156,9 +156,6 @@ "kevinpapst/tabler-bundle": { "version": "dev-initial" }, - "laminas/laminas-escaper": { - "version": "2.7.0" - }, "league/csv": { "version": "9.4.1" }, diff --git a/templates/reporting/user_list_period_data.html.twig b/templates/reporting/user_list_period_data.html.twig index a095e79b..15f6b82b 100644 --- a/templates/reporting/user_list_period_data.html.twig +++ b/templates/reporting/user_list_period_data.html.twig @@ -38,6 +38,25 @@ {% set usersTotalDuration = 0 %} {% set usersTotalInternalRate = 0 %} {% set usersTotalRate = 0 %} + {% for period in attribute(userPeriod, period_attribute) %} + {% if period.totalDuration > 0 %} + {% set usersTotalDuration = usersTotalDuration + period.totalDuration %} + {% set absoluteDuration = absoluteDuration + period.totalDuration %} + {% endif %} + {% if period.totalInternalRate > 0 %} + {% set usersTotalInternalRate = usersTotalInternalRate + period.totalInternalRate %} + {% set absoluteInternalRate = absoluteInternalRate + period.totalInternalRate %} + {% endif %} + {% if period.totalRate > 0 %} + {% set usersTotalRate = usersTotalRate + period.totalRate %} + {% set absoluteRate = absoluteRate + period.totalRate %} + {% endif %} + {% set reportDateKey = period.date|report_date %} + {% set totalsDuration = totalsDuration|merge({(reportDateKey): (totalsDuration[reportDateKey] + period.totalDuration)}) %} + {% set totalsInternalRate = totalsInternalRate|merge({(reportDateKey): (totalsInternalRate[reportDateKey] + period.totalInternalRate)}) %} + {% set totalsRate = totalsRate|merge({(reportDateKey): (totalsRate[reportDateKey] + period.totalRate)}) %} + {% endfor %} + {% if userPeriod.user.enabled or usersTotalDuration > 0 %} {% if with_avatar %} @@ -51,24 +70,6 @@ {% if showAccountNumber %} {{ userPeriod.user.accountNumber }} {% endif %} - {% for period in attribute(userPeriod, period_attribute) %} - {% if period.totalDuration > 0 %} - {% set usersTotalDuration = usersTotalDuration + period.totalDuration %} - {% set absoluteDuration = absoluteDuration + period.totalDuration %} - {% endif %} - {% if period.totalInternalRate > 0 %} - {% set usersTotalInternalRate = usersTotalInternalRate + period.totalInternalRate %} - {% set absoluteInternalRate = absoluteInternalRate + period.totalInternalRate %} - {% endif %} - {% if period.totalRate > 0 %} - {% set usersTotalRate = usersTotalRate + period.totalRate %} - {% set absoluteRate = absoluteRate + period.totalRate %} - {% endif %} - {% set reportDateKey = period.date|report_date %} - {% set totalsDuration = totalsDuration|merge({(reportDateKey): (totalsDuration[reportDateKey] + period.totalDuration)}) %} - {% set totalsInternalRate = totalsInternalRate|merge({(reportDateKey): (totalsInternalRate[reportDateKey] + period.totalInternalRate)}) %} - {% set totalsRate = totalsRate|merge({(reportDateKey): (totalsRate[reportDateKey] + period.totalRate)}) %} - {% endfor %} {% if dataType == 'rate' %} {% block total_rate_user %}{% endblock %} @@ -92,6 +93,7 @@ {% endfor %} + {% endif %} {% endfor %} diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index b40d6c9e..9adf2089 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -1689,6 +1689,10 @@ days Tage + + unpaid_vacation + Unbezahlter Urlaub + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index aed32124..93a0aff0 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -1689,6 +1689,10 @@ days Days + + unpaid_vacation + Unpaid holidays + diff --git a/translations/validators.de.xlf b/translations/validators.de.xlf index 1a8c845b..fb66883c 100644 --- a/translations/validators.de.xlf +++ b/translations/validators.de.xlf @@ -148,7 +148,7 @@ You can book a maximum of {{ value }} days at once. - Sie können maximal {{ value }} Tage auf einmal buchen. + Sie können maximal {{ value }} Tage auf einmal buchen, aktuell sind {{ selected }} ausgewählt. The period of absence must not extend beyond the turn of the year. diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index 4b4331d3..d386e900 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -148,7 +148,7 @@ You can book a maximum of {{ value }} days at once. - You can book a maximum of {{ value }} days at once. + You can book a maximum of {{ value }} days at once, you currently selected {{ selected }}. The period of absence must not extend beyond the turn of the year.