From 82a3b99a3171d3604cef6abf2bc4c7adae41e2dd Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Thu, 5 Dec 2024 10:42:07 +0100 Subject: [PATCH] Release 2.26 (#5189) * bring back deprecated methods * bump packages * fix SAML redirect * config flag for break times * use class constant instead of string in attributes * throw if all tags were not found - fixes #4792 --- composer.lock | 463 +++++++++--------- phpstan.neon | 15 - src/API/TimesheetController.php | 8 +- src/Command/RegenerateLocalesCommand.php | 7 +- src/Constants.php | 4 +- src/Controller/Auth/SamlController.php | 16 +- src/Controller/DoctorController.php | 1 - src/DependencyInjection/Configuration.php | 3 + src/Entity/AccessToken.php | 3 +- src/Entity/Activity.php | 3 +- src/Entity/ActivityRate.php | 3 +- src/Entity/Bookmark.php | 3 +- src/Entity/Configuration.php | 3 +- src/Entity/Customer.php | 3 +- src/Entity/CustomerRate.php | 3 +- src/Entity/Invoice.php | 6 +- src/Entity/InvoiceTemplate.php | 3 +- src/Entity/Project.php | 3 +- src/Entity/ProjectRate.php | 3 +- src/Entity/Role.php | 3 +- src/Entity/RolePermission.php | 3 +- src/Entity/Tag.php | 3 +- src/Entity/Timesheet.php | 3 +- src/Entity/User.php | 3 +- src/Repository/WorkingTimeRepository.php | 29 ++ src/Saml/SamlAuthenticator.php | 6 +- .../SamlAuthenticationSuccessHandler.php | 13 +- src/Security/TwoFactorCondition.php | 2 +- src/Utils/DataTable.php | 3 +- src/WorkingTime/WorkingTimeService.php | 20 + tests/API/APIControllerBaseTest.php | 8 + tests/API/TimesheetControllerTest.php | 15 +- tests/Controller/Auth/SamlControllerTest.php | 30 +- .../DependencyInjection/ConfigurationTest.php | 1 + tests/Mocks/SecurityFactory.php | 31 ++ .../SamlAuthenticationSuccessHandlerTest.php | 42 +- tests/phpstan.neon | 50 -- translations/messages.de.xlf | 8 + translations/messages.en.xlf | 8 + 39 files changed, 437 insertions(+), 397 deletions(-) create mode 100644 tests/Mocks/SecurityFactory.php diff --git a/composer.lock b/composer.lock index 7d99a9df..bd8e99a3 100644 --- a/composer.lock +++ b/composer.lock @@ -1836,16 +1836,16 @@ }, { "name": "friendsofsymfony/rest-bundle", - "version": "3.7.1", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/FriendsOfSymfony/FOSRestBundle.git", - "reference": "db7d9a17da2bcae1bb8e2d7ff320ef3915903373" + "reference": "d24736896518bae817bf0de8a6b682cb6535044b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/db7d9a17da2bcae1bb8e2d7ff320ef3915903373", - "reference": "db7d9a17da2bcae1bb8e2d7ff320ef3915903373", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/d24736896518bae817bf0de8a6b682cb6535044b", + "reference": "d24736896518bae817bf0de8a6b682cb6535044b", "shasum": "" }, "require": { @@ -1936,9 +1936,9 @@ ], "support": { "issues": "https://github.com/FriendsOfSymfony/FOSRestBundle/issues", - "source": "https://github.com/FriendsOfSymfony/FOSRestBundle/tree/3.7.1" + "source": "https://github.com/FriendsOfSymfony/FOSRestBundle/tree/3.8.0" }, - "time": "2024-04-12T22:57:10+00:00" + "time": "2024-11-04T08:41:36+00:00" }, { "name": "gedmo/doctrine-extensions", @@ -3752,16 +3752,16 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "2.3.2", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "08d4e08cf0c7e6182750cef7958b860b8c7f10ad" + "reference": "91a4b42e41976a0b2f839720c3e20a12a84f6852" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/08d4e08cf0c7e6182750cef7958b860b8c7f10ad", - "reference": "08d4e08cf0c7e6182750cef7958b860b8c7f10ad", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/91a4b42e41976a0b2f839720c3e20a12a84f6852", + "reference": "91a4b42e41976a0b2f839720c3e20a12a84f6852", "shasum": "" }, "require": { @@ -3850,9 +3850,9 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.3.2" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.3.3" }, - "time": "2024-11-10T09:35:47+00:00" + "time": "2024-11-22T06:11:37+00:00" }, { "name": "phpoffice/phpword", @@ -4906,16 +4906,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.14", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "36fb8aa88833708e9f29014b6f15fac051a8b613" + "reference": "70d60e9a3603108563010f8592dff15a6f15dfae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/36fb8aa88833708e9f29014b6f15fac051a8b613", - "reference": "36fb8aa88833708e9f29014b6f15fac051a8b613", + "url": "https://api.github.com/repos/symfony/cache/zipball/70d60e9a3603108563010f8592dff15a6f15dfae", + "reference": "70d60e9a3603108563010f8592dff15a6f15dfae", "shasum": "" }, "require": { @@ -4982,7 +4982,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.14" + "source": "https://github.com/symfony/cache/tree/v6.4.16" }, "funding": [ { @@ -4998,20 +4998,20 @@ "type": "tidelift" } ], - "time": "2024-11-05T15:34:40+00:00" + "time": "2024-11-20T10:10:54+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197" + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/df6a1a44c890faded49a5fca33c2d5c5fd3c2197", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", "shasum": "" }, "require": { @@ -5058,7 +5058,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.5.1" }, "funding": [ { @@ -5074,7 +5074,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/clock", @@ -5386,16 +5386,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.15", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "70ab1f65a4516ef741e519ea938e6aa465e6aa36" + "reference": "7a379d8871f6a36f01559c14e11141cc02eb8dc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/70ab1f65a4516ef741e519ea938e6aa465e6aa36", - "reference": "70ab1f65a4516ef741e519ea938e6aa465e6aa36", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/7a379d8871f6a36f01559c14e11141cc02eb8dc8", + "reference": "7a379d8871f6a36f01559c14e11141cc02eb8dc8", "shasum": "" }, "require": { @@ -5447,7 +5447,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.15" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.16" }, "funding": [ { @@ -5463,20 +5463,20 @@ "type": "tidelift" } ], - "time": "2024-11-09T06:56:25+00:00" + "time": "2024-11-25T14:52:46+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -5514,7 +5514,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -5530,20 +5530,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "402d5831a73217ea76ab7e032cc05045cd3fa678" + "reference": "429a4b6786901afcc085ee16dc3f2be621f33488" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/402d5831a73217ea76ab7e032cc05045cd3fa678", - "reference": "402d5831a73217ea76ab7e032cc05045cd3fa678", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/429a4b6786901afcc085ee16dc3f2be621f33488", + "reference": "429a4b6786901afcc085ee16dc3f2be621f33488", "shasum": "" }, "require": { @@ -5573,7 +5573,7 @@ }, "require-dev": { "doctrine/collections": "^1.0|^2.0", - "doctrine/data-fixtures": "^1.1", + "doctrine/data-fixtures": "^1.1|^2", "doctrine/dbal": "^2.13.1|^3|^4", "doctrine/orm": "^2.15|^3", "psr/log": "^1|^2|^3", @@ -5622,7 +5622,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.13" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.16" }, "funding": [ { @@ -5638,20 +5638,20 @@ "type": "tidelift" } ], - "time": "2024-10-18T09:23:39+00:00" + "time": "2024-11-25T12:00:20+00:00" }, { "name": "symfony/dotenv", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "436ae2dd89360fea8c7d5ff3f48ecf523c80bfb4" + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/436ae2dd89360fea8c7d5ff3f48ecf523c80bfb4", - "reference": "436ae2dd89360fea8c7d5ff3f48ecf523c80bfb4", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/1ac5e7e7e862d4d574258daf08bd569ba926e4a5", + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5", "shasum": "" }, "require": { @@ -5696,7 +5696,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.13" + "source": "https://github.com/symfony/dotenv/tree/v6.4.16" }, "funding": [ { @@ -5712,7 +5712,7 @@ "type": "tidelift" } ], - "time": "2024-09-28T07:43:51+00:00" + "time": "2024-11-27T11:08:19+00:00" }, { "name": "symfony/error-handler", @@ -5871,16 +5871,16 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -5927,7 +5927,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -5943,7 +5943,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/expression-language", @@ -6455,23 +6455,23 @@ }, { "name": "symfony/http-client", - "version": "v6.4.15", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "cb4073c905cd12b8496d24ac428a9228c1750670" + "reference": "60a113666fa67e598abace38e5f46a0954d8833d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/cb4073c905cd12b8496d24ac428a9228c1750670", - "reference": "cb4073c905cd12b8496d24ac428a9228c1750670", + "url": "https://api.github.com/repos/symfony/http-client/zipball/60a113666fa67e598abace38e5f46a0954d8833d", + "reference": "60a113666fa67e598abace38e5f46a0954d8833d", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", + "symfony/http-client-contracts": "~3.4.3|^3.5.1", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -6528,7 +6528,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.15" + "source": "https://github.com/symfony/http-client/tree/v6.4.16" }, "funding": [ { @@ -6544,20 +6544,20 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:40:18+00:00" + "time": "2024-11-27T11:52:33+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c2f3ad828596624ca39ea40f83617ef51ca8bbf9", + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9", "shasum": "" }, "require": { @@ -6606,7 +6606,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.1" }, "funding": [ { @@ -6622,20 +6622,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-11-25T12:02:18+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.15", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "9b3165eb2f04aeaa1a5a2cfef73e63fe3b22dff6" + "reference": "431771b7a6f662f1575b3cfc8fd7617aa9864d57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9b3165eb2f04aeaa1a5a2cfef73e63fe3b22dff6", - "reference": "9b3165eb2f04aeaa1a5a2cfef73e63fe3b22dff6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/431771b7a6f662f1575b3cfc8fd7617aa9864d57", + "reference": "431771b7a6f662f1575b3cfc8fd7617aa9864d57", "shasum": "" }, "require": { @@ -6683,7 +6683,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.15" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.16" }, "funding": [ { @@ -6699,20 +6699,20 @@ "type": "tidelift" } ], - "time": "2024-11-08T16:09:24+00:00" + "time": "2024-11-13T18:58:10+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.15", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "b002a5b3947653c5aee3adac2a024ea615fd3ff5" + "reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b002a5b3947653c5aee3adac2a024ea615fd3ff5", - "reference": "b002a5b3947653c5aee3adac2a024ea615fd3ff5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", + "reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", "shasum": "" }, "require": { @@ -6797,7 +6797,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.15" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.16" }, "funding": [ { @@ -6813,7 +6813,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:57:37+00:00" + "time": "2024-11-27T12:49:36+00:00" }, { "name": "symfony/intl", @@ -7225,16 +7225,16 @@ }, { "name": "symfony/options-resolver", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "0a62a9f2504a8dd27083f89d21894ceb01cc59db" + "reference": "368128ad168f20e22c32159b9f761e456cec0c78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0a62a9f2504a8dd27083f89d21894ceb01cc59db", - "reference": "0a62a9f2504a8dd27083f89d21894ceb01cc59db", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/368128ad168f20e22c32159b9f761e456cec0c78", + "reference": "368128ad168f20e22c32159b9f761e456cec0c78", "shasum": "" }, "require": { @@ -7272,7 +7272,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.13" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.16" }, "funding": [ { @@ -7288,7 +7288,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2024-11-20T10:57:02+00:00" }, { "name": "symfony/password-hasher", @@ -7578,16 +7578,16 @@ }, { "name": "symfony/property-info", - "version": "v6.4.15", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "9d7b576bb643c72bf3b60eb8e89c98725d00afd0" + "reference": "e4782ec1c2b6896e820896357f6a3d02249e63eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/9d7b576bb643c72bf3b60eb8e89c98725d00afd0", - "reference": "9d7b576bb643c72bf3b60eb8e89c98725d00afd0", + "url": "https://api.github.com/repos/symfony/property-info/zipball/e4782ec1c2b6896e820896357f6a3d02249e63eb", + "reference": "e4782ec1c2b6896e820896357f6a3d02249e63eb", "shasum": "" }, "require": { @@ -7595,17 +7595,18 @@ "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { + "doctrine/annotations": "<1.12", "phpdocumentor/reflection-docblock": "<5.2", "phpdocumentor/type-resolver": "<1.5.1", - "symfony/dependency-injection": "<5.4", - "symfony/serializer": "<6.4" + "symfony/dependency-injection": "<5.4|>=6.0,<6.4" }, "require-dev": { + "doctrine/annotations": "^1.12|^2", "phpdocumentor/reflection-docblock": "^5.2", "phpstan/phpdoc-parser": "^1.0|^2.0", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/serializer": "^5.4|^6.4|^7.0" }, "type": "library", "autoload": { @@ -7641,7 +7642,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.4.15" + "source": "https://github.com/symfony/property-info/tree/v6.4.16" }, "funding": [ { @@ -7657,7 +7658,7 @@ "type": "tidelift" } ], - "time": "2024-11-07T16:39:46+00:00" + "time": "2024-11-27T10:18:02+00:00" }, { "name": "symfony/rate-limiter", @@ -7732,16 +7733,16 @@ }, { "name": "symfony/routing", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "640a74250d13f9c30d5ca045b6aaaabcc8215278" + "reference": "91e02e606b4b705c2f4fb42f7e7708b7923a3220" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/640a74250d13f9c30d5ca045b6aaaabcc8215278", - "reference": "640a74250d13f9c30d5ca045b6aaaabcc8215278", + "url": "https://api.github.com/repos/symfony/routing/zipball/91e02e606b4b705c2f4fb42f7e7708b7923a3220", + "reference": "91e02e606b4b705c2f4fb42f7e7708b7923a3220", "shasum": "" }, "require": { @@ -7795,7 +7796,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.13" + "source": "https://github.com/symfony/routing/tree/v6.4.16" }, "funding": [ { @@ -7811,7 +7812,7 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:30:56+00:00" + "time": "2024-11-13T15:31:34+00:00" }, { "name": "symfony/runtime", @@ -8006,16 +8007,16 @@ }, { "name": "symfony/security-core", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "bbd1a919aec8696a95bf8749d5577fbe74de973c" + "reference": "19cdb7de86e556202ab16e0cffd1a97348231bc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/bbd1a919aec8696a95bf8749d5577fbe74de973c", - "reference": "bbd1a919aec8696a95bf8749d5577fbe74de973c", + "url": "https://api.github.com/repos/symfony/security-core/zipball/19cdb7de86e556202ab16e0cffd1a97348231bc0", + "reference": "19cdb7de86e556202ab16e0cffd1a97348231bc0", "shasum": "" }, "require": { @@ -8072,7 +8073,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.13" + "source": "https://github.com/symfony/security-core/tree/v6.4.16" }, "funding": [ { @@ -8088,7 +8089,7 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:07:50+00:00" + "time": "2024-11-27T09:48:51+00:00" }, { "name": "symfony/security-csrf", @@ -8346,16 +8347,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -8409,7 +8410,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -8425,7 +8426,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/stopwatch", @@ -8672,16 +8673,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", "shasum": "" }, "require": { @@ -8730,7 +8731,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" }, "funding": [ { @@ -8746,20 +8747,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "ec3511eef0576f378b2758da9e1c157086babd59" + "reference": "32ec012ed4f6426441a66014471bdb26674744be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/ec3511eef0576f378b2758da9e1c157086babd59", - "reference": "ec3511eef0576f378b2758da9e1c157086babd59", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/32ec012ed4f6426441a66014471bdb26674744be", + "reference": "32ec012ed4f6426441a66014471bdb26674744be", "shasum": "" }, "require": { @@ -8839,7 +8840,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.13" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.16" }, "funding": [ { @@ -8855,7 +8856,7 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:07:50+00:00" + "time": "2024-11-25T11:59:11+00:00" }, { "name": "symfony/twig-bundle", @@ -8943,16 +8944,16 @@ }, { "name": "symfony/validator", - "version": "v6.4.15", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "7541055cdaf54ff95f0735bf703d313374e8b20b" + "reference": "9b0d1988b56511706bc91d96ead39acd77aaf34d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/7541055cdaf54ff95f0735bf703d313374e8b20b", - "reference": "7541055cdaf54ff95f0735bf703d313374e8b20b", + "url": "https://api.github.com/repos/symfony/validator/zipball/9b0d1988b56511706bc91d96ead39acd77aaf34d", + "reference": "9b0d1988b56511706bc91d96ead39acd77aaf34d", "shasum": "" }, "require": { @@ -9020,7 +9021,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.15" + "source": "https://github.com/symfony/validator/tree/v6.4.16" }, "funding": [ { @@ -9036,7 +9037,7 @@ "type": "tidelift" } ], - "time": "2024-11-08T15:28:48+00:00" + "time": "2024-11-27T09:48:51+00:00" }, { "name": "symfony/var-dumper", @@ -9232,8 +9233,8 @@ "type": "symfony-bundle", "extra": { "thanks": { - "name": "symfony/webpack-encore", - "url": "https://github.com/symfony/webpack-encore" + "url": "https://github.com/symfony/webpack-encore", + "name": "symfony/webpack-encore" } }, "autoload": { @@ -9399,7 +9400,7 @@ }, { "name": "twig/cssinliner-extra", - "version": "v3.15.0", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/cssinliner-extra.git", @@ -9452,7 +9453,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/cssinliner-extra/tree/v3.15.0" + "source": "https://github.com/twigphp/cssinliner-extra/tree/v3.16.0" }, "funding": [ { @@ -9468,7 +9469,7 @@ }, { "name": "twig/extra-bundle", - "version": "v3.15.0", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/twig-extra-bundle.git", @@ -9526,7 +9527,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.15.0" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.16.0" }, "funding": [ { @@ -9542,7 +9543,7 @@ }, { "name": "twig/inky-extra", - "version": "v3.15.0", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/inky-extra.git", @@ -9596,7 +9597,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/inky-extra/tree/v3.15.0" + "source": "https://github.com/twigphp/inky-extra/tree/v3.16.0" }, "funding": [ { @@ -9612,16 +9613,16 @@ }, { "name": "twig/intl-extra", - "version": "v3.15.0", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/intl-extra.git", - "reference": "92a127a58857597acc6eca2e34d5ef90057dcc59" + "reference": "4eeab2a3f8d04d1838be7251ab2d183f817aea7b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/92a127a58857597acc6eca2e34d5ef90057dcc59", - "reference": "92a127a58857597acc6eca2e34d5ef90057dcc59", + "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/4eeab2a3f8d04d1838be7251ab2d183f817aea7b", + "reference": "4eeab2a3f8d04d1838be7251ab2d183f817aea7b", "shasum": "" }, "require": { @@ -9660,7 +9661,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/intl-extra/tree/v3.15.0" + "source": "https://github.com/twigphp/intl-extra/tree/v3.16.0" }, "funding": [ { @@ -9672,20 +9673,20 @@ "type": "tidelift" } ], - "time": "2024-09-16T10:21:35+00:00" + "time": "2024-11-20T13:19:52+00:00" }, { "name": "twig/string-extra", - "version": "v3.15.0", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/string-extra.git", - "reference": "b098bd4910aba185afb70e40b8e23071fce8c656" + "reference": "3f90208078a7d55ad4a561301ee3929d3e3840e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/string-extra/zipball/b098bd4910aba185afb70e40b8e23071fce8c656", - "reference": "b098bd4910aba185afb70e40b8e23071fce8c656", + "url": "https://api.github.com/repos/twigphp/string-extra/zipball/3f90208078a7d55ad4a561301ee3929d3e3840e0", + "reference": "3f90208078a7d55ad4a561301ee3929d3e3840e0", "shasum": "" }, "require": { @@ -9727,7 +9728,7 @@ "unicode" ], "support": { - "source": "https://github.com/twigphp/string-extra/tree/v3.15.0" + "source": "https://github.com/twigphp/string-extra/tree/v3.16.0" }, "funding": [ { @@ -9739,20 +9740,20 @@ "type": "tidelift" } ], - "time": "2024-11-03T14:08:48+00:00" + "time": "2024-11-20T13:10:15+00:00" }, { "name": "twig/twig", - "version": "v3.15.0", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "2d5b3964cc21d0188633d7ddce732dc8e874db02" + "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/2d5b3964cc21d0188633d7ddce732dc8e874db02", - "reference": "2d5b3964cc21d0188633d7ddce732dc8e874db02", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/475ad2dc97d65d8631393e721e7e44fb544f0561", + "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561", "shasum": "" }, "require": { @@ -9763,6 +9764,7 @@ "symfony/polyfill-php81": "^1.29" }, "require-dev": { + "phpstan/phpstan": "^2.0", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, @@ -9806,7 +9808,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.15.0" + "source": "https://github.com/twigphp/Twig/tree/v3.16.0" }, "funding": [ { @@ -9818,7 +9820,7 @@ "type": "tidelift" } ], - "time": "2024-11-17T15:59:19+00:00" + "time": "2024-11-29T08:27:05+00:00" }, { "name": "webmozart/assert", @@ -10338,23 +10340,22 @@ }, { "name": "doctrine/data-fixtures", - "version": "1.8.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "d2ff5046b263868baf6e9b06cf4918f60096c0d0" + "reference": "eddc4c37beff550a9172a449ab285f4511573dc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/d2ff5046b263868baf6e9b06cf4918f60096c0d0", - "reference": "d2ff5046b263868baf6e9b06cf4918f60096c0d0", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/eddc4c37beff550a9172a449ab285f4511573dc8", + "reference": "eddc4c37beff550a9172a449ab285f4511573dc8", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1.0", - "doctrine/persistence": "^2.0 || ^3.0", - "php": "^7.4 || ^8.0", - "symfony/polyfill-php80": "^1" + "doctrine/persistence": "^3.1", + "php": "^8.1", + "psr/log": "^1.1 || ^2 || ^3" }, "conflict": { "doctrine/dbal": "<3.5 || >=5", @@ -10362,7 +10363,6 @@ "doctrine/phpcr-odm": "<1.3.0" }, "require-dev": { - "doctrine/annotations": "^1.12 || ^2", "doctrine/coding-standard": "^12", "doctrine/dbal": "^3.5 || ^4", "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", @@ -10370,10 +10370,9 @@ "ext-sqlite3": "*", "fig/log-test": "^1", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6.13 || ^10.4.2", - "psr/log": "^1.1 || ^2 || ^3", - "symfony/cache": "^5.4 || ^6.3 || ^7", - "symfony/var-exporter": "^5.4 || ^6.3 || ^7" + "phpunit/phpunit": "^10.5.3", + "symfony/cache": "^6.4 || ^7", + "symfony/var-exporter": "^6.4 || ^7" }, "suggest": { "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", @@ -10404,7 +10403,7 @@ ], "support": { "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/1.8.0" + "source": "https://github.com/doctrine/data-fixtures/tree/2.0.0" }, "funding": [ { @@ -10420,24 +10419,24 @@ "type": "tidelift" } ], - "time": "2024-11-04T22:36:12+00:00" + "time": "2024-11-06T07:58:24+00:00" }, { "name": "doctrine/doctrine-fixtures-bundle", - "version": "3.6.2", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", - "reference": "f44a224e27573b79140197a44e68484c45fb24da" + "reference": "3004c9b3ac3d2a8f484597416ae1882040b3ef3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/f44a224e27573b79140197a44e68484c45fb24da", - "reference": "f44a224e27573b79140197a44e68484c45fb24da", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/3004c9b3ac3d2a8f484597416ae1882040b3ef3b", + "reference": "3004c9b3ac3d2a8f484597416ae1882040b3ef3b", "shasum": "" }, "require": { - "doctrine/data-fixtures": "^1.3", + "doctrine/data-fixtures": "^1.5|^2.0", "doctrine/doctrine-bundle": "^2.2", "doctrine/orm": "^2.14.0 || ^3.0", "doctrine/persistence": "^2.4|^3.0", @@ -10446,7 +10445,7 @@ "symfony/console": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/deprecation-contracts": "^2.1|^3", - "symfony/doctrine-bridge": "^5.4|^6.0|^7.0", + "symfony/doctrine-bridge": "^5.4.48|^6.4.16|^7.1.9", "symfony/http-kernel": "^5.4|^6.0|^7.0" }, "conflict": { @@ -10491,7 +10490,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineFixturesBundle/issues", - "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/3.6.2" + "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/3.7.0" }, "funding": [ { @@ -10507,7 +10506,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T07:41:29+00:00" + "time": "2024-11-28T07:19:21+00:00" }, { "name": "evenement/evenement", @@ -10682,16 +10681,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.64.0", + "version": "v3.65.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "58dd9c931c785a79739310aef5178928305ffa67" + "reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/58dd9c931c785a79739310aef5178928305ffa67", - "reference": "58dd9c931c785a79739310aef5178928305ffa67", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/79d4f3e77b250a7d8043d76c6af8f0695e8a469f", + "reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f", "shasum": "" }, "require": { @@ -10701,7 +10700,7 @@ "ext-filter": "*", "ext-json": "*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.0", + "fidry/cpu-core-counter": "^1.2", "php": "^7.4 || ^8.0", "react/child-process": "^0.6.5", "react/event-loop": "^1.0", @@ -10721,18 +10720,18 @@ "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "facile-it/paraunit": "^1.3 || ^2.3", - "infection/infection": "^0.29.5", - "justinrainbow/json-schema": "^5.2", + "facile-it/paraunit": "^1.3.1 || ^2.4", + "infection/infection": "^0.29.8", + "justinrainbow/json-schema": "^5.3 || ^6.0", "keradus/cli-executor": "^2.1", - "mikey179/vfsstream": "^1.6.11", + "mikey179/vfsstream": "^1.6.12", "php-coveralls/php-coveralls": "^2.7", "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5", - "phpunit/phpunit": "^9.6.19 || ^10.5.21 || ^11.2", - "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + "phpunit/phpunit": "^9.6.21 || ^10.5.38 || ^11.4.3", + "symfony/var-dumper": "^5.4.47 || ^6.4.15 || ^7.1.8", + "symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.1.6" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -10773,7 +10772,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.64.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.65.0" }, "funding": [ { @@ -10781,7 +10780,7 @@ "type": "github" } ], - "time": "2024-08-30T23:09:38+00:00" + "time": "2024-11-25T00:39:24+00:00" }, { "name": "masterminds/html5", @@ -11028,16 +11027,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "6c98c7600fc717b2c78c11ef60040d5b1e359c82" + "reference": "46b4d3529b12178112d9008337beda0cc2a1a6b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6c98c7600fc717b2c78c11ef60040d5b1e359c82", - "reference": "6c98c7600fc717b2c78c11ef60040d5b1e359c82", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46b4d3529b12178112d9008337beda0cc2a1a6b4", + "reference": "46b4d3529b12178112d9008337beda0cc2a1a6b4", "shasum": "" }, "require": { @@ -11082,20 +11081,20 @@ "type": "github" } ], - "time": "2024-11-17T14:17:00+00:00" + "time": "2024-11-28T22:19:37+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "81833b5787e2e8f451b31218875e29e4ed600ab2" + "reference": "1cc1259cb91ee4cfbb5c39bca9f635f067c910b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/81833b5787e2e8f451b31218875e29e4ed600ab2", - "reference": "81833b5787e2e8f451b31218875e29e4ed600ab2", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/1cc1259cb91ee4cfbb5c39bca9f635f067c910b4", + "reference": "1cc1259cb91ee4cfbb5c39bca9f635f067c910b4", "shasum": "" }, "require": { @@ -11127,27 +11126,27 @@ "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.0" + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.1" }, - "time": "2024-10-26T16:04:11+00:00" + "time": "2024-11-28T21:56:36+00:00" }, { "name": "phpstan/phpstan-doctrine", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-doctrine.git", - "reference": "90c42756b2d7c3660b423d328622d4dfa2194487" + "reference": "bdb6a835c5aa9725979694ae9b70591e180f4853" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/90c42756b2d7c3660b423d328622d4dfa2194487", - "reference": "90c42756b2d7c3660b423d328622d4dfa2194487", + "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/bdb6a835c5aa9725979694ae9b70591e180f4853", + "reference": "bdb6a835c5aa9725979694ae9b70591e180f4853", "shasum": "" }, "require": { "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.0" + "phpstan/phpstan": "^2.0.3" }, "conflict": { "doctrine/collections": "<1.0", @@ -11198,9 +11197,9 @@ "description": "Doctrine extensions for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-doctrine/issues", - "source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.0" + "source": "https://github.com/phpstan/phpstan-doctrine/tree/2.0.1" }, - "time": "2024-11-09T17:34:32+00:00" + "time": "2024-12-02T16:48:00+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -13430,16 +13429,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "ae074dffb018c37a57071990d16e6152728dd972" + "reference": "4304e6ad5c894a9c72831ad459f627bfd35d766d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/ae074dffb018c37a57071990d16e6152728dd972", - "reference": "ae074dffb018c37a57071990d16e6152728dd972", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/4304e6ad5c894a9c72831ad459f627bfd35d766d", + "reference": "4304e6ad5c894a9c72831ad459f627bfd35d766d", "shasum": "" }, "require": { @@ -13477,7 +13476,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.13" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.16" }, "funding": [ { @@ -13493,20 +13492,20 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:07:50+00:00" + "time": "2024-11-13T15:06:22+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v6.4.13", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "e6377bea5b114f70de6332fe935e160da5014ce8" + "reference": "cebafe2f1ad2d1e745c1015b7c2519592341e4e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/e6377bea5b114f70de6332fe935e160da5014ce8", - "reference": "e6377bea5b114f70de6332fe935e160da5014ce8", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/cebafe2f1ad2d1e745c1015b7c2519592341e4e6", + "reference": "cebafe2f1ad2d1e745c1015b7c2519592341e4e6", "shasum": "" }, "require": { @@ -13526,8 +13525,8 @@ "type": "symfony-bridge", "extra": { "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" + "url": "https://github.com/sebastianbergmann/phpunit", + "name": "phpunit/phpunit" } }, "autoload": { @@ -13559,7 +13558,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.13" + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.16" }, "funding": [ { @@ -13575,20 +13574,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2024-11-13T15:06:22+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.14", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "bfbade623f1cc7f1e243ce5488af33861a8f5be7" + "reference": "2d58fd04ac0d3c6279cadd0105959083ef1d7f5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/bfbade623f1cc7f1e243ce5488af33861a8f5be7", - "reference": "bfbade623f1cc7f1e243ce5488af33861a8f5be7", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/2d58fd04ac0d3c6279cadd0105959083ef1d7f5b", + "reference": "2d58fd04ac0d3c6279cadd0105959083ef1d7f5b", "shasum": "" }, "require": { @@ -13641,7 +13640,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.14" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.16" }, "funding": [ { @@ -13657,7 +13656,7 @@ "type": "tidelift" } ], - "time": "2024-11-04T11:33:53+00:00" + "time": "2024-11-19T10:11:25+00:00" }, { "name": "theseer/tokenizer", diff --git a/phpstan.neon b/phpstan.neon index 9d356e81..674b240d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -697,11 +697,6 @@ parameters: count: 1 path: src/Controller/ActivityController.php - - - message: "#^Parameter \\#1 \\$returnTo of method OneLogin\\\\Saml2\\\\Auth\\:\\:login\\(\\) expects string\\|null, mixed given\\.$#" - count: 1 - path: src/Controller/Auth/SamlController.php - - message: "#^Cannot access offset 'user' on mixed\\.$#" count: 1 @@ -3872,11 +3867,6 @@ parameters: count: 1 path: src/Repository/TimesheetRepository.php - - - message: "#^Method App\\\\Repository\\\\TimesheetRepository\\:\\:getRawData\\(\\) should return array but returns mixed\\.$#" - count: 1 - path: src/Repository/TimesheetRepository.php - - message: "#^Parameter \\#1 \\$amountThisMonth of method App\\\\Model\\\\TimesheetStatistic\\:\\:setAmountThisMonth\\(\\) expects float\\|int, mixed given\\.$#" count: 1 @@ -3972,11 +3962,6 @@ parameters: count: 1 path: src/Saml/Security/SamlAuthenticationFailureHandler.php - - - message: "#^Method App\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandler\\:\\:determineTargetUrl\\(\\) should return string but returns mixed\\.$#" - count: 1 - path: src/Saml/Security/SamlAuthenticationSuccessHandler.php - - message: "#^Property App\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandler\\:\\:\\$defaultOptions has no type specified\\.$#" count: 1 diff --git a/src/API/TimesheetController.php b/src/API/TimesheetController.php index 99625dd7..c2dc73a1 100644 --- a/src/API/TimesheetController.php +++ b/src/API/TimesheetController.php @@ -37,6 +37,7 @@ use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Validator\Constraints; @@ -181,8 +182,11 @@ final class TimesheetController extends BaseApiController /** @var array $tags */ $tags = $paramFetcher->get('tags'); if (\is_array($tags) && \count($tags) > 0) { - $tags = $this->tagRepository->findTagsByName($tags, true); - foreach ($tags as $tag) { + $tagsByName = $this->tagRepository->findTagsByName($tags, true); + if (\count($tagsByName) === 0) { + throw new BadRequestHttpException('Given tags were not found'); + } + foreach ($tagsByName as $tag) { $query->addTag($tag); } } diff --git a/src/Command/RegenerateLocalesCommand.php b/src/Command/RegenerateLocalesCommand.php index 8dd857de..aca0ad1d 100644 --- a/src/Command/RegenerateLocalesCommand.php +++ b/src/Command/RegenerateLocalesCommand.php @@ -26,7 +26,7 @@ use Symfony\Component\Intl\Locales; * * @codeCoverageIgnore */ -#[AsCommand(name: 'kimai:reset:locales')] +#[AsCommand(name: 'kimai:reset:locales', description: 'Regenerate the locale definition file')] final class RegenerateLocalesCommand extends Command { /** @@ -66,11 +66,6 @@ final class RegenerateLocalesCommand extends Command return $this->kernelEnvironment !== 'prod'; } - protected function configure(): void - { - $this->setDescription('Regenerate the locale definition file'); - } - protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); diff --git a/src/Constants.php b/src/Constants.php index aba0f193..ffaf3ec8 100644 --- a/src/Constants.php +++ b/src/Constants.php @@ -17,11 +17,11 @@ class Constants /** * The current release version */ - public const VERSION = '2.25.0'; + public const VERSION = '2.26.0'; /** * The current release: major * 10000 + minor * 100 + patch */ - public const VERSION_ID = 22500; + public const VERSION_ID = 22600; /** * The software name */ diff --git a/src/Controller/Auth/SamlController.php b/src/Controller/Auth/SamlController.php index e8c636f7..0eb90626 100644 --- a/src/Controller/Auth/SamlController.php +++ b/src/Controller/Auth/SamlController.php @@ -12,18 +12,24 @@ namespace App\Controller\Auth; use App\Configuration\SamlConfigurationInterface; use App\Saml\SamlAuthFactory; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Http\SecurityRequestAttributes; +use Symfony\Component\Security\Http\Util\TargetPathTrait; #[Route(path: '/saml')] final class SamlController extends AbstractController { + use TargetPathTrait; + public function __construct( private readonly SamlAuthFactory $authFactory, - private readonly SamlConfigurationInterface $samlConfiguration + private readonly SamlConfigurationInterface $samlConfiguration, + private readonly Security $security, ) { } @@ -54,8 +60,12 @@ final class SamlController extends AbstractController throw new \RuntimeException($error); } - // this does set headers and exit as $stay is not set to true - $redirectTarget = $session->get('_security.main.target_path'); + $firewallName = $this->security->getFirewallConfig($request)?->getName(); + if ($firewallName === null || $firewallName === '') { + throw new ServiceUnavailableHttpException(message: 'Unknown firewall.'); + } + + $redirectTarget = $this->getTargetPath($session, $firewallName); if ($redirectTarget === null || $redirectTarget === '') { $redirectTarget = $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL); } diff --git a/src/Controller/DoctorController.php b/src/Controller/DoctorController.php index 94f900df..788873f5 100644 --- a/src/Controller/DoctorController.php +++ b/src/Controller/DoctorController.php @@ -253,7 +253,6 @@ final class DoctorController extends AbstractController 'max_execution_time', 'date.timezone', 'allow_url_fopen', - 'allow_url_include', 'default_charset', 'default_mimetype', 'display_errors', diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index d80f8030..abe69497 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -331,6 +331,9 @@ final class Configuration implements ConfigurationInterface ->booleanNode('require_activity') ->defaultTrue() ->end() + ->booleanNode('break_time_active') + ->defaultFalse() + ->end() ->end() ->end() ->end() diff --git a/src/Entity/AccessToken.php b/src/Entity/AccessToken.php index 2eb01e98..b0a63420 100644 --- a/src/Entity/AccessToken.php +++ b/src/Entity/AccessToken.php @@ -9,12 +9,13 @@ namespace App\Entity; +use App\Repository\AccessTokenRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_access_token')] -#[ORM\Entity(repositoryClass: 'App\Repository\AccessTokenRepository')] +#[ORM\Entity(repositoryClass: AccessTokenRepository::class)] #[ORM\UniqueConstraint(columns: ['token'])] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity(fields: ['token'])] diff --git a/src/Entity/Activity.php b/src/Entity/Activity.php index dd7d73fb..0410069d 100644 --- a/src/Entity/Activity.php +++ b/src/Entity/Activity.php @@ -12,6 +12,7 @@ namespace App\Entity; use App\Doctrine\Behavior\CreatedAt; use App\Doctrine\Behavior\CreatedTrait; use App\Export\Annotation as Exporter; +use App\Repository\ActivityRepository; use App\Validator\Constraints as Constraints; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -24,7 +25,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Index(columns: ['visible', 'project_id'])] #[ORM\Index(columns: ['visible', 'project_id', 'name'])] #[ORM\Index(columns: ['visible', 'name'])] -#[ORM\Entity(repositoryClass: 'App\Repository\ActivityRepository')] +#[ORM\Entity(repositoryClass: ActivityRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[Serializer\ExclusionPolicy('all')] #[Serializer\VirtualProperty('ProjectName', exp: 'object.getProject() === null ? null : object.getProject().getName()', options: [new Serializer\SerializedName('parentTitle'), new Serializer\Type(name: 'string'), new Serializer\Groups(['Activity'])])] diff --git a/src/Entity/ActivityRate.php b/src/Entity/ActivityRate.php index 59156066..1399ed65 100644 --- a/src/Entity/ActivityRate.php +++ b/src/Entity/ActivityRate.php @@ -9,6 +9,7 @@ namespace App\Entity; +use App\Repository\ActivityRateRepository; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; @@ -16,7 +17,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_activities_rates')] #[ORM\UniqueConstraint(columns: ['user_id', 'activity_id'])] -#[ORM\Entity(repositoryClass: 'App\Repository\ActivityRateRepository')] +#[ORM\Entity(repositoryClass: ActivityRateRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity(['user', 'activity'], ignoreNull: false)] #[Serializer\ExclusionPolicy('all')] diff --git a/src/Entity/Bookmark.php b/src/Entity/Bookmark.php index 82d3236d..35d58cd3 100644 --- a/src/Entity/Bookmark.php +++ b/src/Entity/Bookmark.php @@ -9,13 +9,14 @@ namespace App\Entity; +use App\Repository\BookmarkRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_bookmarks')] #[ORM\UniqueConstraint(columns: ['user_id', 'name'])] -#[ORM\Entity(repositoryClass: 'App\Repository\BookmarkRepository')] +#[ORM\Entity(repositoryClass: BookmarkRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity(fields: ['user', 'name'])] class Bookmark diff --git a/src/Entity/Configuration.php b/src/Entity/Configuration.php index 969e5cb6..eb8f8772 100644 --- a/src/Entity/Configuration.php +++ b/src/Entity/Configuration.php @@ -9,13 +9,14 @@ namespace App\Entity; +use App\Repository\ConfigurationRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_configuration')] #[ORM\UniqueConstraint(columns: ['name'])] -#[ORM\Entity(repositoryClass: 'App\Repository\ConfigurationRepository')] +#[ORM\Entity(repositoryClass: ConfigurationRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity('name')] class Configuration diff --git a/src/Entity/Customer.php b/src/Entity/Customer.php index 6e4b18bc..4931ce2e 100644 --- a/src/Entity/Customer.php +++ b/src/Entity/Customer.php @@ -12,6 +12,7 @@ namespace App\Entity; use App\Doctrine\Behavior\CreatedAt; use App\Doctrine\Behavior\CreatedTrait; use App\Export\Annotation as Exporter; +use App\Repository\CustomerRepository; use App\Validator\Constraints as Constraints; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -22,7 +23,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_customers')] #[ORM\Index(columns: ['visible'])] -#[ORM\Entity(repositoryClass: 'App\Repository\CustomerRepository')] +#[ORM\Entity(repositoryClass: CustomerRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[Serializer\ExclusionPolicy('all')] #[Exporter\Order(['id', 'name', 'company', 'number', 'vatId', 'address', 'contact', 'email', 'phone', 'mobile', 'fax', 'homepage', 'country', 'currency', 'timezone', 'budget', 'timeBudget', 'budgetType', 'color', 'visible', 'comment', 'billable'])] diff --git a/src/Entity/CustomerRate.php b/src/Entity/CustomerRate.php index 9ab493f4..30e95f10 100644 --- a/src/Entity/CustomerRate.php +++ b/src/Entity/CustomerRate.php @@ -9,6 +9,7 @@ namespace App\Entity; +use App\Repository\CustomerRateRepository; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; @@ -16,7 +17,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_customers_rates')] #[ORM\UniqueConstraint(columns: ['user_id', 'customer_id'])] -#[ORM\Entity(repositoryClass: 'App\Repository\CustomerRateRepository')] +#[ORM\Entity(repositoryClass: CustomerRateRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity(['user', 'customer'], ignoreNull: false)] #[Serializer\ExclusionPolicy('all')] diff --git a/src/Entity/Invoice.php b/src/Entity/Invoice.php index 350136cd..5f1f691c 100644 --- a/src/Entity/Invoice.php +++ b/src/Entity/Invoice.php @@ -11,17 +11,19 @@ namespace App\Entity; use App\Export\Annotation as Exporter; use App\Invoice\InvoiceModel; +use App\Repository\InvoiceRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; +use OpenApi\Attributes as OA; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_invoices')] #[ORM\UniqueConstraint(columns: ['invoice_number'])] #[ORM\UniqueConstraint(columns: ['invoice_filename'])] -#[ORM\Entity(repositoryClass: 'App\Repository\InvoiceRepository')] +#[ORM\Entity(repositoryClass: InvoiceRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity('invoiceNumber')] #[UniqueEntity('invoiceFilename')] @@ -65,12 +67,14 @@ class Invoice implements EntityWithMetaFields #[Assert\NotNull] #[Serializer\Expose] #[Serializer\Groups(['Default'])] + #[OA\Property(ref: '#/components/schemas/Customer')] private ?Customer $customer = null; #[ORM\ManyToOne(targetEntity: User::class)] #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] #[Assert\NotNull] #[Serializer\Expose] #[Serializer\Groups(['Default'])] + #[OA\Property(ref: '#/components/schemas/User')] private ?User $user = null; #[ORM\Column(name: 'created_at', type: 'datetime', nullable: false)] #[Assert\NotNull] diff --git a/src/Entity/InvoiceTemplate.php b/src/Entity/InvoiceTemplate.php index 39cbe6a7..26286071 100644 --- a/src/Entity/InvoiceTemplate.php +++ b/src/Entity/InvoiceTemplate.php @@ -9,13 +9,14 @@ namespace App\Entity; +use App\Repository\InvoiceTemplateRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_invoice_templates')] #[ORM\UniqueConstraint(columns: ['name'])] -#[ORM\Entity(repositoryClass: 'App\Repository\InvoiceTemplateRepository')] +#[ORM\Entity(repositoryClass: InvoiceTemplateRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity('name')] class InvoiceTemplate diff --git a/src/Entity/Project.php b/src/Entity/Project.php index 0f6b9b3a..097169db 100644 --- a/src/Entity/Project.php +++ b/src/Entity/Project.php @@ -12,6 +12,7 @@ namespace App\Entity; use App\Doctrine\Behavior\CreatedAt; use App\Doctrine\Behavior\CreatedTrait; use App\Export\Annotation as Exporter; +use App\Repository\ProjectRepository; use App\Validator\Constraints as Constraints; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; @@ -23,7 +24,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_projects')] #[ORM\Index(columns: ['customer_id', 'visible', 'name'])] #[ORM\Index(columns: ['customer_id', 'visible', 'id'])] -#[ORM\Entity(repositoryClass: 'App\Repository\ProjectRepository')] +#[ORM\Entity(repositoryClass: ProjectRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[Serializer\ExclusionPolicy('all')] #[Serializer\VirtualProperty('CustomerName', exp: 'object.getCustomer() === null ? null : object.getCustomer().getName()', options: [new Serializer\SerializedName('parentTitle'), new Serializer\Type(name: 'string'), new Serializer\Groups(['Project'])])] diff --git a/src/Entity/ProjectRate.php b/src/Entity/ProjectRate.php index 54095fe3..04dce7d5 100644 --- a/src/Entity/ProjectRate.php +++ b/src/Entity/ProjectRate.php @@ -9,6 +9,7 @@ namespace App\Entity; +use App\Repository\ProjectRateRepository; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; @@ -16,7 +17,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_projects_rates')] #[ORM\UniqueConstraint(columns: ['user_id', 'project_id'])] -#[ORM\Entity(repositoryClass: 'App\Repository\ProjectRateRepository')] +#[ORM\Entity(repositoryClass: ProjectRateRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity(['user', 'project'], ignoreNull: false)] #[Serializer\ExclusionPolicy('all')] diff --git a/src/Entity/Role.php b/src/Entity/Role.php index eaa9403c..c877becf 100644 --- a/src/Entity/Role.php +++ b/src/Entity/Role.php @@ -9,13 +9,14 @@ namespace App\Entity; +use App\Repository\RoleRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_roles')] #[ORM\UniqueConstraint(name: 'roles_name', columns: ['name'])] -#[ORM\Entity(repositoryClass: 'App\Repository\RoleRepository')] +#[ORM\Entity(repositoryClass: RoleRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity('name')] class Role diff --git a/src/Entity/RolePermission.php b/src/Entity/RolePermission.php index b1477acd..eda45186 100644 --- a/src/Entity/RolePermission.php +++ b/src/Entity/RolePermission.php @@ -9,13 +9,14 @@ namespace App\Entity; +use App\Repository\RolePermissionRepository; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_roles_permissions')] #[ORM\UniqueConstraint(name: 'role_permission', columns: ['role_id', 'permission'])] -#[ORM\Entity(repositoryClass: 'App\Repository\RolePermissionRepository')] +#[ORM\Entity(repositoryClass: RolePermissionRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity(['role', 'permission'])] class RolePermission diff --git a/src/Entity/Tag.php b/src/Entity/Tag.php index fa7435e6..1701ae80 100644 --- a/src/Entity/Tag.php +++ b/src/Entity/Tag.php @@ -9,6 +9,7 @@ namespace App\Entity; +use App\Repository\TagRepository; use App\Utils\Color; use Doctrine\ORM\Mapping as ORM; use JMS\Serializer\Annotation as Serializer; @@ -17,7 +18,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_tags')] #[ORM\UniqueConstraint(columns: ['name'])] -#[ORM\Entity(repositoryClass: 'App\Repository\TagRepository')] +#[ORM\Entity(repositoryClass: TagRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity('name')] #[Serializer\ExclusionPolicy('all')] diff --git a/src/Entity/Timesheet.php b/src/Entity/Timesheet.php index 11d2059e..b85d0eb1 100644 --- a/src/Entity/Timesheet.php +++ b/src/Entity/Timesheet.php @@ -11,6 +11,7 @@ namespace App\Entity; use App\Doctrine\Behavior\ModifiedAt; use App\Doctrine\Behavior\ModifiedTrait; +use App\Repository\TimesheetRepository; use App\Validator\Constraints as Constraints; use DateTime; use DateTimeZone; @@ -37,7 +38,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Index(columns: ['end_time', 'user', 'start_time'], name: 'IDX_TIMESHEET_TICKTAC')] #[ORM\Index(columns: ['user', 'project_id', 'activity_id'], name: 'IDX_TIMESHEET_RECENT_ACTIVITIES')] #[ORM\Index(columns: ['user', 'id', 'duration'], name: 'IDX_TIMESHEET_RESULT_STATS')] -#[ORM\Entity(repositoryClass: 'App\Repository\TimesheetRepository')] +#[ORM\Entity(repositoryClass: TimesheetRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[ORM\HasLifecycleCallbacks] #[Serializer\ExclusionPolicy('all')] diff --git a/src/Entity/User.php b/src/Entity/User.php index a1209fec..07542034 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -10,6 +10,7 @@ namespace App\Entity; use App\Export\Annotation as Exporter; +use App\Repository\UserRepository; use App\Utils\StringHelper; use App\Validator\Constraints as Constraints; use App\WorkingTime\Mode\WorkingTimeModeNone; @@ -33,7 +34,7 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Table(name: 'kimai2_users')] #[ORM\UniqueConstraint(columns: ['username'])] #[ORM\UniqueConstraint(columns: ['email'])] -#[ORM\Entity(repositoryClass: 'App\Repository\UserRepository')] +#[ORM\Entity(repositoryClass: UserRepository::class)] #[ORM\ChangeTrackingPolicy('DEFERRED_EXPLICIT')] #[UniqueEntity('username')] #[UniqueEntity('email')] diff --git a/src/Repository/WorkingTimeRepository.php b/src/Repository/WorkingTimeRepository.php index 59543f2a..4f4031f3 100644 --- a/src/Repository/WorkingTimeRepository.php +++ b/src/Repository/WorkingTimeRepository.php @@ -66,6 +66,35 @@ class WorkingTimeRepository extends EntityRepository return $qb->getQuery()->getResult(); } + /** + * @deprecated since 2.25.0 - kept for BC with old plugin versions + */ + public function getLatestApproval(User $user): ?WorkingTime + { + $qb = $this->createQueryBuilder('w'); + $qb->select('MAX(DATE(w.date))') + ->where($qb->expr()->eq('w.user', ':user')) + ->setParameter('user', $user->getId()) + ->andWhere($qb->expr()->isNotNull('w.approvedAt')) + ; + + $date = $qb->getQuery()->getSingleScalarResult(); + + if ($date === null) { + return null; + } + + $qb = $this->createQueryBuilder('w'); + $qb->select('w') + ->where($qb->expr()->eq('w.user', ':user')) + ->setParameter('user', $user->getId()) + ->andWhere($qb->expr()->eq('DATE(w.date)', 'DATE(:date)')) + ->setParameter('date', $date) + ; + + return $qb->getQuery()->getOneOrNullResult(); + } + public function getLatestApprovalDate(User $user): ?\DateTimeInterface { $qb = $this->createQueryBuilder('w'); diff --git a/src/Saml/SamlAuthenticator.php b/src/Saml/SamlAuthenticator.php index 80d3e9cb..45bb7674 100644 --- a/src/Saml/SamlAuthenticator.php +++ b/src/Saml/SamlAuthenticator.php @@ -50,6 +50,10 @@ class SamlAuthenticator extends AbstractAuthenticator return false; } + if (!$request->isMethod(Request::METHOD_POST)) { + return false; + } + if (!$this->httpUtils->checkRequestPath($request, $this->options['check_path'])) { return false; } @@ -81,7 +85,7 @@ class SamlAuthenticator extends AbstractAuthenticator // file_put_contents(__DIR__ . '/../../var/log/saml.xml', $oneLoginAuth->getLastResponseXML()); - if ($oneLoginAuth->getErrors()) { + if (\count($oneLoginAuth->getErrors()) > 0) { throw new AuthenticationException($oneLoginAuth->getLastErrorReason()); } diff --git a/src/Saml/Security/SamlAuthenticationSuccessHandler.php b/src/Saml/Security/SamlAuthenticationSuccessHandler.php index bd9403ad..0874a211 100644 --- a/src/Saml/Security/SamlAuthenticationSuccessHandler.php +++ b/src/Saml/Security/SamlAuthenticationSuccessHandler.php @@ -24,15 +24,12 @@ final class SamlAuthenticationSuccessHandler extends DefaultAuthenticationSucces protected function determineTargetUrl(Request $request): string { - if ($this->options['always_use_default_target_path']) { - return $this->options['default_target_path']; - } - $relayState = $request->get('RelayState'); - $loginUrl = $this->httpUtils->generateUri($request, $this->options['login_path']); - - if ($relayState !== null && $relayState !== '' && $relayState !== $loginUrl) { - return $relayState; + if (\is_scalar($relayState)) { + $relayState = (string) $relayState; + if ($relayState !== $this->httpUtils->generateUri($request, (string) $this->options['login_path'])) { + return $relayState; + } } return parent::determineTargetUrl($request); diff --git a/src/Security/TwoFactorCondition.php b/src/Security/TwoFactorCondition.php index ce501cdc..c88ad8de 100644 --- a/src/Security/TwoFactorCondition.php +++ b/src/Security/TwoFactorCondition.php @@ -15,7 +15,7 @@ use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; final class TwoFactorCondition implements TwoFactorConditionInterface { - public function __construct(private AuthorizationCheckerInterface $authorizationChecker) + public function __construct(private readonly AuthorizationCheckerInterface $authorizationChecker) { } diff --git a/src/Utils/DataTable.php b/src/Utils/DataTable.php index a3897970..bdcfc269 100644 --- a/src/Utils/DataTable.php +++ b/src/Utils/DataTable.php @@ -88,13 +88,12 @@ final class DataTable implements \Countable, \IteratorAggregate /** * @param FormInterface|null $batchForm - * @return void */ public function setBatchForm(?FormInterface $batchForm): void { $this->batchForm = $batchForm; - if (!\array_key_exists('id', $this->columns)) { + if ($batchForm !== null && !\array_key_exists('id', $this->columns)) { $this->addColumn('id', [ 'class' => 'alwaysVisible multiCheckbox', 'orderBy' => false, diff --git a/src/WorkingTime/WorkingTimeService.php b/src/WorkingTime/WorkingTimeService.php index c6bf8b13..11c3044a 100644 --- a/src/WorkingTime/WorkingTimeService.php +++ b/src/WorkingTime/WorkingTimeService.php @@ -32,6 +32,8 @@ final class WorkingTimeService { private const LATEST_APPROVAL_PREF = '_latest_approval'; private const LATEST_APPROVAL_FORMAT = 'Y-m-d H:i:s'; + /** @var array */ + private array $latestApprovals = []; public function __construct( private readonly TimesheetRepository $timesheetRepository, @@ -58,6 +60,24 @@ final class WorkingTimeService return $yearPerUserSummary; } + /** + * @deprecated since 2.25.0 - kept for BC with old plugin versions + */ + public function getLatestApproval(User $user): ?WorkingTime + { + if ($user->getId() === null) { + return null; + } + + $key = 'u_' . $user->getId(); + + if (!\array_key_exists($key, $this->latestApprovals)) { + $this->latestApprovals[$key] = $this->workingTimeRepository->getLatestApproval($user); + } + + return $this->latestApprovals[$key]; + } + public function getLatestApprovalDate(User $user): ?\DateTimeInterface { if ($user->getId() === null) { diff --git a/tests/API/APIControllerBaseTest.php b/tests/API/APIControllerBaseTest.php index 09519f7a..d29b83f6 100644 --- a/tests/API/APIControllerBaseTest.php +++ b/tests/API/APIControllerBaseTest.php @@ -188,6 +188,14 @@ abstract class APIControllerBaseTest extends ControllerBaseTest ]); } + protected function assertBadRequestResponse(Response $response): void + { + $this->assertApiException($response, [ + 'code' => Response::HTTP_BAD_REQUEST, + 'message' => 'Bad Request' + ]); + } + protected function assertApiAccessDenied(HttpKernelBrowser $client, string $url, string $message = 'Forbidden'): void { $this->request($client, $url); diff --git a/tests/API/TimesheetControllerTest.php b/tests/API/TimesheetControllerTest.php index c8305a2e..8d75f335 100644 --- a/tests/API/TimesheetControllerTest.php +++ b/tests/API/TimesheetControllerTest.php @@ -1173,18 +1173,9 @@ class TimesheetControllerTest extends APIControllerBaseTest $this->assertIsArray($result[0]); self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]); - $query = ['tags' => ['Nothing-2-see', 'here']]; - $this->assertAccessIsGranted($client, '/api/timesheets', 'GET', $query); - - $content = $client->getResponse()->getContent(); - self::assertIsString($content); - $result = json_decode($content, true); - - self::assertIsArray($result); - self::assertNotEmpty($result); - self::assertEquals(20, \count($result)); - $this->assertIsArray($result[0]); - self::assertApiResponseTypeStructure('TimesheetCollection', $result[0]); + $query = ['tags' => ['Nothing-2-see', 'not-existing-here']]; + $this->request($client, '/api/timesheets', 'GET', $query); + $this->assertBadRequestResponse($client->getResponse()); } public function testRestartAction(): void diff --git a/tests/Controller/Auth/SamlControllerTest.php b/tests/Controller/Auth/SamlControllerTest.php index 24fb26b8..34c1ccb4 100644 --- a/tests/Controller/Auth/SamlControllerTest.php +++ b/tests/Controller/Auth/SamlControllerTest.php @@ -10,11 +10,13 @@ namespace App\Tests\Controller\Auth; use App\Configuration\SamlConfiguration; +use App\Configuration\SamlConfigurationInterface; use App\Configuration\SystemConfiguration; use App\Controller\Auth\SamlController; use App\Saml\SamlAuthFactory; use App\Tests\Configuration\TestConfigLoader; use App\Tests\Mocks\Saml\SamlAuthFactoryFactory; +use App\Tests\Mocks\SecurityFactory; use App\Tests\Mocks\SystemConfigurationFactory; use OneLogin\Saml2\Auth; use PHPUnit\Framework\TestCase; @@ -28,19 +30,14 @@ use Symfony\Component\Security\Http\SecurityRequestAttributes; */ class SamlControllerTest extends TestCase { - /** - * @param array $settings - * @param array $loaderSettings - * @return SystemConfiguration - */ - protected function getSystemConfigurationMock(array $settings, array $loaderSettings = []) + protected function getSystemConfigurationMock(array $settings, array $loaderSettings = []): SystemConfiguration { $loader = new TestConfigLoader($loaderSettings); return SystemConfigurationFactory::create($loader, $settings); } - protected function getDefaultSettings(bool $activated = true) + protected function getDefaultSettings(bool $activated = true): array { return [ 'saml' => [ @@ -66,10 +63,15 @@ class SamlControllerTest extends TestCase $factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock(); - $sut = new SamlController($factory, $this->getSamlConfiguration()); + $sut = $this->getSut($factory, $this->getSamlConfiguration()); $sut->assertionConsumerServiceAction(); } + public function getSut(SamlAuthFactory $authFactory, SamlConfigurationInterface $samlConfiguration): SamlController + { + return new SamlController($authFactory, $samlConfiguration, (new SecurityFactory($this))->create()); + } + public function testMetadataAction(): void { $expectedXmlString = <<getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock(); $factory->expects($this->once())->method('create')->willReturn($oauth); - $sut = new SamlController($factory, $this->getSamlConfiguration()); + $sut = $this->getSut($factory, $this->getSamlConfiguration()); $result = $sut->metadataAction(); self::assertEquals('xml', $result->headers->get('Content-Type')); @@ -129,7 +131,7 @@ class SamlControllerTest extends TestCase $factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock(); - $sut = new SamlController($factory, $this->getSamlConfiguration()); + $sut = $this->getSut($factory, $this->getSamlConfiguration()); $sut->loginAction($request); } @@ -140,7 +142,7 @@ class SamlControllerTest extends TestCase $factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock(); - $sut = new SamlController($factory, $this->getSamlConfiguration(false)); + $sut = $this->getSut($factory, $this->getSamlConfiguration(false)); $sut->loginAction(new Request()); } @@ -151,7 +153,7 @@ class SamlControllerTest extends TestCase $factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock(); - $sut = new SamlController($factory, $this->getSamlConfiguration(false)); + $sut = $this->getSut($factory, $this->getSamlConfiguration(false)); $sut->metadataAction(); } @@ -162,7 +164,7 @@ class SamlControllerTest extends TestCase $factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock(); - $sut = new SamlController($factory, $this->getSamlConfiguration(false)); + $sut = $this->getSut($factory, $this->getSamlConfiguration(false)); $sut->logoutAction(); } @@ -173,7 +175,7 @@ class SamlControllerTest extends TestCase $factory = $this->getMockBuilder(SamlAuthFactory::class)->disableOriginalConstructor()->getMock(); - $sut = new SamlController($factory, $this->getSamlConfiguration(false)); + $sut = $this->getSut($factory, $this->getSamlConfiguration(false)); $sut->assertionConsumerServiceAction(); } } diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index f5e078ef..94eb99a6 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -290,6 +290,7 @@ class ConfigurationTest extends TestCase 'break_warning_duration' => 0, 'long_running_duration' => 0, 'require_activity' => true, + 'break_time_active' => false, ], 'duration_increment' => 15, 'time_increment' => 15, diff --git a/tests/Mocks/SecurityFactory.php b/tests/Mocks/SecurityFactory.php new file mode 100644 index 00000000..04e54fa7 --- /dev/null +++ b/tests/Mocks/SecurityFactory.php @@ -0,0 +1,31 @@ +createMock(TokenInterface::class); + $interface->method('getUser')->willReturn(new User()); + $storage = $this->createMock(TokenStorageInterface::class); + $storage->method('getToken')->willReturn($interface); + $container = $this->createMock(ContainerInterface::class); + $container->method('get')->willReturn($storage); + + return new Security($container); + } +} diff --git a/tests/Saml/Security/SamlAuthenticationSuccessHandlerTest.php b/tests/Saml/Security/SamlAuthenticationSuccessHandlerTest.php index 4fb80752..e004e2ee 100644 --- a/tests/Saml/Security/SamlAuthenticationSuccessHandlerTest.php +++ b/tests/Saml/Security/SamlAuthenticationSuccessHandlerTest.php @@ -15,6 +15,7 @@ use App\Saml\Security\SamlAuthenticationSuccessHandler; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Http\HttpUtils; /** @@ -22,19 +23,9 @@ use Symfony\Component\Security\Http\HttpUtils; */ class SamlAuthenticationSuccessHandlerTest extends TestCase { - public function testWithAlwaysUseDefaultTargetPath(): void - { - $httpUtils = new HttpUtils($this->getUrlGenerator()); - $handler = new SamlAuthenticationSuccessHandler($httpUtils, ['always_use_default_target_path' => true]); - $defaultTargetPath = $httpUtils->generateUri($this->getRequest('/sso/login'), $this->getOption($handler, 'default_target_path', '/')); - $response = $handler->onAuthenticationSuccess($this->getRequest('/login', 'http://localhost/relayed'), $this->getSamlToken()); - $this->assertInstanceOf(RedirectResponse::class, $response); - $this->assertTrue($response->isRedirect($defaultTargetPath)); - } - public function testRelayState(): void { - $handler = new SamlAuthenticationSuccessHandler(new HttpUtils($this->getUrlGenerator()), ['always_use_default_target_path' => false]); + $handler = new SamlAuthenticationSuccessHandler(new HttpUtils($this->getUrlGenerator())); $response = $handler->onAuthenticationSuccess($this->getRequest('/sso/login', 'http://localhost/relayed'), $this->getSamlToken()); $this->assertInstanceOf(RedirectResponse::class, $response); $this->assertTrue($response->isRedirect('http://localhost/relayed')); @@ -43,8 +34,8 @@ class SamlAuthenticationSuccessHandlerTest extends TestCase public function testWithoutRelayState(): void { $httpUtils = new HttpUtils($this->getUrlGenerator()); - $handler = new SamlAuthenticationSuccessHandler($httpUtils, ['always_use_default_target_path' => false]); - $defaultTargetPath = $httpUtils->generateUri($this->getRequest('/sso/login'), $this->getOption($handler, 'default_target_path', '/')); + $handler = new SamlAuthenticationSuccessHandler($httpUtils); + $defaultTargetPath = $httpUtils->generateUri($this->getRequest('/sso/login'), '/'); $response = $handler->onAuthenticationSuccess($this->getRequest(), $this->getSamlToken()); $this->assertInstanceOf(RedirectResponse::class, $response); $this->assertTrue($response->isRedirect($defaultTargetPath)); @@ -53,16 +44,16 @@ class SamlAuthenticationSuccessHandlerTest extends TestCase public function testRelayStateLoop(): void { $httpUtils = new HttpUtils($this->getUrlGenerator()); - $handler = new SamlAuthenticationSuccessHandler($httpUtils, ['always_use_default_target_path' => false]); - $loginPath = $httpUtils->generateUri($this->getRequest('/sso/login'), $this->getOption($handler, 'login_path', '/login')); + $handler = new SamlAuthenticationSuccessHandler($httpUtils); + $loginPath = $httpUtils->generateUri($this->getRequest('/sso/login'), '/login'); $response = $handler->onAuthenticationSuccess($this->getRequest($loginPath), $this->getSamlToken()); $this->assertInstanceOf(RedirectResponse::class, $response); $this->assertTrue(!$response->isRedirect($loginPath)); } - private function getUrlGenerator() + private function getUrlGenerator(): UrlGeneratorInterface { - $urlGenerator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock(); + $urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock(); $urlGenerator ->expects($this->any()) ->method('generate') @@ -74,7 +65,7 @@ class SamlAuthenticationSuccessHandlerTest extends TestCase return $urlGenerator; } - private function getRequest($path = '/', $relayState = null) + private function getRequest(string $path = '/', ?string $relayState = null): Request { $params = []; if (null !== $relayState) { @@ -84,7 +75,7 @@ class SamlAuthenticationSuccessHandlerTest extends TestCase return Request::create($path, 'get', $params); } - private function getSamlToken() + private function getSamlToken(): SamlToken { $user = new User(); $user->setUserIdentifier('admin'); @@ -94,17 +85,4 @@ class SamlAuthenticationSuccessHandlerTest extends TestCase return $token; } - - private function getOption($handler, $name, $default = null) - { - $reflection = new \ReflectionObject($handler); - $options = $reflection->getProperty('options'); - $options->setAccessible(true); - $arr = $options->getValue($handler); - if (!\is_array($arr) || !isset($arr[$name])) { - return $default; - } - - return $arr[$name]; - } } diff --git a/tests/phpstan.neon b/tests/phpstan.neon index d8084c5d..f268e0ea 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -599,11 +599,6 @@ parameters: count: 2 path: Controller/Auth/SamlControllerTest.php - - - message: "#^Method App\\\\Tests\\\\Controller\\\\Auth\\\\SamlControllerTest\\:\\:getDefaultSettings\\(\\) has no return type specified\\.$#" - count: 1 - path: Controller/Auth/SamlControllerTest.php - - message: "#^Method App\\\\Tests\\\\Controller\\\\Auth\\\\SamlControllerTest\\:\\:getSystemConfigurationMock\\(\\) has parameter \\$loaderSettings with no value type specified in iterable type array\\.$#" count: 1 @@ -2364,51 +2359,6 @@ parameters: count: 1 path: Saml/SamlProviderTest.php - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getOption\\(\\) has no return type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getOption\\(\\) has parameter \\$default with no type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getOption\\(\\) has parameter \\$handler with no type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getOption\\(\\) has parameter \\$name with no type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getRequest\\(\\) has no return type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getRequest\\(\\) has parameter \\$path with no type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getRequest\\(\\) has parameter \\$relayState with no type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getSamlToken\\(\\) has no return type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - - - message: "#^Method App\\\\Tests\\\\Saml\\\\Security\\\\SamlAuthenticationSuccessHandlerTest\\:\\:getUrlGenerator\\(\\) has no return type specified\\.$#" - count: 1 - path: Saml/Security/SamlAuthenticationSuccessHandlerTest.php - - message: "#^Method App\\\\Tests\\\\Timesheet\\\\Calculator\\\\BillableCalculatorTest\\:\\:getTestData\\(\\) has no return type specified\\.$#" count: 1 diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index bf433dc5..748e2bed 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -1930,6 +1930,14 @@ import Import + + Sessions + Sitzungen + + + Log out of all devices + Von allen Geräten abmelden + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 36620bde..27221eeb 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -1930,6 +1930,14 @@ import Import + + Sessions + Sessions + + + Log out of all devices + Log out of all devices +