diff --git a/composer.json b/composer.json index 164c5d3ab..5a1e4d294 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "ext-zip": "*", "composer/package-versions-deprecated": "^1.8", "composer/semver": "^3.3", - "doctrine/doctrine-bundle": "^2.0", + "doctrine/doctrine-bundle": "^2.7", "doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/orm": "^2.8", "endroid/qr-code": "^4.4.9", @@ -49,7 +49,6 @@ "scheb/2fa-backup-code": "^6.2", "scheb/2fa-bundle": "^6.2", "scheb/2fa-totp": "^6.2", - "sensio/framework-extra-bundle": "^6.0", "symfony/asset": "^6.0", "symfony/console": "^6.0", "symfony/dotenv": "^6.0", @@ -68,7 +67,7 @@ "symfony/translation": "^6.0", "symfony/twig-bundle": "^6.0", "symfony/validator": "^6.0", - "symfony/webpack-encore-bundle": "^1.5", + "symfony/webpack-encore-bundle": "^1.16", "symfony/yaml": "^6.0", "twig/cssinliner-extra": "^3.0", "twig/extra-bundle": "^3.0", @@ -196,7 +195,7 @@ "symfony": { "id": "01C3FWRDJJEX9K6Y3A4XDFXPBR", "allow-contrib": true, - "require": "6.0.*" + "require": "6.2.*" } } } diff --git a/composer.lock b/composer.lock index 40fb409ba..ac1229fb7 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": "f3b0627c043009647c1ab9c3ddea3f22", + "content-hash": "28a3255e3b7098abd50383910cd0cf9b", "packages": [ { "name": "bacon/bacon-qr-code", @@ -642,16 +642,16 @@ }, { "name": "doctrine/dbal", - "version": "3.5.2", + "version": "3.5.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "63e513cebbbaf96a6795e5c5ee34d205831bfc85" + "reference": "88fa7e5189fd5ec6682477044264dc0ed4e3aa1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/63e513cebbbaf96a6795e5c5ee34d205831bfc85", - "reference": "63e513cebbbaf96a6795e5c5ee34d205831bfc85", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/88fa7e5189fd5ec6682477044264dc0ed4e3aa1e", + "reference": "88fa7e5189fd5ec6682477044264dc0ed4e3aa1e", "shasum": "" }, "require": { @@ -666,7 +666,7 @@ "require-dev": { "doctrine/coding-standard": "11.0.0", "jetbrains/phpstorm-stubs": "2022.3", - "phpstan/phpstan": "1.9.2", + "phpstan/phpstan": "1.9.4", "phpstan/phpstan-strict-rules": "^1.4", "phpunit/phpunit": "9.5.27", "psalm/plugin-phpunit": "0.18.4", @@ -733,7 +733,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.5.2" + "source": "https://github.com/doctrine/dbal/tree/3.5.3" }, "funding": [ { @@ -749,7 +749,7 @@ "type": "tidelift" } ], - "time": "2022-12-19T08:17:34+00:00" + "time": "2023-01-12T10:21:44+00:00" }, { "name": "doctrine/deprecations", @@ -796,16 +796,16 @@ }, { "name": "doctrine/doctrine-bundle", - "version": "2.8.1", + "version": "2.8.2", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "fe9b2cc1cd0c9b76553b1d4c1a077590ba231a2d" + "reference": "251cd5aaea32bb92cdad4204840786b317dcdd4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/fe9b2cc1cd0c9b76553b1d4c1a077590ba231a2d", - "reference": "fe9b2cc1cd0c9b76553b1d4c1a077590ba231a2d", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/251cd5aaea32bb92cdad4204840786b317dcdd4c", + "reference": "251cd5aaea32bb92cdad4204840786b317dcdd4c", "shasum": "" }, "require": { @@ -891,7 +891,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.8.1" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.8.2" }, "funding": [ { @@ -907,7 +907,7 @@ "type": "tidelift" } ], - "time": "2023-01-06T00:24:26+00:00" + "time": "2023-01-06T11:42:10+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", @@ -1249,31 +1249,33 @@ }, { "name": "doctrine/lexer", - "version": "1.2.3", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229" + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229", - "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.0", "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9.0", + "doctrine/coding-standard": "^9 || ^10", "phpstan/phpstan": "^1.3", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.11" + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1305,7 +1307,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.2.3" + "source": "https://github.com/doctrine/lexer/tree/2.1.0" }, "funding": [ { @@ -1321,25 +1323,25 @@ "type": "tidelift" } ], - "time": "2022-02-28T11:07:21+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { "name": "doctrine/migrations", - "version": "3.5.2", + "version": "3.5.4", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "61c6ef3a10b7df43c3b6388a184754f26e58700a" + "reference": "e327d1f241e964161f1d3f4e82f7aefbe2da45dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/61c6ef3a10b7df43c3b6388a184754f26e58700a", - "reference": "61c6ef3a10b7df43c3b6388a184754f26e58700a", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/e327d1f241e964161f1d3f4e82f7aefbe2da45dd", + "reference": "e327d1f241e964161f1d3f4e82f7aefbe2da45dd", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/dbal": "^3.3", + "doctrine/dbal": "^3.5.1", "doctrine/deprecations": "^0.5.3 || ^1", "doctrine/event-manager": "^1.0", "friendsofphp/proxy-manager-lts": "^1.0", @@ -1353,10 +1355,9 @@ }, "require-dev": { "doctrine/coding-standard": "^9", - "doctrine/orm": "^2.12", + "doctrine/orm": "^2.13", "doctrine/persistence": "^2 || ^3", "doctrine/sql-formatter": "^1.0", - "ergebnis/composer-normalize": "^2.9", "ext-pdo_sqlite": "*", "phpstan/phpstan": "^1.5", "phpstan/phpstan-deprecation-rules": "^1", @@ -1376,12 +1377,6 @@ "bin/doctrine-migrations" ], "type": "library", - "extra": { - "composer-normalize": { - "indent-size": 4, - "indent-style": "space" - } - }, "autoload": { "psr-4": { "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" @@ -1414,7 +1409,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.5.2" + "source": "https://github.com/doctrine/migrations/tree/3.5.4" }, "funding": [ { @@ -1430,20 +1425,20 @@ "type": "tidelift" } ], - "time": "2022-08-04T14:29:49+00:00" + "time": "2023-01-17T20:39:56+00:00" }, { "name": "doctrine/orm", - "version": "2.14.0", + "version": "2.14.1", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "f82485e651763fbd1b34879726f4d3b91c358bd9" + "reference": "de7eee5ed7b1b35c99b118f26f210a8281e6db8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/f82485e651763fbd1b34879726f4d3b91c358bd9", - "reference": "f82485e651763fbd1b34879726f4d3b91c358bd9", + "url": "https://api.github.com/repos/doctrine/orm/zipball/de7eee5ed7b1b35c99b118f26f210a8281e6db8e", + "reference": "de7eee5ed7b1b35c99b118f26f210a8281e6db8e", "shasum": "" }, "require": { @@ -1472,14 +1467,14 @@ "doctrine/annotations": "^1.13 || ^2", "doctrine/coding-standard": "^9.0.2 || ^11.0", "phpbench/phpbench": "^0.16.10 || ^1.0", - "phpstan/phpstan": "~1.4.10 || 1.9.4", + "phpstan/phpstan": "~1.4.10 || 1.9.8", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.1", "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.3.0" + "vimeo/psalm": "4.30.0 || 5.4.0" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1529,9 +1524,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.14.0" + "source": "https://github.com/doctrine/orm/tree/2.14.1" }, - "time": "2022-12-19T21:51:58+00:00" + "time": "2023-01-16T18:36:59+00:00" }, { "name": "doctrine/persistence", @@ -2020,16 +2015,16 @@ }, { "name": "friendsofsymfony/rest-bundle", - "version": "3.4.0", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/FriendsOfSymfony/FOSRestBundle.git", - "reference": "b888195589d245002880d07073ef23ab60e3795d" + "reference": "893f3a01e4d88789abc399c6f1b3cfff79238734" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/b888195589d245002880d07073ef23ab60e3795d", - "reference": "b888195589d245002880d07073ef23ab60e3795d", + "url": "https://api.github.com/repos/FriendsOfSymfony/FOSRestBundle/zipball/893f3a01e4d88789abc399c6f1b3cfff79238734", + "reference": "893f3a01e4d88789abc399c6f1b3cfff79238734", "shasum": "" }, "require": { @@ -2056,7 +2051,7 @@ "doctrine/annotations": "^1.13.2", "friendsofphp/php-cs-fixer": "^3.0", "jms/serializer": "^1.13|^2.0|^3.0", - "jms/serializer-bundle": "^2.4.3|^3.0.1|^4.0|^5.0@beta", + "jms/serializer-bundle": "^2.4.3|^3.0.1|^4.0|^5.0", "psr/http-message": "^1.0", "psr/log": "^1.0|^2.0|^3.0", "sensio/framework-extra-bundle": "^6.1", @@ -2120,9 +2115,9 @@ ], "support": { "issues": "https://github.com/FriendsOfSymfony/FOSRestBundle/issues", - "source": "https://github.com/FriendsOfSymfony/FOSRestBundle/tree/3.4.0" + "source": "https://github.com/FriendsOfSymfony/FOSRestBundle/tree/3.5.0" }, - "time": "2022-09-18T04:54:54+00:00" + "time": "2023-01-06T15:33:47+00:00" }, { "name": "gedmo/doctrine-extensions", @@ -2350,22 +2345,22 @@ }, { "name": "jms/serializer", - "version": "3.18.2", + "version": "3.21.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "329e29c323fb1e5c65b4ae4c77ba747678755a6c" + "reference": "cc49ca6cd97baa173166c1f4fc54521964cf28bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/329e29c323fb1e5c65b4ae4c77ba747678755a6c", - "reference": "329e29c323fb1e5c65b4ae4c77ba747678755a6c", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/cc49ca6cd97baa173166c1f4fc54521964cf28bd", + "reference": "cc49ca6cd97baa173166c1f4fc54521964cf28bd", "shasum": "" }, "require": { - "doctrine/annotations": "^1.13", + "doctrine/annotations": "^1.13 || ^2.0", "doctrine/instantiator": "^1.0.3", - "doctrine/lexer": "^1.1", + "doctrine/lexer": "^1.1 || ^2", "jms/metadata": "^2.6", "php": "^7.2||^8.0", "phpstan/phpdoc-parser": "^0.4 || ^0.5 || ^1.0" @@ -2423,7 +2418,7 @@ "email": "goetas@gmail.com" } ], - "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.", + "description": "Library for (de-)serializing data of any complexity; supports XML, and JSON.", "homepage": "http://jmsyst.com/libs/serializer", "keywords": [ "deserialization", @@ -2434,7 +2429,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/serializer/issues", - "source": "https://github.com/schmittjoh/serializer/tree/3.18.2" + "source": "https://github.com/schmittjoh/serializer/tree/3.21.0" }, "funding": [ { @@ -2442,25 +2437,25 @@ "type": "github" } ], - "time": "2022-09-12T08:40:16+00:00" + "time": "2023-01-10T13:08:17+00:00" }, { "name": "jms/serializer-bundle", - "version": "5.0.2", + "version": "5.2.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/JMSSerializerBundle.git", - "reference": "aadf3d14cfb4bf1347ecf0a5426c82a7b99a48f5" + "reference": "cdc876a8bc4611279a7ec970f3da2052cda55078" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/JMSSerializerBundle/zipball/aadf3d14cfb4bf1347ecf0a5426c82a7b99a48f5", - "reference": "aadf3d14cfb4bf1347ecf0a5426c82a7b99a48f5", + "url": "https://api.github.com/repos/schmittjoh/JMSSerializerBundle/zipball/cdc876a8bc4611279a7ec970f3da2052cda55078", + "reference": "cdc876a8bc4611279a7ec970f3da2052cda55078", "shasum": "" }, "require": { "jms/metadata": "^2.5", - "jms/serializer": "^3.18", + "jms/serializer": "^3.20", "php": "^7.2 || ^8.0", "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0 || ^6.0", "symfony/framework-bundle": "^3.4 || ^4.0 || ^5.0 || ^6.0" @@ -2521,7 +2516,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/JMSSerializerBundle/issues", - "source": "https://github.com/schmittjoh/JMSSerializerBundle/tree/5.0.2" + "source": "https://github.com/schmittjoh/JMSSerializerBundle/tree/5.2.0" }, "funding": [ { @@ -2529,7 +2524,7 @@ "type": "github" } ], - "time": "2022-11-03T11:53:29+00:00" + "time": "2023-01-09T16:25:13+00:00" }, { "name": "kevinpapst/tabler-bundle", @@ -2816,16 +2811,16 @@ }, { "name": "lorenzo/pinky", - "version": "1.0.7", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/lorenzo/pinky.git", - "reference": "60afc9f8c2b8fb6a2f77050b485ce93143dd8dcf" + "reference": "f890472e4a25f89591f176aa03d9588a9d3332a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lorenzo/pinky/zipball/60afc9f8c2b8fb6a2f77050b485ce93143dd8dcf", - "reference": "60afc9f8c2b8fb6a2f77050b485ce93143dd8dcf", + "url": "https://api.github.com/repos/lorenzo/pinky/zipball/f890472e4a25f89591f176aa03d9588a9d3332a7", + "reference": "f890472e4a25f89591f176aa03d9588a9d3332a7", "shasum": "" }, "require": { @@ -2863,9 +2858,9 @@ ], "support": { "issues": "https://github.com/lorenzo/pinky/issues", - "source": "https://github.com/lorenzo/pinky/tree/1.0.7" + "source": "https://github.com/lorenzo/pinky/tree/1.0.9" }, - "time": "2022-10-02T12:15:42+00:00" + "time": "2023-01-12T16:15:52+00:00" }, { "name": "maennchen/zipstream-php", @@ -3054,27 +3049,27 @@ }, { "name": "monolog/monolog", - "version": "2.8.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "720488632c590286b88b80e62aa3d3d551ad4a50" + "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/720488632c590286b88b80e62aa3d3d551ad4a50", - "reference": "720488632c590286b88b80e62aa3d3d551ad4a50", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/305444bc6fb6c89e490f4b34fa6e979584d7fa81", + "reference": "305444bc6fb6c89e490f4b34fa6e979584d7fa81", "shasum": "" }, "require": { - "php": ">=7.2", - "psr/log": "^1.0.1 || ^2.0 || ^3.0" + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + "psr/log-implementation": "3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "aws/aws-sdk-php": "^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", @@ -3083,13 +3078,12 @@ "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpspec/prophecy": "^1.15", - "phpstan/phpstan": "^0.12.91", - "phpunit/phpunit": "^8.5.14", - "predis/predis": "^1.1 || ^2.0", - "rollbar/rollbar": "^1.3 || ^2 || ^3", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^9.5.16", + "predis/predis": "^1.1", "ruflin/elastica": "^7", - "swiftmailer/swiftmailer": "^5.3|^6.0", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -3112,7 +3106,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -3140,7 +3134,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.8.0" + "source": "https://github.com/Seldaek/monolog/tree/3.2.0" }, "funding": [ { @@ -3152,7 +3146,7 @@ "type": "tidelift" } ], - "time": "2022-07-24T11:55:47+00:00" + "time": "2022-07-24T12:00:55+00:00" }, { "name": "mpdf/mpdf", @@ -4907,85 +4901,6 @@ }, "time": "2022-12-10T15:20:09+00:00" }, - { - "name": "sensio/framework-extra-bundle", - "version": "v6.2.9", - "source": { - "type": "git", - "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git", - "reference": "dcfac94d6bdcf95c126e8ccac2104917c7c8f135" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/dcfac94d6bdcf95c126e8ccac2104917c7c8f135", - "reference": "dcfac94d6bdcf95c126e8ccac2104917c7c8f135", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "php": ">=7.2.5", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/framework-bundle": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0" - }, - "conflict": { - "doctrine/doctrine-cache-bundle": "<1.3.1", - "doctrine/persistence": "<1.3" - }, - "require-dev": { - "doctrine/dbal": "^2.10|^3.0", - "doctrine/doctrine-bundle": "^1.11|^2.0", - "doctrine/orm": "^2.5", - "symfony/browser-kit": "^4.4|^5.0|^6.0", - "symfony/doctrine-bridge": "^4.4|^5.0|^6.0", - "symfony/dom-crawler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/monolog-bridge": "^4.0|^5.0|^6.0", - "symfony/monolog-bundle": "^3.2", - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0", - "symfony/security-bundle": "^4.4|^5.0|^6.0", - "symfony/twig-bundle": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0", - "twig/twig": "^1.34|^2.4|^3.0" - }, - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "6.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Sensio\\Bundle\\FrameworkExtraBundle\\": "src/" - }, - "exclude-from-classmap": [ - "/tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "This bundle provides a way to configure your controllers with annotations", - "keywords": [ - "annotations", - "controllers" - ], - "support": { - "issues": "https://github.com/sensiolabs/SensioFrameworkExtraBundle/issues", - "source": "https://github.com/sensiolabs/SensioFrameworkExtraBundle/tree/v6.2.9" - }, - "abandoned": "Symfony", - "time": "2022-11-01T17:17:13+00:00" - }, { "name": "setasign/fpdi", "version": "v2.3.6", @@ -5140,20 +5055,20 @@ }, { "name": "symfony/asset", - "version": "v6.0.13", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "77b6b2273185bae723c38b40c6b6990a09616327" + "reference": "a0ebf67f56f028217256d5f99438175430b3836c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/77b6b2273185bae723c38b40c6b6990a09616327", - "reference": "77b6b2273185bae723c38b40c6b6990a09616327", + "url": "https://api.github.com/repos/symfony/asset/zipball/a0ebf67f56f028217256d5f99438175430b3836c", + "reference": "a0ebf67f56f028217256d5f99438175430b3836c", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "conflict": { "symfony/http-foundation": "<5.4" @@ -5192,7 +5107,7 @@ "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset/tree/v6.0.13" + "source": "https://github.com/symfony/asset/tree/v6.2.0" }, "funding": [ { @@ -5208,29 +5123,29 @@ "type": "tidelift" } ], - "time": "2022-08-31T08:17:34+00:00" + "time": "2022-10-19T16:13:28+00:00" }, { "name": "symfony/cache", - "version": "v6.0.18", + "version": "v6.2.4", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "079ec0afe323fdcd5ac1f16e3ffdb4991fb5d4c9" + "reference": "ddd1a70bfdf4ed19facad0db689c7bca979d322e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/079ec0afe323fdcd5ac1f16e3ffdb4991fb5d4c9", - "reference": "079ec0afe323fdcd5ac1f16e3ffdb4991fb5d4c9", + "url": "https://api.github.com/repos/symfony/cache/zipball/ddd1a70bfdf4ed19facad0db689c7bca979d322e", + "reference": "ddd1a70bfdf4ed19facad0db689c7bca979d322e", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^1.1.7|^2|^3", "symfony/service-contracts": "^1.1|^2|^3", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/var-exporter": "^6.2" }, "conflict": { "doctrine/dbal": "<2.13.1", @@ -5260,6 +5175,9 @@ "psr-4": { "Symfony\\Component\\Cache\\": "" }, + "classmap": [ + "Traits/ValueWrapper.php" + ], "exclude-from-classmap": [ "/Tests/" ] @@ -5285,7 +5203,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.0.18" + "source": "https://github.com/symfony/cache/tree/v6.2.4" }, "funding": [ { @@ -5301,7 +5219,7 @@ "type": "tidelift" } ], - "time": "2022-12-29T16:27:58+00:00" + "time": "2022-12-29T16:29:13+00:00" }, { "name": "symfony/cache-contracts", @@ -5384,27 +5302,26 @@ }, { "name": "symfony/config", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "956d4ec5df274dda91a4cedfccc2bfd063f6f649" + "reference": "ebf27792246165a2a0b6b69ec9c620cac8c5a2f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/956d4ec5df274dda91a4cedfccc2bfd063f6f649", - "reference": "956d4ec5df274dda91a4cedfccc2bfd063f6f649", + "url": "https://api.github.com/repos/symfony/config/zipball/ebf27792246165a2a0b6b69ec9c620cac8c5a2f0", + "reference": "ebf27792246165a2a0b6b69ec9c620cac8c5a2f0", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3", "symfony/filesystem": "^5.4|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php81": "^1.22" + "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/finder": "<4.4" + "symfony/finder": "<5.4" }, "require-dev": { "symfony/event-dispatcher": "^5.4|^6.0", @@ -5442,7 +5359,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.0.11" + "source": "https://github.com/symfony/config/tree/v6.2.0" }, "funding": [ { @@ -5458,24 +5375,25 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/console", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2ab307342a7233b9a260edd5ef94087aaca57d18" + "reference": "0f579613e771dba2dbb8211c382342a641f5da06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2ab307342a7233b9a260edd5ef94087aaca57d18", - "reference": "2ab307342a7233b9a260edd5ef94087aaca57d18", + "url": "https://api.github.com/repos/symfony/console/zipball/0f579613e771dba2dbb8211c382342a641f5da06", + "reference": "0f579613e771dba2dbb8211c382342a641f5da06", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^1.1|^2|^3", "symfony/string": "^5.4|^6.0" @@ -5537,7 +5455,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.17" + "source": "https://github.com/symfony/console/tree/v6.2.3" }, "funding": [ { @@ -5553,24 +5471,24 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:21:34+00:00" + "time": "2022-12-28T14:26:22+00:00" }, { "name": "symfony/css-selector", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "3e526b732295b5d4c16c38d557b74ba8498a92b4" + "reference": "ab1df4ba3ded7b724766ba3a6e0eca0418e74f80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/3e526b732295b5d4c16c38d557b74ba8498a92b4", - "reference": "3e526b732295b5d4c16c38d557b74ba8498a92b4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab1df4ba3ded7b724766ba3a6e0eca0418e74f80", + "reference": "ab1df4ba3ded7b724766ba3a6e0eca0418e74f80", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -5602,7 +5520,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.0.17" + "source": "https://github.com/symfony/css-selector/tree/v6.2.3" }, "funding": [ { @@ -5618,34 +5536,34 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:21:34+00:00" + "time": "2022-12-28T14:26:22+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "37ffd67504beedbacaa7fd7358eff7042970d4dc" + "reference": "d10309b75035ce8aae33a377375dac04cab941d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/37ffd67504beedbacaa7fd7358eff7042970d4dc", - "reference": "37ffd67504beedbacaa7fd7358eff7042970d4dc", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d10309b75035ce8aae33a377375dac04cab941d6", + "reference": "d10309b75035ce8aae33a377375dac04cab941d6", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2.0|^3.0" + "symfony/service-contracts": "^1.1.6|^2.0|^3.0", + "symfony/var-exporter": "^6.2" }, "conflict": { "ext-psr": "<1.1|>=2", - "symfony/config": "<5.4", + "symfony/config": "<6.1", "symfony/finder": "<5.4", - "symfony/proxy-manager-bridge": "<5.4", + "symfony/proxy-manager-bridge": "<6.2", "symfony/yaml": "<5.4" }, "provide": { @@ -5653,7 +5571,7 @@ "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^5.4|^6.0", + "symfony/config": "^6.1", "symfony/expression-language": "^5.4|^6.0", "symfony/yaml": "^5.4|^6.0" }, @@ -5661,7 +5579,6 @@ "symfony/config": "", "symfony/expression-language": "For using expressions in service container configuration", "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", "symfony/yaml": "" }, "type": "library", @@ -5690,7 +5607,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.0.17" + "source": "https://github.com/symfony/dependency-injection/tree/v6.2.3" }, "funding": [ { @@ -5706,7 +5623,7 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:21:34+00:00" + "time": "2022-12-28T14:43:49+00:00" }, { "name": "symfony/deprecation-contracts", @@ -5777,22 +5694,22 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "0cc7195607bf655f182e905c141a22140ef9aa9e" + "reference": "f0f0d9d81a172a334c29f536500475c741a5d4c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0cc7195607bf655f182e905c141a22140ef9aa9e", - "reference": "0cc7195607bf655f182e905c141a22140ef9aa9e", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/f0f0d9d81a172a334c29f536500475c741a5d4c0", + "reference": "f0f0d9d81a172a334c29f536500475c741a5d4c0", "shasum": "" }, "require": { - "doctrine/event-manager": "^1|^2", + "doctrine/event-manager": "^1.2|^2", "doctrine/persistence": "^2|^3", - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", @@ -5806,7 +5723,7 @@ "symfony/cache": "<5.4", "symfony/dependency-injection": "<5.4", "symfony/form": "<5.4", - "symfony/http-kernel": "<5.4", + "symfony/http-kernel": "<6.2", "symfony/messenger": "<5.4", "symfony/property-info": "<5.4", "symfony/security-bundle": "<5.4", @@ -5826,7 +5743,7 @@ "symfony/doctrine-messenger": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/form": "^5.4.9|^6.0.9", - "symfony/http-kernel": "^5.4|^6.0", + "symfony/http-kernel": "^6.2", "symfony/messenger": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", @@ -5872,7 +5789,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.0.17" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.2.3" }, "funding": [ { @@ -5888,24 +5805,28 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/dotenv", - "version": "v6.0.5", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "1c2288fdfd0787288cd04b9868f879f2212159c4" + "reference": "bdc3766f31a0944cadfcdf52170ad3fb80b1540b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/1c2288fdfd0787288cd04b9868f879f2212159c4", - "reference": "1c2288fdfd0787288cd04b9868f879f2212159c4", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/bdc3766f31a0944cadfcdf52170ad3fb80b1540b", + "reference": "bdc3766f31a0944cadfcdf52170ad3fb80b1540b", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" + }, + "conflict": { + "symfony/console": "<5.4", + "symfony/process": "<5.4" }, "require-dev": { "symfony/console": "^5.4|^6.0", @@ -5942,7 +5863,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.0.5" + "source": "https://github.com/symfony/dotenv/tree/v6.2.0" }, "funding": [ { @@ -5958,24 +5879,24 @@ "type": "tidelift" } ], - "time": "2022-02-21T17:15:17+00:00" + "time": "2022-09-30T13:41:10+00:00" }, { "name": "symfony/error-handler", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "1113c4bcf3bc77a9c79562543317479c90ba7b82" + "reference": "0926124c95d220499e2baf0fb465772af3a4eddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/1113c4bcf3bc77a9c79562543317479c90ba7b82", - "reference": "1113c4bcf3bc77a9c79562543317479c90ba7b82", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0926124c95d220499e2baf0fb465772af3a4eddb", + "reference": "0926124c95d220499e2baf0fb465772af3a4eddb", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/var-dumper": "^5.4|^6.0" }, @@ -6013,7 +5934,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.0.17" + "source": "https://github.com/symfony/error-handler/tree/v6.2.3" }, "funding": [ { @@ -6029,24 +5950,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-19T14:33:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "42b3985aa07837c9df36013ec5b965e9f2d480bc" + "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/42b3985aa07837c9df36013ec5b965e9f2d480bc", - "reference": "42b3985aa07837c9df36013ec5b965e9f2d480bc", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3ffeb31139b49bf6ef0bc09d1db95eac053388d1", + "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/event-dispatcher-contracts": "^2|^3" }, "conflict": { @@ -6096,7 +6017,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.0.17" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.2" }, "funding": [ { @@ -6112,7 +6033,7 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6195,20 +6116,20 @@ }, { "name": "symfony/expression-language", - "version": "v6.0.14", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "80fc98c72206ee7caa3c427e91467d6bf48862c6" + "reference": "e558680a661eddd31f8718f968e75c9c3c8bdad1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/80fc98c72206ee7caa3c427e91467d6bf48862c6", - "reference": "80fc98c72206ee7caa3c427e91467d6bf48862c6", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/e558680a661eddd31f8718f968e75c9c3c8bdad1", + "reference": "e558680a661eddd31f8718f968e75c9c3c8bdad1", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/cache": "^5.4|^6.0", "symfony/service-contracts": "^1.1|^2|^3" }, @@ -6238,7 +6159,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.0.14" + "source": "https://github.com/symfony/expression-language/tree/v6.2.2" }, "funding": [ { @@ -6254,24 +6175,24 @@ "type": "tidelift" } ], - "time": "2022-10-07T08:02:12+00:00" + "time": "2022-12-13T15:46:14+00:00" }, { "name": "symfony/filesystem", - "version": "v6.0.13", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3adca49133bd055ebe6011ed1e012be3c908af79" + "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3adca49133bd055ebe6011ed1e012be3c908af79", - "reference": "3adca49133bd055ebe6011ed1e012be3c908af79", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/50b2523c874605cf3d4acf7a9e2b30b6a440a016", + "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, @@ -6301,7 +6222,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.0.13" + "source": "https://github.com/symfony/filesystem/tree/v6.2.0" }, "funding": [ { @@ -6317,24 +6238,27 @@ "type": "tidelift" } ], - "time": "2022-09-21T20:25:27+00:00" + "time": "2022-11-20T13:01:27+00:00" }, { "name": "symfony/finder", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d467d625fc88f7cebf96f495e588a7196a669db1" + "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d467d625fc88f7cebf96f495e588a7196a669db1", - "reference": "d467d625fc88f7cebf96f495e588a7196a669db1", + "url": "https://api.github.com/repos/symfony/finder/zipball/81eefbddfde282ee33b437ba5e13d7753211ae8e", + "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" }, "type": "library", "autoload": { @@ -6362,7 +6286,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.0.17" + "source": "https://github.com/symfony/finder/tree/v6.2.3" }, "funding": [ { @@ -6378,7 +6302,7 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:53:58+00:00" + "time": "2022-12-22T17:55:15+00:00" }, { "name": "symfony/flex", @@ -6447,27 +6371,26 @@ }, { "name": "symfony/form", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "8e16d402fc7e52c2d7b7f185a66b4f792a308546" + "reference": "fac98f69461aa8bcabe6bf254de69da892ba9b5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/8e16d402fc7e52c2d7b7f185a66b4f792a308546", - "reference": "8e16d402fc7e52c2d7b7f185a66b4f792a308546", + "url": "https://api.github.com/repos/symfony/form/zipball/fac98f69461aa8bcabe6bf254de69da892ba9b5b", + "reference": "fac98f69461aa8bcabe6bf254de69da892ba9b5b", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/options-resolver": "^5.4|^6.0", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-icu": "^1.21", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.23", "symfony/property-access": "^5.4|^6.0", "symfony/service-contracts": "^1.1|^2|^3" }, @@ -6489,9 +6412,11 @@ "symfony/console": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", + "symfony/html-sanitizer": "^6.1", "symfony/http-foundation": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", + "symfony/security-core": "^6.2", "symfony/security-csrf": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", "symfony/uid": "^5.4|^6.0", @@ -6499,6 +6424,7 @@ "symfony/var-dumper": "^5.4|^6.0" }, "suggest": { + "symfony/security-core": "For hashing users passwords.", "symfony/security-csrf": "For protecting forms against CSRF attacks.", "symfony/twig-bridge": "For templating with Twig.", "symfony/validator": "For form validation." @@ -6529,7 +6455,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v6.0.17" + "source": "https://github.com/symfony/form/tree/v6.2.3" }, "funding": [ { @@ -6545,37 +6471,37 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:21:34+00:00" + "time": "2022-12-28T14:26:22+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "76a74c36915079e80dd0d538ae3f65a205881f2b" + "reference": "c26ddbb2c2d8e5eaebbb1297b833be0967725fbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/76a74c36915079e80dd0d538ae3f65a205881f2b", - "reference": "76a74c36915079e80dd0d538ae3f65a205881f2b", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c26ddbb2c2d8e5eaebbb1297b833be0967725fbc", + "reference": "c26ddbb2c2d8e5eaebbb1297b833be0967725fbc", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.0.2", + "php": ">=8.1", "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4.5|^6.0.5", - "symfony/error-handler": "^5.4|^6.0", + "symfony/config": "^6.1", + "symfony/dependency-injection": "^6.2", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^6.1", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/filesystem": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", + "symfony/http-foundation": "^6.2", + "symfony/http-kernel": "^6.2.1", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.22", "symfony/routing": "^5.4|^6.0" }, "conflict": { @@ -6592,13 +6518,13 @@ "symfony/http-client": "<5.4", "symfony/lock": "<5.4", "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/mime": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", "symfony/property-access": "<5.4", "symfony/property-info": "<5.4", "symfony/security-core": "<5.4", "symfony/security-csrf": "<5.4", - "symfony/serializer": "<5.4", + "symfony/serializer": "<6.1", "symfony/stopwatch": "<5.4", "symfony/translation": "<5.4", "symfony/twig-bridge": "<5.4", @@ -6619,22 +6545,25 @@ "symfony/dotenv": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/form": "^5.4|^6.0", + "symfony/html-sanitizer": "^6.1", "symfony/http-client": "^5.4|^6.0", "symfony/lock": "^5.4|^6.0", "symfony/mailer": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", + "symfony/messenger": "^6.2", + "symfony/mime": "^6.2", "symfony/notifier": "^5.4|^6.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/process": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", "symfony/rate-limiter": "^5.4|^6.0", "symfony/security-bundle": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", + "symfony/semaphore": "^5.4|^6.0", + "symfony/serializer": "^6.1", "symfony/stopwatch": "^5.4|^6.0", "symfony/string": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", "symfony/twig-bundle": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", "symfony/validator": "^5.4|^6.0", "symfony/web-link": "^5.4|^6.0", "symfony/workflow": "^5.4|^6.0", @@ -6677,7 +6606,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.0.17" + "source": "https://github.com/symfony/framework-bundle/tree/v6.2.3" }, "funding": [ { @@ -6693,25 +6622,26 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/http-client", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "d104286d135d29a17ead777888087e7f0fd11771" + "reference": "7054ad466f836309aef511789b9c697bc986d8ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/d104286d135d29a17ead777888087e7f0fd11771", - "reference": "d104286d135d29a17ead777888087e7f0fd11771", + "url": "https://api.github.com/repos/symfony/http-client/zipball/7054ad466f836309aef511789b9c697bc986d8ce", + "reference": "7054ad466f836309aef511789b9c697bc986d8ce", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/http-client-contracts": "^3", "symfony/service-contracts": "^1.0|^2|^3" }, @@ -6761,7 +6691,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v6.0.17" + "source": "https://github.com/symfony/http-client/tree/v6.2.2" }, "funding": [ { @@ -6777,20 +6707,20 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.1.1", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800" + "reference": "c5f587eb445224ddfeb05b5ee703476742d730bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/fd038f08c623ab5d22b26e9ba35afe8c79071800", - "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c5f587eb445224ddfeb05b5ee703476742d730bf", + "reference": "c5f587eb445224ddfeb05b5ee703476742d730bf", "shasum": "" }, "require": { @@ -6802,7 +6732,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.1-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -6842,7 +6772,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.1.1" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.2.0" }, "funding": [ { @@ -6858,27 +6788,30 @@ "type": "tidelift" } ], - "time": "2022-04-22T07:30:54+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "22fe17e40b0481d39212e7165e004eb26422085d" + "reference": "ddf4dd35de1623e7c02013523e6c2137b67b636f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/22fe17e40b0481d39212e7165e004eb26422085d", - "reference": "22fe17e40b0481d39212e7165e004eb26422085d", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ddf4dd35de1623e7c02013523e6c2137b67b636f", + "reference": "ddf4dd35de1623e7c02013523e6c2137b67b636f", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1" }, + "conflict": { + "symfony/cache": "<6.2" + }, "require-dev": { "predis/predis": "~1.0", "symfony/cache": "^5.4|^6.0", @@ -6917,7 +6850,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.0.17" + "source": "https://github.com/symfony/http-foundation/tree/v6.2.2" }, "funding": [ { @@ -6933,26 +6866,27 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.0.18", + "version": "v6.2.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "71b52f9e5740b124894b454244fa0db48bb15814" + "reference": "74f2e638ec3fa0315443bd85fab7fc8066b77f83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/71b52f9e5740b124894b454244fa0db48bb15814", - "reference": "71b52f9e5740b124894b454244fa0db48bb15814", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/74f2e638ec3fa0315443bd85fab7fc8066b77f83", + "reference": "74f2e638ec3fa0315443bd85fab7fc8066b77f83", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/error-handler": "^5.4|^6.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^6.1", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", "symfony/polyfill-ctype": "^1.8" @@ -6960,9 +6894,9 @@ "conflict": { "symfony/browser-kit": "<5.4", "symfony/cache": "<5.4", - "symfony/config": "<5.4", + "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.2", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", @@ -6979,10 +6913,10 @@ "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", + "symfony/config": "^6.1", "symfony/console": "^5.4|^6.0", "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", + "symfony/dependency-injection": "^6.2", "symfony/dom-crawler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", @@ -6992,6 +6926,7 @@ "symfony/stopwatch": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/uid": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, "suggest": { @@ -7026,7 +6961,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.0.18" + "source": "https://github.com/symfony/http-kernel/tree/v6.2.4" }, "funding": [ { @@ -7042,27 +6977,28 @@ "type": "tidelift" } ], - "time": "2022-12-29T18:58:12+00:00" + "time": "2022-12-29T19:05:08+00:00" }, { "name": "symfony/intl", - "version": "v6.0.15", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "3377841a596c69da08086c50e09a37f2b5b1b598" + "reference": "04726ae6cec43582f7dfbfc67a313d1ecdd81c0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/3377841a596c69da08086c50e09a37f2b5b1b598", - "reference": "3377841a596c69da08086c50e09a37f2b5b1b598", + "url": "https://api.github.com/repos/symfony/intl/zipball/04726ae6cec43582f7dfbfc67a313d1ecdd81c0f", + "reference": "04726ae6cec43582f7dfbfc67a313d1ecdd81c0f", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "require-dev": { - "symfony/filesystem": "^5.4|^6.0" + "symfony/filesystem": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -7106,7 +7042,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.0.15" + "source": "https://github.com/symfony/intl/tree/v6.2.0" }, "funding": [ { @@ -7122,37 +7058,42 @@ "type": "tidelift" } ], - "time": "2022-10-23T10:33:07+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/mailer", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "0d4562cd13f1e5b78b578120ae5cbd5527ec1534" + "reference": "b355ad81f1d2987c47dcd3b04d5dce669e1e62e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/0d4562cd13f1e5b78b578120ae5cbd5527ec1534", - "reference": "0d4562cd13f1e5b78b578120ae5cbd5527ec1534", + "url": "https://api.github.com/repos/symfony/mailer/zipball/b355ad81f1d2987c47dcd3b04d5dce669e1e62e6", + "reference": "b355ad81f1d2987c47dcd3b04d5dce669e1e62e6", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3", - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", + "symfony/mime": "^6.2", "symfony/service-contracts": "^1.1|^2|^3" }, "conflict": { - "symfony/http-kernel": "<5.4" + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" }, "require-dev": { + "symfony/console": "^5.4|^6.0", "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/messenger": "^5.4|^6.0" + "symfony/messenger": "^6.2", + "symfony/twig-bridge": "^6.2" }, "type": "library", "autoload": { @@ -7180,7 +7121,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.0.17" + "source": "https://github.com/symfony/mailer/tree/v6.2.2" }, "funding": [ { @@ -7196,24 +7137,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/mime", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "3e6a7ba15997020778312ed576ad01ab60dc2336" + "reference": "8c98bf40406e791043890a163f6f6599b9cfa1ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/3e6a7ba15997020778312ed576ad01ab60dc2336", - "reference": "3e6a7ba15997020778312ed576ad01ab60dc2336", + "url": "https://api.github.com/repos/symfony/mime/zipball/8c98bf40406e791043890a163f6f6599b9cfa1ed", + "reference": "8c98bf40406e791043890a163f6f6599b9cfa1ed", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -7222,15 +7163,16 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" + "symfony/serializer": "<6.2" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" + "symfony/serializer": "^6.2" }, "type": "library", "autoload": { @@ -7262,7 +7204,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.0.17" + "source": "https://github.com/symfony/mime/tree/v6.2.2" }, "funding": [ { @@ -7278,25 +7220,25 @@ "type": "tidelift" } ], - "time": "2022-12-14T16:19:02+00:00" + "time": "2022-12-14T16:38:10+00:00" }, { "name": "symfony/monolog-bridge", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "58e36c79d0fd5fdfc7e1208adcd2209bcc5692d5" + "reference": "56172b511312a7ea9759311109df060d14b55e08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/58e36c79d0fd5fdfc7e1208adcd2209bcc5692d5", - "reference": "58e36c79d0fd5fdfc7e1208adcd2209bcc5692d5", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/56172b511312a7ea9759311109df060d14b55e08", + "reference": "56172b511312a7ea9759311109df060d14b55e08", "shasum": "" }, "require": { - "monolog/monolog": "^1.25.1|^2", - "php": ">=8.0.2", + "monolog/monolog": "^1.25.1|^2|^3", + "php": ">=8.1", "symfony/http-kernel": "^5.4|^6.0", "symfony/service-contracts": "^1.1|^2|^3" }, @@ -7345,7 +7287,7 @@ "description": "Provides integration for Monolog with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/monolog-bridge/tree/v6.0.17" + "source": "https://github.com/symfony/monolog-bridge/tree/v6.2.2" }, "funding": [ { @@ -7361,7 +7303,7 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/monolog-bundle", @@ -7446,20 +7388,20 @@ }, { "name": "symfony/options-resolver", - "version": "v6.0.3", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "51f7006670febe4cbcbae177cbffe93ff833250d" + "reference": "d28f02acde71ff75e957082cd36e973df395f626" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/51f7006670febe4cbcbae177cbffe93ff833250d", - "reference": "51f7006670febe4cbcbae177cbffe93ff833250d", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d28f02acde71ff75e957082cd36e973df395f626", + "reference": "d28f02acde71ff75e957082cd36e973df395f626", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3" }, "type": "library", @@ -7493,7 +7435,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.0.3" + "source": "https://github.com/symfony/options-resolver/tree/v6.2.0" }, "funding": [ { @@ -7509,24 +7451,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/password-hasher", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "7ff6706266cbe55310d029b42299eb6e2bebe849" + "reference": "955ce6bdbb53933897043ad00776a88ba916208a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/7ff6706266cbe55310d029b42299eb6e2bebe849", - "reference": "7ff6706266cbe55310d029b42299eb6e2bebe849", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/955ce6bdbb53933897043ad00776a88ba916208a", + "reference": "955ce6bdbb53933897043ad00776a88ba916208a", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "conflict": { "symfony/security-core": "<5.4" @@ -7565,7 +7507,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.0.11" + "source": "https://github.com/symfony/password-hasher/tree/v6.2.0" }, "funding": [ { @@ -7581,7 +7523,7 @@ "type": "tidelift" } ], - "time": "2022-07-20T14:06:08+00:00" + "time": "2022-09-01T02:03:18+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8006,20 +7948,21 @@ }, { "name": "symfony/property-access", - "version": "v6.0.15", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "bdcd636b962c10eb3575dac41cf60a704da42c89" + "reference": "9c267d87dd665d5d33e897290bbb9f64ae905b94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/bdcd636b962c10eb3575dac41cf60a704da42c89", - "reference": "bdcd636b962c10eb3575dac41cf60a704da42c89", + "url": "https://api.github.com/repos/symfony/property-access/zipball/9c267d87dd665d5d33e897290bbb9f64ae905b94", + "reference": "9c267d87dd665d5d33e897290bbb9f64ae905b94", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/property-info": "^5.4|^6.0" }, "require-dev": { @@ -8065,7 +8008,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v6.0.15" + "source": "https://github.com/symfony/property-access/tree/v6.2.3" }, "funding": [ { @@ -8081,29 +8024,29 @@ "type": "tidelift" } ], - "time": "2022-10-26T20:57:43+00:00" + "time": "2022-12-23T08:18:26+00:00" }, { "name": "symfony/property-info", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "a8593a44d1d3621c3fefd03bd6f1d10b26ca9ab2" + "reference": "b4cbbbcc8679460cfeb1d5bdcb8127a2e85c376c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/a8593a44d1d3621c3fefd03bd6f1d10b26ca9ab2", - "reference": "a8593a44d1d3621c3fefd03bd6f1d10b26ca9ab2", + "url": "https://api.github.com/repos/symfony/property-info/zipball/b4cbbbcc8679460cfeb1d5bdcb8127a2e85c376c", + "reference": "b4cbbbcc8679460cfeb1d5bdcb8127a2e85c376c", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/string": "^5.4|^6.0" }, "conflict": { "phpdocumentor/reflection-docblock": "<5.2", - "phpdocumentor/type-resolver": "<1.4.0", + "phpdocumentor/type-resolver": "<1.5.1", "symfony/dependency-injection": "<5.4" }, "require-dev": { @@ -8154,7 +8097,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.0.17" + "source": "https://github.com/symfony/property-info/tree/v6.2.3" }, "funding": [ { @@ -8170,35 +8113,35 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/routing", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "61687a0aa80f6807c52e116ee64072f6ec53780c" + "reference": "35fec764f3e2c8c08fb340d275c84bc78ca7e0c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/61687a0aa80f6807c52e116ee64072f6ec53780c", - "reference": "61687a0aa80f6807c52e116ee64072f6ec53780c", + "url": "https://api.github.com/repos/symfony/routing/zipball/35fec764f3e2c8c08fb340d275c84bc78ca7e0c9", + "reference": "35fec764f3e2c8c08fb340d275c84bc78ca7e0c9", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "conflict": { "doctrine/annotations": "<1.12", - "symfony/config": "<5.4", + "symfony/config": "<6.2", "symfony/dependency-injection": "<5.4", "symfony/yaml": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", + "symfony/config": "^6.2", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", @@ -8242,7 +8185,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.0.17" + "source": "https://github.com/symfony/routing/tree/v6.2.3" }, "funding": [ { @@ -8258,25 +8201,25 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/runtime", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "88813c1735d9ce6e1a7cccf63d6f2b6faca79018" + "reference": "45a63a5885f92741c8def9cbd81c925e6b5b891d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/88813c1735d9ce6e1a7cccf63d6f2b6faca79018", - "reference": "88813c1735d9ce6e1a7cccf63d6f2b6faca79018", + "url": "https://api.github.com/repos/symfony/runtime/zipball/45a63a5885f92741c8def9cbd81c925e6b5b891d", + "reference": "45a63a5885f92741c8def9cbd81c925e6b5b891d", "shasum": "" }, "require": { "composer-plugin-api": "^1.0|^2.0", - "php": ">=8.0.2" + "php": ">=8.1" }, "conflict": { "symfony/dotenv": "<5.4" @@ -8318,7 +8261,7 @@ "description": "Enables decoupling PHP applications from global state", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/runtime/tree/v6.0.11" + "source": "https://github.com/symfony/runtime/tree/v6.2.0" }, "funding": [ { @@ -8334,35 +8277,35 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/security-bundle", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "2973e1f2b8af2c85bca230bfe383642a6daaa3d8" + "reference": "313c1c65828b0524a5e5e590d667890d55964ebe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/2973e1f2b8af2c85bca230bfe383642a6daaa3d8", - "reference": "2973e1f2b8af2c85bca230bfe383642a6daaa3d8", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/313c1c65828b0524a5e5e590d667890d55964ebe", + "reference": "313c1c65828b0524a5e5e590d667890d55964ebe", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.0.2", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", + "php": ">=8.1", + "symfony/config": "^6.1", + "symfony/dependency-injection": "^6.2", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", + "symfony/http-foundation": "^6.2", + "symfony/http-kernel": "^6.2", "symfony/password-hasher": "^5.4|^6.0", - "symfony/security-core": "^5.4|^6.0", + "symfony/security-core": "^6.2", "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^5.4|^6.0" + "symfony/security-http": "^6.2" }, "conflict": { "symfony/browser-kit": "<5.4", @@ -8418,7 +8361,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.0.17" + "source": "https://github.com/symfony/security-bundle/tree/v6.2.3" }, "funding": [ { @@ -8434,24 +8377,24 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-21T09:01:37+00:00" }, { "name": "symfony/security-core", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "544a1f6428490bb2ed71559a6ae5d2939346d291" + "reference": "c03a0dae81e0afca9b6e70e25f1813999fcd8c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/544a1f6428490bb2ed71559a6ae5d2939346d291", - "reference": "544a1f6428490bb2ed71559a6ae5d2939346d291", + "url": "https://api.github.com/repos/symfony/security-core/zipball/c03a0dae81e0afca9b6e70e25f1813999fcd8c75", + "reference": "c03a0dae81e0afca9b6e70e25f1813999fcd8c75", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/event-dispatcher-contracts": "^1.1|^2|^3", "symfony/password-hasher": "^5.4|^6.0", "symfony/service-contracts": "^1.1.6|^2|^3" @@ -8509,7 +8452,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.0.17" + "source": "https://github.com/symfony/security-core/tree/v6.2.2" }, "funding": [ { @@ -8525,24 +8468,24 @@ "type": "tidelift" } ], - "time": "2022-12-09T07:42:08+00:00" + "time": "2022-12-09T17:05:11+00:00" }, { "name": "symfony/security-csrf", - "version": "v6.0.9", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "5a48bfb3ba3a4e139d8184ca1005c00d8b8e4dc0" + "reference": "12d6ef4695f522566639e58b929d90e25b509379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/5a48bfb3ba3a4e139d8184ca1005c00d8b8e4dc0", - "reference": "5a48bfb3ba3a4e139d8184ca1005c00d8b8e4dc0", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/12d6ef4695f522566639e58b929d90e25b509379", + "reference": "12d6ef4695f522566639e58b929d90e25b509379", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/security-core": "^5.4|^6.0" }, "conflict": { @@ -8580,7 +8523,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v6.0.9" + "source": "https://github.com/symfony/security-csrf/tree/v6.2.0" }, "funding": [ { @@ -8596,38 +8539,40 @@ "type": "tidelift" } ], - "time": "2022-05-14T12:52:12+00:00" + "time": "2022-11-21T18:36:40+00:00" }, { "name": "symfony/security-http", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "feeeebb645cb886d90fe47612531cf4253b963dd" + "reference": "9f8712ce90d97b7a7cc20c1ac354a0da44cd4831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/feeeebb645cb886d90fe47612531cf4253b963dd", - "reference": "feeeebb645cb886d90fe47612531cf4253b963dd", + "url": "https://api.github.com/repos/symfony/security-http/zipball/9f8712ce90d97b7a7cc20c1ac354a0da44cd4831", + "reference": "9f8712ce90d97b7a7cc20c1ac354a0da44cd4831", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", + "symfony/http-kernel": "^6.2", "symfony/polyfill-mbstring": "~1.0", "symfony/property-access": "^5.4|^6.0", - "symfony/security-core": "^5.4|^6.0" + "symfony/security-core": "^6.0" }, "conflict": { - "symfony/event-dispatcher": "<5.4", + "symfony/event-dispatcher": "<5.4.9|>=6,<6.0.9", "symfony/security-bundle": "<5.4", "symfony/security-csrf": "<5.4" }, "require-dev": { "psr/log": "^1|^2|^3", "symfony/cache": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", "symfony/rate-limiter": "^5.4|^6.0", "symfony/routing": "^5.4|^6.0", "symfony/security-csrf": "^5.4|^6.0", @@ -8663,7 +8608,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.0.17" + "source": "https://github.com/symfony/security-http/tree/v6.2.2" }, "funding": [ { @@ -8679,24 +8624,24 @@ "type": "tidelift" } ], - "time": "2022-11-30T17:16:57+00:00" + "time": "2022-12-13T14:55:03+00:00" }, { "name": "symfony/serializer", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "65545e9a05d9aa86d1e8c1fedccf4d0e532c5b71" + "reference": "9cb1e8fd22f9ff40b9580ae822f44c13317ddb20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/65545e9a05d9aa86d1e8c1fedccf4d0e532c5b71", - "reference": "65545e9a05d9aa86d1e8c1fedccf4d0e532c5b71", + "url": "https://api.github.com/repos/symfony/serializer/zipball/9cb1e8fd22f9ff40b9580ae822f44c13317ddb20", + "reference": "9cb1e8fd22f9ff40b9580ae822f44c13317ddb20", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -8764,7 +8709,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.0.17" + "source": "https://github.com/symfony/serializer/tree/v6.2.3" }, "funding": [ { @@ -8780,7 +8725,7 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/service-contracts", @@ -8869,20 +8814,20 @@ }, { "name": "symfony/stopwatch", - "version": "v6.0.13", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "7554fde6848af5ef1178f8ccbdbdb8ae1092c70a" + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/7554fde6848af5ef1178f8ccbdbdb8ae1092c70a", - "reference": "7554fde6848af5ef1178f8ccbdbdb8ae1092c70a", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/service-contracts": "^1|^2|^3" }, "type": "library", @@ -8911,7 +8856,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.0.13" + "source": "https://github.com/symfony/stopwatch/tree/v6.2.0" }, "funding": [ { @@ -8927,24 +8872,24 @@ "type": "tidelift" } ], - "time": "2022-09-28T15:52:47+00:00" + "time": "2022-09-28T16:00:52+00:00" }, { "name": "symfony/string", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "3f57003dd8a67ed76870cc03092f8501db7788d9" + "reference": "863219fd713fa41cbcd285a79723f94672faff4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/3f57003dd8a67ed76870cc03092f8501db7788d9", - "reference": "3f57003dd8a67ed76870cc03092f8501db7788d9", + "url": "https://api.github.com/repos/symfony/string/zipball/863219fd713fa41cbcd285a79723f94672faff4d", + "reference": "863219fd713fa41cbcd285a79723f94672faff4d", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -8956,6 +8901,7 @@ "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", "symfony/translation-contracts": "^2.0|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, @@ -8996,7 +8942,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.17" + "source": "https://github.com/symfony/string/tree/v6.2.2" }, "funding": [ { @@ -9012,24 +8958,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/translation", - "version": "v6.0.14", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6f99eb179aee4652c0a7cd7c11f2a870d904330c" + "reference": "a2a15404ef4c15d92c205718eb828b225a144379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6f99eb179aee4652c0a7cd7c11f2a870d904330c", - "reference": "6f99eb179aee4652c0a7cd7c11f2a870d904330c", + "url": "https://api.github.com/repos/symfony/translation/zipball/a2a15404ef4c15d92c205718eb828b225a144379", + "reference": "a2a15404ef4c15d92c205718eb828b225a144379", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^2.3|^3.0" }, @@ -9045,6 +8991,7 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.13", "psr/log": "^1|^2|^3", "symfony/config": "^5.4|^6.0", "symfony/console": "^5.4|^6.0", @@ -9054,10 +9001,12 @@ "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0", "symfony/service-contracts": "^1.1.2|^2|^3", "symfony/yaml": "^5.4|^6.0" }, "suggest": { + "nikic/php-parser": "To use PhpAstExtractor", "psr/log-implementation": "To use logging capability in translator", "symfony/config": "", "symfony/yaml": "" @@ -9091,7 +9040,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.14" + "source": "https://github.com/symfony/translation/tree/v6.2.3" }, "funding": [ { @@ -9107,7 +9056,7 @@ "type": "tidelift" } ], - "time": "2022-10-07T08:02:12+00:00" + "time": "2022-12-23T14:11:11+00:00" }, { "name": "symfony/translation-contracts", @@ -9192,20 +9141,20 @@ }, { "name": "symfony/twig-bridge", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "b2ba5c7bdeb7ec3fb8597cfc82a0e5c42535c1fe" + "reference": "f3b60bbbe23308fd7b5f99ad480a1852acfd4d65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/b2ba5c7bdeb7ec3fb8597cfc82a0e5c42535c1fe", - "reference": "b2ba5c7bdeb7ec3fb8597cfc82a0e5c42535c1fe", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/f3b60bbbe23308fd7b5f99ad480a1852acfd4d65", + "reference": "f3b60bbbe23308fd7b5f99ad480a1852acfd4d65", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/translation-contracts": "^1.1|^2|^3", "twig/twig": "^2.13|^3.0.4" }, @@ -9213,26 +9162,29 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/console": "<5.4", - "symfony/form": "<5.4", + "symfony/form": "<6.1", "symfony/http-foundation": "<5.4", - "symfony/http-kernel": "<5.4", + "symfony/http-kernel": "<6.2", + "symfony/mime": "<6.2", "symfony/translation": "<5.4", "symfony/workflow": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.12|^2", "egulias/email-validator": "^2.1.10|^3", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/asset": "^5.4|^6.0", "symfony/console": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", + "symfony/form": "^6.1", + "symfony/html-sanitizer": "^6.1", "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", + "symfony/http-kernel": "^6.2", "symfony/intl": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", + "symfony/mime": "^6.2", "symfony/polyfill-intl-icu": "~1.0", "symfony/property-info": "^5.4|^6.0", "symfony/routing": "^5.4|^6.0", @@ -9240,7 +9192,7 @@ "symfony/security-core": "^5.4|^6.0", "symfony/security-csrf": "^5.4|^6.0", "symfony/security-http": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", + "symfony/serializer": "^6.2", "symfony/stopwatch": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", "symfony/web-link": "^5.4|^6.0", @@ -9255,6 +9207,7 @@ "symfony/expression-language": "For using the ExpressionExtension", "symfony/finder": "", "symfony/form": "For using the FormExtension", + "symfony/html-sanitizer": "For using the HtmlSanitizerExtension", "symfony/http-kernel": "For using the HttpKernelExtension", "symfony/routing": "For using the RoutingExtension", "symfony/security-core": "For using the SecurityExtension", @@ -9292,7 +9245,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.0.17" + "source": "https://github.com/symfony/twig-bridge/tree/v6.2.3" }, "funding": [ { @@ -9308,41 +9261,39 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/twig-bundle", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "97ef8de536976ac13d34806624853a4ab1554a91" + "reference": "6d32d5f8f36a543663e9db6aa4aefd184f492883" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/97ef8de536976ac13d34806624853a4ab1554a91", - "reference": "97ef8de536976ac13d34806624853a4ab1554a91", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/6d32d5f8f36a543663e9db6aa4aefd184f492883", + "reference": "6d32d5f8f36a543663e9db6aa4aefd184f492883", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", - "php": ">=8.0.2", - "symfony/config": "^5.4|^6.0", + "php": ">=8.1", + "symfony/config": "^6.1", + "symfony/dependency-injection": "^6.1", "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/twig-bridge": "^5.4|^6.0", + "symfony/http-kernel": "^6.2", + "symfony/twig-bridge": "^6.2", "twig/twig": "^2.13|^3.0.4" }, "conflict": { - "symfony/dependency-injection": "<5.4", "symfony/framework-bundle": "<5.4", "symfony/translation": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.10.4|^2", "symfony/asset": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", "symfony/form": "^5.4|^6.0", @@ -9379,7 +9330,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.0.17" + "source": "https://github.com/symfony/twig-bundle/tree/v6.2.3" }, "funding": [ { @@ -9395,27 +9346,27 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/validator", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "c61685fe00eeedebda629c394bce75d1d0d34398" + "reference": "bd44a9ae3b19ae81c723b5a5fff6a1a36844ee01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/c61685fe00eeedebda629c394bce75d1d0d34398", - "reference": "c61685fe00eeedebda629c394bce75d1d0d34398", + "url": "https://api.github.com/repos/symfony/validator/zipball/bd44a9ae3b19ae81c723b5a5fff6a1a36844ee01", + "reference": "bd44a9ae3b19ae81c723b5a5fff6a1a36844ee01", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.22", "symfony/translation-contracts": "^1.1|^2|^3" }, "conflict": { @@ -9487,7 +9438,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.0.17" + "source": "https://github.com/symfony/validator/tree/v6.2.3" }, "funding": [ { @@ -9503,24 +9454,24 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:53:58+00:00" + "time": "2022-12-22T17:55:15+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7d8e7c3c67c77790425ebe33691419dada154e65" + "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7d8e7c3c67c77790425ebe33691419dada154e65", - "reference": "7d8e7c3c67c77790425ebe33691419dada154e65", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0", + "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -9575,7 +9526,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.0.17" + "source": "https://github.com/symfony/var-dumper/tree/v6.2.3" }, "funding": [ { @@ -9591,24 +9542,24 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:53:58+00:00" + "time": "2022-12-22T17:55:15+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "d87c15d59421d38fe5eb4f6724eb75891479e3da" + "reference": "d055d12b20b42e407e607460e7552a1fe6d27f08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/d87c15d59421d38fe5eb4f6724eb75891479e3da", - "reference": "d87c15d59421d38fe5eb4f6724eb75891479e3da", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/d055d12b20b42e407e607460e7552a1fe6d27f08", + "reference": "d055d12b20b42e407e607460e7552a1fe6d27f08", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "require-dev": { "symfony/var-dumper": "^5.4|^6.0" @@ -9644,10 +9595,12 @@ "export", "hydrate", "instantiate", + "lazy loading", + "proxy", "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.0.17" + "source": "https://github.com/symfony/var-exporter/tree/v6.2.3" }, "funding": [ { @@ -9663,7 +9616,7 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:53:58+00:00" + "time": "2022-12-22T17:55:15+00:00" }, { "name": "symfony/webpack-encore-bundle", @@ -9740,20 +9693,20 @@ }, { "name": "symfony/yaml", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "76c08913ea1c50541503a4563b2172710189fa29" + "reference": "6ed8243aa5f2cb5a57009f826b5e7fb3c4200cf3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/76c08913ea1c50541503a4563b2172710189fa29", - "reference": "76c08913ea1c50541503a4563b2172710189fa29", + "url": "https://api.github.com/repos/symfony/yaml/zipball/6ed8243aa5f2cb5a57009f826b5e7fb3c4200cf3", + "reference": "6ed8243aa5f2cb5a57009f826b5e7fb3c4200cf3", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -9794,7 +9747,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.0.17" + "source": "https://github.com/symfony/yaml/tree/v6.2.2" }, "funding": [ { @@ -9810,7 +9763,7 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -10461,16 +10414,16 @@ }, { "name": "zircote/swagger-php", - "version": "4.5.4", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "09356f4d68d29bdf3254811fb2602a5d5d1788ea" + "reference": "ee8147745c92dd4404adb531751ce32676b888d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/09356f4d68d29bdf3254811fb2602a5d5d1788ea", - "reference": "09356f4d68d29bdf3254811fb2602a5d5d1788ea", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/ee8147745c92dd4404adb531751ce32676b888d4", + "reference": "ee8147745c92dd4404adb531751ce32676b888d4", "shasum": "" }, "require": { @@ -10533,9 +10486,9 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/4.5.4" + "source": "https://github.com/zircote/swagger-php/tree/4.6.0" }, - "time": "2023-01-04T00:51:43+00:00" + "time": "2023-01-13T00:51:01+00:00" } ], "packages-dev": [ @@ -10745,16 +10698,16 @@ }, { "name": "doctrine/data-fixtures", - "version": "1.6.2", + "version": "1.6.3", "source": { "type": "git", "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "d52cc6d392717734fac908768a7319f8a417401a" + "reference": "c27821d038e64f1bfc852a94064d65d2a75ad01f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/d52cc6d392717734fac908768a7319f8a417401a", - "reference": "d52cc6d392717734fac908768a7319f8a417401a", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/c27821d038e64f1bfc852a94064d65d2a75ad01f", + "reference": "c27821d038e64f1bfc852a94064d65d2a75ad01f", "shasum": "" }, "require": { @@ -10807,7 +10760,7 @@ ], "support": { "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/1.6.2" + "source": "https://github.com/doctrine/data-fixtures/tree/1.6.3" }, "funding": [ { @@ -10823,7 +10776,7 @@ "type": "tidelift" } ], - "time": "2023-01-05T18:42:27+00:00" + "time": "2023-01-07T15:10:22+00:00" }, { "name": "doctrine/doctrine-fixtures-bundle", @@ -11066,17 +11019,86 @@ "time": "2023-01-02T23:53:50+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.15.2", + "name": "masterminds/html5", + "version": "2.7.6", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc" + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "897eb517a343a2281f11bc5556d6548db7d93947" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", - "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/897eb517a343a2281f11bc5556d6548db7d93947", + "reference": "897eb517a343a2281f11bc5556d6548db7d93947", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-libxml": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.7.6" + }, + "time": "2022-08-18T16:18:26+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.3", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", "shasum": "" }, "require": { @@ -11117,9 +11139,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" }, - "time": "2022-11-12T15:38:23+00:00" + "time": "2023-01-16T22:05:37+00:00" }, { "name": "phar-io/manifest", @@ -11234,16 +11256,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.9.7", + "version": "1.9.12", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "0501435cd342eac7664bd62155b1ef907fc60b6f" + "reference": "44a338ff0d5572c13fd77dfd91addb96e48c29f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0501435cd342eac7664bd62155b1ef907fc60b6f", - "reference": "0501435cd342eac7664bd62155b1ef907fc60b6f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/44a338ff0d5572c13fd77dfd91addb96e48c29f8", + "reference": "44a338ff0d5572c13fd77dfd91addb96e48c29f8", "shasum": "" }, "require": { @@ -11273,7 +11295,7 @@ ], "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.9.7" + "source": "https://github.com/phpstan/phpstan/tree/1.9.12" }, "funding": [ { @@ -11289,25 +11311,25 @@ "type": "tidelift" } ], - "time": "2023-01-04T21:59:57+00:00" + "time": "2023-01-17T10:44:04+00:00" }, { "name": "phpstan/phpstan-doctrine", - "version": "1.3.29", + "version": "1.3.32", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-doctrine.git", - "reference": "4967ebbc24a2d7e94f5b2f6dad78e0087dd52fc3" + "reference": "4534559a8c08ab3648c6fa09289478780e190ae7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/4967ebbc24a2d7e94f5b2f6dad78e0087dd52fc3", - "reference": "4967ebbc24a2d7e94f5b2f6dad78e0087dd52fc3", + "url": "https://api.github.com/repos/phpstan/phpstan-doctrine/zipball/4534559a8c08ab3648c6fa09289478780e190ae7", + "reference": "4534559a8c08ab3648c6fa09289478780e190ae7", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.9.7" + "phpstan/phpstan": "^1.9.11" }, "conflict": { "doctrine/collections": "<1.0", @@ -11317,6 +11339,7 @@ "doctrine/persistence": "<1.3" }, "require-dev": { + "composer/semver": "^3.3.2", "doctrine/annotations": "^1.11.0", "doctrine/collections": "^1.6", "doctrine/common": "^2.7 || ^3.0", @@ -11356,9 +11379,9 @@ "description": "Doctrine extensions for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-doctrine/issues", - "source": "https://github.com/phpstan/phpstan-doctrine/tree/1.3.29" + "source": "https://github.com/phpstan/phpstan-doctrine/tree/1.3.32" }, - "time": "2023-01-04T21:51:32+00:00" + "time": "2023-01-12T13:39:08+00:00" }, { "name": "phpstan/phpstan-phpunit", @@ -11414,21 +11437,21 @@ }, { "name": "phpstan/phpstan-strict-rules", - "version": "1.4.4", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-strict-rules.git", - "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6" + "reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", - "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d", + "reference": "361f75b06066f3fdaba87c1f57bdb1ffc28d6f1d", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", - "phpstan/phpstan": "^1.8.6" + "phpstan/phpstan": "^1.9.7" }, "require-dev": { "nikic/php-parser": "^4.13.0", @@ -11456,22 +11479,22 @@ "description": "Extra strict and opinionated rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", - "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4" + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.5" }, - "time": "2022-09-21T11:38:17+00:00" + "time": "2023-01-11T14:16:29+00:00" }, { "name": "phpstan/phpstan-symfony", - "version": "1.2.19", + "version": "1.2.20", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-symfony.git", - "reference": "dac2474904b092267f0a19dfba8c46b6f21eab6a" + "reference": "d89a521e7e31822409bf37f70691f7a12a6e7d76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/dac2474904b092267f0a19dfba8c46b6f21eab6a", - "reference": "dac2474904b092267f0a19dfba8c46b6f21eab6a", + "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/d89a521e7e31822409bf37f70691f7a12a6e7d76", + "reference": "d89a521e7e31822409bf37f70691f7a12a6e7d76", "shasum": "" }, "require": { @@ -11527,9 +11550,9 @@ "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.2.19" + "source": "https://github.com/phpstan/phpstan-symfony/tree/1.2.20" }, - "time": "2022-12-22T20:05:46+00:00" + "time": "2023-01-15T12:28:31+00:00" }, { "name": "phpunit/php-code-coverage", @@ -11851,20 +11874,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.27", + "version": "9.5.28", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38" + "reference": "954ca3113a03bf780d22f07bf055d883ee04b65e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38", - "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/954ca3113a03bf780d22f07bf055d883ee04b65e", + "reference": "954ca3113a03bf780d22f07bf055d883ee04b65e", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -11933,7 +11956,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.28" }, "funding": [ { @@ -11949,7 +11972,7 @@ "type": "tidelift" } ], - "time": "2022-12-09T07:31:23+00:00" + "time": "2023-01-14T12:32:24+00:00" }, { "name": "sebastian/cli-parser", @@ -12917,20 +12940,20 @@ }, { "name": "symfony/browser-kit", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "92e4b59bf2ef0f7a01d2620c4c87108e5c143d36" + "reference": "5602fcc9a2a696f1743050ffcafa30741da94227" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/92e4b59bf2ef0f7a01d2620c4c87108e5c143d36", - "reference": "92e4b59bf2ef0f7a01d2620c4c87108e5c143d36", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/5602fcc9a2a696f1743050ffcafa30741da94227", + "reference": "5602fcc9a2a696f1743050ffcafa30741da94227", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/dom-crawler": "^5.4|^6.0" }, "require-dev": { @@ -12968,7 +12991,7 @@ "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/browser-kit/tree/v6.0.11" + "source": "https://github.com/symfony/browser-kit/tree/v6.2.0" }, "funding": [ { @@ -12984,25 +13007,26 @@ "type": "tidelift" } ], - "time": "2022-07-27T15:50:26+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/debug-bundle", - "version": "v6.0.11", + "version": "v6.2.1", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "78426ad77ab9d2429e20354bf7dc56c966205848" + "reference": "d87ef905baa453646a6e633690c184998e573e10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/78426ad77ab9d2429e20354bf7dc56c966205848", - "reference": "78426ad77ab9d2429e20354bf7dc56c966205848", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/d87ef905baa453646a6e633690c184998e573e10", + "reference": "d87ef905baa453646a6e633690c184998e573e10", "shasum": "" }, "require": { "ext-xml": "*", - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/twig-bridge": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" @@ -13013,7 +13037,6 @@ }, "require-dev": { "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", "symfony/web-profiler-bundle": "^5.4|^6.0" }, "suggest": { @@ -13046,7 +13069,7 @@ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v6.0.11" + "source": "https://github.com/symfony/debug-bundle/tree/v6.2.1" }, "funding": [ { @@ -13062,32 +13085,29 @@ "type": "tidelift" } ], - "time": "2022-07-20T13:45:53+00:00" + "time": "2022-12-05T06:41:34+00:00" }, { "name": "symfony/dom-crawler", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "281d13dfd1a2ac4ca8be8c60b0af208ffdac95fe" + "reference": "f2743e033dd05a62978ced0ad368022e82c9fab2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/281d13dfd1a2ac4ca8be8c60b0af208ffdac95fe", - "reference": "281d13dfd1a2ac4ca8be8c60b0af208ffdac95fe", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f2743e033dd05a62978ced0ad368022e82c9fab2", + "reference": "f2743e033dd05a62978ced0ad368022e82c9fab2", "shasum": "" }, "require": { - "php": ">=8.0.2", + "masterminds/html5": "^2.6", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, - "conflict": { - "masterminds/html5": "<2.6" - }, "require-dev": { - "masterminds/html5": "^2.6", "symfony/css-selector": "^5.4|^6.0" }, "suggest": { @@ -13119,7 +13139,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.0.17" + "source": "https://github.com/symfony/dom-crawler/tree/v6.2.3" }, "funding": [ { @@ -13135,7 +13155,7 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:53:58+00:00" + "time": "2022-12-22T17:55:15+00:00" }, { "name": "symfony/phpunit-bridge", @@ -13222,20 +13242,20 @@ }, { "name": "symfony/process", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "44270a08ccb664143dede554ff1c00aaa2247a43" + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/44270a08ccb664143dede554ff1c00aaa2247a43", - "reference": "44270a08ccb664143dede554ff1c00aaa2247a43", + "url": "https://api.github.com/repos/symfony/process/zipball/ba6e55359f8f755fe996c58a81e00eaa67a35877", + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -13263,7 +13283,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.0.11" + "source": "https://github.com/symfony/process/tree/v6.2.0" }, "funding": [ { @@ -13279,33 +13299,32 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.0.17", + "version": "v6.2.4", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "d970ba52d542186cdf8b592eb36a157a025d2d76" + "reference": "1c5f690bf54593ff4d3170cf6b47d76cedb557b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/d970ba52d542186cdf8b592eb36a157a025d2d76", - "reference": "d970ba52d542186cdf8b592eb36a157a025d2d76", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/1c5f690bf54593ff4d3170cf6b47d76cedb557b9", + "reference": "1c5f690bf54593ff4d3170cf6b47d76cedb557b9", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/config": "^5.4|^6.0", "symfony/framework-bundle": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", + "symfony/http-kernel": "^6.1", "symfony/routing": "^5.4|^6.0", "symfony/twig-bundle": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, "conflict": { - "symfony/dependency-injection": "<5.4", "symfony/form": "<5.4", "symfony/mailer": "<5.4", "symfony/messenger": "<5.4" @@ -13342,7 +13361,7 @@ "description": "Provides a development tool that gives detailed information about the execution of any request", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.0.17" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.2.4" }, "funding": [ { @@ -13358,7 +13377,7 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-29T18:33:43+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/bundles.php b/config/bundles.php index 6413f639a..6b8d787c1 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -5,7 +5,6 @@ return [ Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], - Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], diff --git a/config/packages/fos_rest.yaml b/config/packages/fos_rest.yaml index ff1fa125e..4ef939b25 100644 --- a/config/packages/fos_rest.yaml +++ b/config/packages/fos_rest.yaml @@ -4,7 +4,7 @@ fos_rest: cache_dir: '%kernel.cache_dir%/fos_rest' routing_loader: false body_converter: - enabled: true + enabled: false serializer: serialize_null: true view: diff --git a/config/packages/nelmio_api_doc.yaml b/config/packages/nelmio_api_doc.yaml index f5b42a7f6..7525577f9 100644 --- a/config/packages/nelmio_api_doc.yaml +++ b/config/packages/nelmio_api_doc.yaml @@ -63,4 +63,4 @@ nelmio_api_doc: in: header security: - X-AUTH-USER: [] - - X-AUTH-TOKEN: [] + X-AUTH-TOKEN: [] diff --git a/config/packages/sensio_framework_extra.yaml b/config/packages/sensio_framework_extra.yaml deleted file mode 100644 index 1821ccc07..000000000 --- a/config/packages/sensio_framework_extra.yaml +++ /dev/null @@ -1,3 +0,0 @@ -sensio_framework_extra: - router: - annotations: false diff --git a/phpstan.neon b/phpstan.neon index 0d8ff59ec..4d6ee9919 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2075,16 +2075,6 @@ parameters: count: 1 path: src/DataFixtures/TeamFixtures.php - - - message: "#^Cannot access offset 1 on mixed\\.$#" - count: 1 - path: src/DataFixtures/TimesheetFixtures.php - - - - message: "#^Cannot access offset 2 on mixed\\.$#" - count: 1 - path: src/DataFixtures/TimesheetFixtures.php - - message: "#^Cannot call method setTimestamp\\(\\) on DateTime\\|null\\.$#" count: 1 @@ -2095,51 +2085,21 @@ parameters: count: 1 path: src/DataFixtures/TimesheetFixtures.php - - - message: "#^Method App\\\\DataFixtures\\\\TimesheetFixtures\\:\\:createTimesheetEntry\\(\\) has no return type specified\\.$#" - count: 1 - path: src/DataFixtures/TimesheetFixtures.php - - - - message: "#^Method App\\\\DataFixtures\\\\TimesheetFixtures\\:\\:findRandom\\(\\) has no return type specified\\.$#" - count: 1 - path: src/DataFixtures/TimesheetFixtures.php - - message: "#^Parameter \\#1 \\$begin of method App\\\\Entity\\\\Timesheet\\:\\:setBegin\\(\\) expects DateTime, DateTime\\|null given\\.$#" count: 1 path: src/DataFixtures/TimesheetFixtures.php - - - message: "#^Parameter \\#1 \\$className of method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getRepository\\(\\) expects class\\-string\\, string given\\.$#" - count: 2 - path: src/DataFixtures/TimesheetFixtures.php - - message: "#^Parameter \\#1 \\$description of method App\\\\Entity\\\\Timesheet\\:\\:setDescription\\(\\) expects string, string\\|null given\\.$#" count: 1 path: src/DataFixtures/TimesheetFixtures.php - - - message: "#^Parameter \\#1 \\$min of function rand expects int, mixed given\\.$#" - count: 1 - path: src/DataFixtures/TimesheetFixtures.php - - message: "#^Parameter \\#1 \\$user of method App\\\\DataFixtures\\\\TimesheetFixtures\\:\\:createTimesheetEntry\\(\\) expects App\\\\Entity\\\\User, App\\\\Entity\\\\User\\|null given\\.$#" count: 2 path: src/DataFixtures/TimesheetFixtures.php - - - message: "#^Parameter \\#2 \\$max of function rand expects int, mixed given\\.$#" - count: 1 - path: src/DataFixtures/TimesheetFixtures.php - - - - message: "#^Unable to resolve the template type T in call to method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getRepository\\(\\)$#" - count: 2 - path: src/DataFixtures/TimesheetFixtures.php - - message: "#^Method App\\\\DataFixtures\\\\UserFixtures\\:\\:getUserDefinition\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 @@ -2150,16 +2110,6 @@ parameters: count: 1 path: src/DataFixtures/UserFixtures.php - - - message: "#^Method App\\\\DataFixtures\\\\UserFixtures\\:\\:loadDefaultAccounts\\(\\) has no return type specified\\.$#" - count: 1 - path: src/DataFixtures/UserFixtures.php - - - - message: "#^Method App\\\\DataFixtures\\\\UserFixtures\\:\\:loadTestUsers\\(\\) has no return type specified\\.$#" - count: 1 - path: src/DataFixtures/UserFixtures.php - - message: "#^Method App\\\\DependencyInjection\\\\AppExtension\\:\\:createPermissionParameter\\(\\) has parameter \\$config with no value type specified in iterable type array\\.$#" count: 1 diff --git a/src/API/ActionsController.php b/src/API/ActionsController.php index 4c84655d0..1466ce493 100644 --- a/src/API/ActionsController.php +++ b/src/API/ActionsController.php @@ -21,14 +21,14 @@ use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Contracts\Translation\TranslatorInterface; #[Route(path: '/actions')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Actions')] final class ActionsController extends BaseApiController { diff --git a/src/API/ActivityController.php b/src/API/ActivityController.php index 0907c212c..8e2254194 100644 --- a/src/API/ActivityController.php +++ b/src/API/ActivityController.php @@ -26,15 +26,15 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/activities')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Activity')] final class ActivityController extends BaseApiController { @@ -179,7 +179,7 @@ final class ActivityController extends BaseApiController /** * Update an existing activity */ - #[Security("is_granted('edit', activity)")] + #[IsGranted('edit', 'activity')] #[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)] @@ -217,7 +217,7 @@ final class ActivityController extends BaseApiController /** * Sets the value of a meta-field for an existing activity */ - #[Security("is_granted('edit', activity)")] + #[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+'])] @@ -250,7 +250,7 @@ final class ActivityController extends BaseApiController /** * Returns a collection of all rates for one activity */ - #[Security("is_granted('edit', activity)")] + #[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+'])] @@ -269,15 +269,14 @@ final class ActivityController extends BaseApiController /** * Deletes one rate for an activity */ - #[Security("is_granted('edit', activity)")] + #[IsGranted('edit', 'activity')] #[OA\Delete(responses: [new OA\Response(response: 204, description: 'Returns no content: 204 on successful delete')])] #[OA\Parameter(name: 'id', in: 'path', description: 'The activity whose rate will be removed', required: true)] #[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+'])] - #[Entity('rate', expr: 'repository.find(rateId)')] - public function deleteRateAction(Activity $activity, ActivityRate $rate): Response + public function deleteRateAction(Activity $activity, #[MapEntity(mapping: ['rateId' => 'id'])] ActivityRate $rate): Response { if ($rate->getActivity() !== $activity) { throw $this->createNotFoundException(); @@ -293,7 +292,7 @@ final class ActivityController extends BaseApiController /** * Adds a new rate to an activity */ - #[Security("is_granted('edit', activity)")] + #[IsGranted('edit', 'activity')] #[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'))] diff --git a/src/API/ConfigurationController.php b/src/API/ConfigurationController.php index 2b844fe3e..6db094d5a 100644 --- a/src/API/ConfigurationController.php +++ b/src/API/ConfigurationController.php @@ -17,10 +17,10 @@ use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Default')] final class ConfigurationController extends BaseApiController { diff --git a/src/API/CustomerController.php b/src/API/CustomerController.php index 0a531b374..4341957c5 100644 --- a/src/API/CustomerController.php +++ b/src/API/CustomerController.php @@ -26,15 +26,15 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/customers')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Customer')] final class CustomerController extends BaseApiController { @@ -156,7 +156,7 @@ final class CustomerController extends BaseApiController /** * Update an existing customer */ - #[Security("is_granted('edit', customer)")] + #[IsGranted('edit', 'customer')] #[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)] @@ -194,7 +194,7 @@ final class CustomerController extends BaseApiController /** * Sets the value of a meta-field for an existing customer */ - #[Security("is_granted('edit', customer)")] + #[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+'])] @@ -227,7 +227,7 @@ final class CustomerController extends BaseApiController /** * Returns a collection of all rates for one customer */ - #[Security("is_granted('edit', customer)")] + #[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+'])] @@ -246,15 +246,14 @@ final class CustomerController extends BaseApiController /** * Deletes one rate for a customer */ - #[Security("is_granted('edit', customer)")] + #[IsGranted('edit', 'customer')] #[OA\Delete(responses: [new OA\Response(response: 204, description: 'Returns no content: 204 on successful delete')])] #[OA\Parameter(name: 'id', in: 'path', description: 'The customer whose rate will be removed', required: true)] #[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+'])] - #[Entity('rate', expr: 'repository.find(rateId)')] - public function deleteRateAction(Customer $customer, CustomerRate $rate): Response + public function deleteRateAction(Customer $customer, #[MapEntity(mapping: ['rateId' => 'id'])] CustomerRate $rate): Response { if ($rate->getCustomer() !== $customer) { throw $this->createNotFoundException(); @@ -270,7 +269,7 @@ final class CustomerController extends BaseApiController /** * Adds a new rate to a customer */ - #[Security("is_granted('edit', customer)")] + #[IsGranted('edit', 'customer')] #[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'))] diff --git a/src/API/ProjectController.php b/src/API/ProjectController.php index 7fe276db6..c4713aefb 100644 --- a/src/API/ProjectController.php +++ b/src/API/ProjectController.php @@ -27,16 +27,16 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Bridge\Doctrine\Attribute\MapEntity; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Validator\Constraints; #[Route(path: '/projects')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Project')] final class ProjectController extends BaseApiController { @@ -209,7 +209,7 @@ final class ProjectController extends BaseApiController /** * Update an existing project */ - #[Security("is_granted('edit', project)")] + #[IsGranted('edit', 'project')] #[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)] @@ -249,7 +249,7 @@ final class ProjectController extends BaseApiController /** * Sets the value of a meta-field for an existing project */ - #[Security("is_granted('edit', project)")] + #[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+'])] @@ -282,7 +282,7 @@ final class ProjectController extends BaseApiController /** * Returns a collection of all rates for one project */ - #[Security("is_granted('edit', project)")] + #[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+'])] @@ -301,15 +301,14 @@ final class ProjectController extends BaseApiController /** * Deletes one rate for a project */ - #[Security("is_granted('edit', project)")] + #[IsGranted('edit', 'project')] #[OA\Delete(responses: [new OA\Response(response: 204, description: 'Returns no content: 204 on successful delete')])] #[OA\Parameter(name: 'id', in: 'path', description: 'The project whose rate will be removed', required: true)] #[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+'])] - #[Entity('rate', expr: 'repository.find(rateId)')] - public function deleteRateAction(Project $project, ProjectRate $rate): Response + public function deleteRateAction(Project $project, #[MapEntity(mapping: ['rateId' => 'id'])] ProjectRate $rate): Response { if ($rate->getProject() !== $project) { throw $this->createNotFoundException(); @@ -325,7 +324,7 @@ final class ProjectController extends BaseApiController /** * Adds a new rate to a project */ - #[Security("is_granted('edit', project)")] + #[IsGranted('edit', 'project')] #[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'))] diff --git a/src/API/Serializer/ValidationFailedExceptionErrorHandler.php b/src/API/Serializer/ValidationFailedExceptionErrorHandler.php index 6c9f25e38..8a66c15a0 100644 --- a/src/API/Serializer/ValidationFailedExceptionErrorHandler.php +++ b/src/API/Serializer/ValidationFailedExceptionErrorHandler.php @@ -16,8 +16,8 @@ use JMS\Serializer\Context; use JMS\Serializer\GraphNavigatorInterface; use JMS\Serializer\Handler\SubscribingHandlerInterface; use JMS\Serializer\JsonSerializationVisitor; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\Security\Core\Security; use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Contracts\Translation\TranslatorInterface; diff --git a/src/API/StatusController.php b/src/API/StatusController.php index 85984252b..fcf5914ef 100644 --- a/src/API/StatusController.php +++ b/src/API/StatusController.php @@ -18,10 +18,10 @@ use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Http\Attribute\IsGranted; -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Default')] final class StatusController extends BaseApiController { diff --git a/src/API/TagController.php b/src/API/TagController.php index 1b3a1f8ea..4769941ed 100644 --- a/src/API/TagController.php +++ b/src/API/TagController.php @@ -18,13 +18,13 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/tags')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Tag')] final class TagController extends BaseApiController { @@ -94,7 +94,7 @@ final class TagController extends BaseApiController /** * Delete a tag */ - #[Security("is_granted('delete_tag')")] + #[IsGranted('delete_tag')] #[OA\Delete(responses: [new OA\Response(response: 204, description: 'HTTP code 204 for a successful delete')])] #[OA\Parameter(name: 'id', in: 'path', description: 'Tag ID to delete', required: true)] #[ApiSecurity(name: 'apiUser')] diff --git a/src/API/TeamController.php b/src/API/TeamController.php index f57a1813e..f504108b0 100644 --- a/src/API/TeamController.php +++ b/src/API/TeamController.php @@ -21,15 +21,15 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +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\Security\Http\Attribute\IsGranted; #[Route(path: '/teams')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Team')] final class TeamController extends BaseApiController { @@ -44,7 +44,7 @@ final class TeamController extends BaseApiController /** * Fetch all existing teams (which are visible to the user) */ - #[Security("is_granted('view_team')")] + #[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')] #[ApiSecurity(name: 'apiUser')] @@ -62,7 +62,7 @@ final class TeamController extends BaseApiController /** * Returns one team */ - #[Security("is_granted('view_team')")] + #[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+'])] #[ApiSecurity(name: 'apiUser')] @@ -78,7 +78,7 @@ final class TeamController extends BaseApiController /** * Delete a team */ - #[Security("is_granted('delete_team')")] + #[IsGranted('delete_team')] #[OA\Delete(responses: [new OA\Response(response: 204, description: 'Delete one team')])] #[OA\Parameter(name: 'id', in: 'path', description: 'Team ID to delete', required: true)] #[ApiSecurity(name: 'apiUser')] @@ -96,7 +96,7 @@ final class TeamController extends BaseApiController /** * Creates a new team */ - #[Security("is_granted('create_team')")] + #[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')] @@ -127,7 +127,7 @@ final class TeamController extends BaseApiController /** * Update an existing team */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[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)] @@ -167,15 +167,14 @@ final class TeamController extends BaseApiController /** * Add a new member to a team */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[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+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Entity('member', expr: 'repository.find(userId)')] - public function postMemberAction(Team $team, User $member): Response + public function postMemberAction(Team $team, #[MapEntity(mapping: ['userId' => 'id'])] User $member): Response { if ($member->isInTeam($team)) { throw new BadRequestHttpException('User is already member of the team'); @@ -194,15 +193,14 @@ final class TeamController extends BaseApiController /** * Removes a member from the team */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a user from the team. The teamlead cannot be removed.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team from which the member will be removed', required: true)] #[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+'])] - #[Entity('member', expr: 'repository.find(userId)')] - public function deleteMemberAction(Team $team, User $member): Response + public function deleteMemberAction(Team $team, #[MapEntity(mapping: ['userId' => 'id'])] User $member): Response { if (!$member->isInTeam($team)) { throw new BadRequestHttpException('User is not a member of the team'); @@ -225,15 +223,14 @@ final class TeamController extends BaseApiController /** * Grant the team access to a customer */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[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+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Entity('customer', expr: 'repository.find(customerId)')] - public function postCustomerAction(Team $team, Customer $customer): Response + public function postCustomerAction(Team $team, #[MapEntity(mapping: ['customerId' => 'id'])] Customer $customer): Response { if ($team->hasCustomer($customer)) { throw new BadRequestHttpException('Team has already access to customer'); @@ -252,15 +249,14 @@ final class TeamController extends BaseApiController /** * Revokes access for a customer from a team */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a customer from the team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team whose permission will be revoked', required: true)] #[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+'])] - #[Entity('customer', expr: 'repository.find(customerId)')] - public function deleteCustomerAction(Team $team, Customer $customer): Response + public function deleteCustomerAction(Team $team, #[MapEntity(mapping: ['customerId' => 'id'])] Customer $customer): Response { if (!$team->hasCustomer($customer)) { throw new BadRequestHttpException('Customer is not assigned to the team'); @@ -279,15 +275,14 @@ final class TeamController extends BaseApiController /** * Grant the team access to a project */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[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+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Entity('project', expr: 'repository.find(projectId)')] - public function postProjectAction(Team $team, Project $project): Response + public function postProjectAction(Team $team, #[MapEntity(mapping: ['projectId' => 'id'])] Project $project): Response { if ($team->hasProject($project)) { throw new BadRequestHttpException('Team has already access to project'); @@ -306,15 +301,14 @@ final class TeamController extends BaseApiController /** * Revokes access for a project from a team */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a project from the team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team whose permission will be revoked', required: true)] #[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+'])] - #[Entity('project', expr: 'repository.find(projectId)')] - public function deleteProjectAction(Team $team, Project $project): Response + public function deleteProjectAction(Team $team, #[MapEntity(mapping: ['projectId' => 'id'])] Project $project): Response { if (!$team->hasProject($project)) { throw new BadRequestHttpException('Project is not assigned to the team'); @@ -333,15 +327,14 @@ final class TeamController extends BaseApiController /** * Grant the team access to an activity */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[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+'])] #[ApiSecurity(name: 'apiUser')] #[ApiSecurity(name: 'apiToken')] - #[Entity('activity', expr: 'repository.find(activityId)')] - public function postActivityAction(Team $team, Activity $activity): Response + public function postActivityAction(Team $team, #[MapEntity(mapping: ['activityId' => 'id'])] Activity $activity): Response { if ($team->hasActivity($activity)) { throw new BadRequestHttpException('Team has already access to activity'); @@ -360,15 +353,14 @@ final class TeamController extends BaseApiController /** * Revokes access for an activity from a team */ - #[Security("is_granted('edit_team')")] + #[IsGranted('edit_team')] #[OA\Delete(responses: [new OA\Response(response: 200, description: 'Removes a activity from the team.', content: new OA\JsonContent(ref: '#/components/schemas/Team'))])] #[OA\Parameter(name: 'id', in: 'path', description: 'The team whose permission will be revoked', required: true)] #[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+'])] - #[Entity('activity', expr: 'repository.find(activityId)')] - public function deleteActivityAction(Team $team, Activity $activity): Response + public function deleteActivityAction(Team $team, #[MapEntity(mapping: ['activityId' => 'id'])] Activity $activity): Response { if (!$team->hasActivity($activity)) { throw new BadRequestHttpException('Activity is not assigned to the team'); diff --git a/src/API/TimesheetController.php b/src/API/TimesheetController.php index 4a00d1ea5..a8aebba52 100644 --- a/src/API/TimesheetController.php +++ b/src/API/TimesheetController.php @@ -33,16 +33,17 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +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\Security\Http\Attribute\IsGranted; use Symfony\Component\Validator\Constraints; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; #[Route(path: '/timesheets')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'Timesheet')] final class TimesheetController extends BaseApiController { @@ -69,7 +70,7 @@ final class TimesheetController extends BaseApiController /** * Returns a collection of timesheet records (which are visible to the user) */ - #[Security("is_granted('view_own_timesheet') or is_granted('view_other_timesheet')")] + #[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')] #[ApiSecurity(name: 'apiUser')] @@ -256,7 +257,7 @@ final class TimesheetController extends BaseApiController /** * Returns one timesheet record */ - #[Security("is_granted('view', timesheet)")] + #[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+'])] @@ -273,7 +274,7 @@ final class TimesheetController extends BaseApiController /** * Creates a new timesheet record */ - #[Security("is_granted('create_own_timesheet')")] + #[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')] @@ -328,7 +329,7 @@ final class TimesheetController extends BaseApiController /** * Update an existing timesheet record */ - #[Security("is_granted('edit', timesheet)")] + #[IsGranted('edit', 'timesheet')] #[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'))] @@ -373,7 +374,7 @@ final class TimesheetController extends BaseApiController /** * Delete an existing timesheet record */ - #[Security("is_granted('delete', timesheet)")] + #[IsGranted('delete', 'timesheet')] #[OA\Delete(responses: [new OA\Response(response: 204, description: 'Delete one timesheet record')])] #[OA\Parameter(name: 'id', in: 'path', description: 'Timesheet record ID to delete', required: true)] #[ApiSecurity(name: 'apiUser')] @@ -391,7 +392,7 @@ final class TimesheetController extends BaseApiController /** * Returns the collection of recent user activities */ - #[Security("is_granted('view_own_timesheet')")] + #[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')] #[ApiSecurity(name: 'apiUser')] @@ -427,7 +428,7 @@ final class TimesheetController extends BaseApiController /** * Returns the collection of active timesheet records */ - #[Security("is_granted('view_own_timesheet')")] + #[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')] #[ApiSecurity(name: 'apiUser')] @@ -448,7 +449,7 @@ final class TimesheetController extends BaseApiController /** * Stops an active timesheet record */ - #[Security("is_granted('stop', timesheet)")] + #[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\Patch(path: '/{id}/stop', name: 'stop_timesheet', requirements: ['id' => '\d+'])] @@ -467,7 +468,7 @@ final class TimesheetController extends BaseApiController /** * Restarts a previously stopped timesheet record for the current user */ - #[Security("is_granted('start', timesheet)")] + #[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\Patch(path: '/{id}/restart', name: 'restart_timesheet', requirements: ['id' => '\d+'])] @@ -529,7 +530,7 @@ final class TimesheetController extends BaseApiController /** * Duplicates an existing timesheet record */ - #[Security("is_granted('duplicate', timesheet)")] + #[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+'])] @@ -552,7 +553,7 @@ final class TimesheetController extends BaseApiController /** * Switch the export state of a timesheet record to (un-)lock it */ - #[Security("is_granted('edit_export', timesheet)")] + #[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+'])] @@ -577,7 +578,7 @@ final class TimesheetController extends BaseApiController /** * Sets the value of a meta-field for an existing timesheet. */ - #[Security("is_granted('edit', timesheet)")] + #[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+'])] diff --git a/src/API/UserController.php b/src/API/UserController.php index a6c30f160..6624114b2 100644 --- a/src/API/UserController.php +++ b/src/API/UserController.php @@ -23,16 +23,16 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; use Nelmio\ApiDocBundle\Annotation\Security as ApiSecurity; use OpenApi\Attributes as OA; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; 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\Security\Http\Attribute\IsGranted; #[Route(path: '/users')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] #[OA\Tag(name: 'User')] final class UserController extends BaseApiController { @@ -51,7 +51,7 @@ final class UserController extends BaseApiController /** * Returns the collection of users (which are visible to the user) */ - #[Security("is_granted('view_user')")] + #[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')] #[ApiSecurity(name: 'apiUser')] @@ -95,7 +95,7 @@ final class UserController extends BaseApiController /** * Return one user entity */ - #[Security("is_granted('view', profile)")] + #[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+'])] @@ -131,7 +131,7 @@ final class UserController extends BaseApiController /** * Creates a new user */ - #[Security("is_granted('create_user')")] + #[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')] @@ -184,7 +184,7 @@ final class UserController extends BaseApiController /** * Update an existing user */ - #[Security("is_granted('edit', profile)")] + #[IsGranted('edit', 'profile')] #[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)] diff --git a/src/Controller/ActivityController.php b/src/Controller/ActivityController.php index 0a79ef9b5..ed2de258a 100644 --- a/src/Controller/ActivityController.php +++ b/src/Controller/ActivityController.php @@ -35,18 +35,19 @@ use App\Repository\TeamRepository; use App\Utils\DataTable; use App\Utils\PageSetup; use Exception; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to manage activities. */ #[Route(path: '/admin/activity')] -#[Security("is_granted('view_activity') or is_granted('view_teamlead_activity') or is_granted('view_team_activity')")] +#[IsGranted(new Expression("is_granted('view_activity') or is_granted('view_teamlead_activity') or is_granted('view_team_activity')"))] final class ActivityController extends AbstractController { public function __construct(private ActivityRepository $repository, private SystemConfiguration $configuration, private EventDispatcherInterface $dispatcher, private ActivityService $activityService) @@ -122,7 +123,7 @@ final class ActivityController extends AbstractController } #[Route(path: '/{id}/details', name: 'activity_details', methods: ['GET', 'POST'])] - #[Security("is_granted('view', activity)")] + #[IsGranted('view', 'activity')] public function detailsAction(Activity $activity, TeamRepository $teamRepository, ActivityRateRepository $rateRepository, ActivityStatisticService $statisticService) { $event = new ActivityMetaDefinitionEvent($activity); @@ -172,14 +173,14 @@ final class ActivityController extends AbstractController } #[Route(path: '/{id}/rate/{rate}', name: 'admin_activity_rate_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', activity)")] + #[IsGranted('edit', 'activity')] public function editRateAction(Activity $activity, ActivityRate $rate, Request $request, ActivityRateRepository $repository): Response { return $this->rateFormAction($activity, $rate, $request, $repository, $this->generateUrl('admin_activity_rate_edit', ['id' => $activity->getId(), 'rate' => $rate->getId()])); } #[Route(path: '/{id}/rate', name: 'admin_activity_rate_add', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', activity)")] + #[IsGranted('edit', 'activity')] public function addRateAction(Activity $activity, Request $request, ActivityRateRepository $repository): Response { $rate = new ActivityRate(); @@ -216,14 +217,14 @@ final class ActivityController extends AbstractController } #[Route(path: '/create/{project}', name: 'admin_activity_create_with_project', methods: ['GET', 'POST'])] - #[Security("is_granted('create_activity')")] + #[IsGranted('create_activity')] public function createWithProjectAction(Request $request, Project $project): Response { return $this->createActivity($request, $project); } #[Route(path: '/create', name: 'admin_activity_create', methods: ['GET', 'POST'])] - #[Security("is_granted('create_activity')")] + #[IsGranted('create_activity')] public function createAction(Request $request): Response { return $this->createActivity($request, null); @@ -258,7 +259,7 @@ final class ActivityController extends AbstractController } #[Route(path: '/{id}/permissions', name: 'admin_activity_permissions', methods: ['GET', 'POST'])] - #[Security("is_granted('permissions', activity)")] + #[IsGranted('permissions', 'activity')] public function teamPermissionsAction(Activity $activity, Request $request): Response { $form = $this->createForm(ActivityTeamPermissionForm::class, $activity, [ @@ -291,7 +292,8 @@ final class ActivityController extends AbstractController } #[Route(path: '/{id}/create_team', name: 'activity_team_create', methods: ['GET'])] - #[Security("is_granted('create_team') and is_granted('permissions', activity)")] + #[IsGranted('create_team')] + #[IsGranted('permissions', 'activity')] public function createDefaultTeamAction(Activity $activity, TeamRepository $teamRepository): Response { $defaultTeam = $teamRepository->findOneBy(['name' => $activity->getName()]); @@ -315,7 +317,7 @@ final class ActivityController extends AbstractController } #[Route(path: '/{id}/edit', name: 'admin_activity_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', activity)")] + #[IsGranted('edit', 'activity')] public function editAction(Activity $activity, Request $request): Response { $event = new ActivityMetaDefinitionEvent($activity); @@ -343,7 +345,7 @@ final class ActivityController extends AbstractController } #[Route(path: '/{id}/delete', name: 'admin_activity_delete', methods: ['GET', 'POST'])] - #[Security("is_granted('delete', activity)")] + #[IsGranted('delete', 'activity')] public function deleteAction(Activity $activity, Request $request, ActivityStatisticService $statisticService): Response { $stats = $statisticService->getActivityStatistics($activity); diff --git a/src/Controller/Auth/SamlController.php b/src/Controller/Auth/SamlController.php index 4dd189781..b8f14eafc 100644 --- a/src/Controller/Auth/SamlController.php +++ b/src/Controller/Auth/SamlController.php @@ -12,10 +12,10 @@ 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\Routing\Annotation\Route; -use Symfony\Component\Security\Core\Security; #[Route(path: '/saml')] final class SamlController extends AbstractController diff --git a/src/Controller/CalendarController.php b/src/Controller/CalendarController.php index ed3804c22..381ec6862 100644 --- a/src/Controller/CalendarController.php +++ b/src/Controller/CalendarController.php @@ -15,16 +15,16 @@ use App\Entity\User; use App\Form\CalendarForm; use App\Timesheet\TrackingModeService; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to display calendars. */ #[Route(path: '/calendar')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] final class CalendarController extends AbstractController { public function __construct(private CalendarService $calendarService, private SystemConfiguration $configuration, private TrackingModeService $service) diff --git a/src/Controller/CustomerController.php b/src/Controller/CustomerController.php index 1b1e9c783..3071be446 100644 --- a/src/Controller/CustomerController.php +++ b/src/Controller/CustomerController.php @@ -38,8 +38,8 @@ use App\Utils\DataTable; use App\Utils\FileHelper; use App\Utils\PageSetup; use JeroenDesloovere\VCard\VCard; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -48,12 +48,13 @@ use Symfony\Component\Intl\Countries; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to manage customer in the admin part of the site. */ #[Route(path: '/admin/customer')] -#[Security("is_granted('view_customer') or is_granted('view_teamlead_customer') or is_granted('view_team_customer')")] +#[IsGranted(new Expression("is_granted('view_customer') or is_granted('view_teamlead_customer') or is_granted('view_team_customer')"))] final class CustomerController extends AbstractController { public function __construct(private CustomerRepository $repository, private EventDispatcherInterface $dispatcher) @@ -139,7 +140,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/create', name: 'admin_customer_create', methods: ['GET', 'POST'])] - #[Security("is_granted('create_customer')")] + #[IsGranted('create_customer')] public function createAction(Request $request, CustomerService $customerService) { $customer = $customerService->createNewCustomer(''); @@ -148,7 +149,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/permissions', name: 'admin_customer_permissions', methods: ['GET', 'POST'])] - #[Security("is_granted('permissions', customer)")] + #[IsGranted('permissions', 'customer')] public function teamPermissionsAction(Customer $customer, Request $request) { $form = $this->createForm(CustomerTeamPermissionForm::class, $customer, [ @@ -181,7 +182,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/comment_delete/{token}', name: 'customer_comment_delete', methods: ['GET'])] - #[Security("is_granted('edit', comment.getCustomer()) and is_granted('comments', comment.getCustomer())")] + #[IsGranted(new Expression("is_granted('edit', subject.getCustomer()) and is_granted('comments', subject.getCustomer())"), 'comment')] public function deleteCommentAction(CustomerComment $comment, string $token, CsrfTokenManagerInterface $csrfTokenManager) { $customerId = $comment->getCustomer()->getId(); @@ -204,7 +205,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/comment_add', name: 'customer_comment_add', methods: ['POST'])] - #[Security("is_granted('comments', customer)")] + #[IsGranted('comments', 'customer')] public function addCommentAction(Customer $customer, Request $request) { $comment = new CustomerComment($customer); @@ -224,7 +225,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/comment_pin/{token}', name: 'customer_comment_pin', methods: ['GET'])] - #[Security("is_granted('edit', comment.getCustomer()) and is_granted('comments', comment.getCustomer())")] + #[IsGranted(new Expression("is_granted('edit', subject.getCustomer()) and is_granted('comments', subject.getCustomer())"), 'comment')] public function pinCommentAction(CustomerComment $comment, string $token, CsrfTokenManagerInterface $csrfTokenManager) { $customerId = $comment->getCustomer()->getId(); @@ -248,7 +249,8 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/create_team', name: 'customer_team_create', methods: ['GET'])] - #[Security("is_granted('create_team') and is_granted('permissions', customer)")] + #[IsGranted('create_team')] + #[IsGranted('permissions', 'customer')] public function createDefaultTeamAction(Customer $customer, TeamRepository $teamRepository) { $defaultTeam = $teamRepository->findOneBy(['name' => $customer->getName()]); @@ -272,7 +274,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/projects/{page}', defaults: ['page' => 1], name: 'customer_projects', methods: ['GET', 'POST'])] - #[Security("is_granted('view', customer)")] + #[IsGranted('view', 'customer')] public function projectsAction(Customer $customer, int $page, ProjectRepository $projectRepository) { $query = new ProjectQuery(); @@ -295,7 +297,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/details', name: 'customer_details', methods: ['GET', 'POST'])] - #[Security("is_granted('view', customer)")] + #[IsGranted('view', 'customer')] public function detailsAction(Customer $customer, TeamRepository $teamRepository, CustomerRateRepository $rateRepository, CustomerStatisticService $statisticService) { $event = new CustomerMetaDefinitionEvent($customer); @@ -362,7 +364,7 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/vcard', name: 'customer_vcard', methods: ['GET'])] - #[Security("is_granted('view', customer)")] + #[IsGranted('view', 'customer')] public function downloadVCard(Customer $customer): Response { $vcard = new VCard(); @@ -415,14 +417,14 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/rate/{rate}', name: 'admin_customer_rate_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', customer)")] + #[IsGranted('edit', 'customer')] public function editRateAction(Customer $customer, CustomerRate $rate, Request $request, CustomerRateRepository $repository): Response { return $this->rateFormAction($customer, $rate, $request, $repository, $this->generateUrl('admin_customer_rate_edit', ['id' => $customer->getId(), 'rate' => $rate->getId()])); } #[Route(path: '/{id}/rate', name: 'admin_customer_rate_add', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', customer)")] + #[IsGranted('edit', 'customer')] public function addRateAction(Customer $customer, Request $request, CustomerRateRepository $repository): Response { $rate = new CustomerRate(); @@ -459,14 +461,14 @@ final class CustomerController extends AbstractController } #[Route(path: '/{id}/edit', name: 'admin_customer_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', customer)")] + #[IsGranted('edit', 'customer')] public function editAction(Customer $customer, Request $request) { return $this->renderCustomerForm($customer, $request); } #[Route(path: '/{id}/delete', name: 'admin_customer_delete', methods: ['GET', 'POST'])] - #[Security("is_granted('delete', customer)")] + #[IsGranted('delete', 'customer')] public function deleteAction(Customer $customer, Request $request, CustomerStatisticService $statisticService) { $stats = $statisticService->getCustomerStatistics($customer); diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php index ddb2421ed..4978ebeae 100644 --- a/src/Controller/DashboardController.php +++ b/src/Controller/DashboardController.php @@ -16,19 +16,19 @@ use App\Repository\BookmarkRepository; use App\Utils\PageSetup; use App\Widget\WidgetInterface; use App\Widget\WidgetService; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Dashboard controller for the admin area. */ #[Route(path: '/dashboard')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] final class DashboardController extends AbstractController { public const BOOKMARK_TYPE = 'dashboard'; diff --git a/src/Controller/DoctorController.php b/src/Controller/DoctorController.php index 7d4f99e94..6ca6be579 100644 --- a/src/Controller/DoctorController.php +++ b/src/Controller/DoctorController.php @@ -13,16 +13,16 @@ use App\Utils\FileHelper; use App\Utils\PageSetup; use App\Utils\ReleaseVersion; use Composer\InstalledVersions; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; #[Route(path: '/doctor')] -#[Security("is_granted('system_information')")] +#[IsGranted('system_information')] final class DoctorController extends AbstractController { /** @@ -51,7 +51,7 @@ final class DoctorController extends AbstractController } #[Route(path: '/flush-log/{token}', name: 'doctor_flush_log', methods: ['GET'])] - #[Security("is_granted('system_configuration')")] + #[IsGranted('system_configuration')] public function deleteLogfileAction(string $token, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$csrfTokenManager->isTokenValid(new CsrfToken('doctor.flush_log', $token))) { diff --git a/src/Controller/ExportController.php b/src/Controller/ExportController.php index ff2eb36fe..c6d42ba2c 100644 --- a/src/Controller/ExportController.php +++ b/src/Controller/ExportController.php @@ -16,17 +16,17 @@ use App\Export\TooManyItemsExportException; use App\Form\Toolbar\ExportToolbarForm; use App\Repository\Query\ExportQuery; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to export timesheet data. */ #[Route(path: '/export')] -#[Security("is_granted('create_export')")] +#[IsGranted('create_export')] final class ExportController extends AbstractController { public function __construct(private ServiceExport $export) diff --git a/src/Controller/FavoriteController.php b/src/Controller/FavoriteController.php index 7abc991ae..94c886785 100644 --- a/src/Controller/FavoriteController.php +++ b/src/Controller/FavoriteController.php @@ -11,23 +11,23 @@ namespace App\Controller; use App\Entity\Timesheet; use App\Timesheet\FavoriteRecordService; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/favorite')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] final class FavoriteController extends AbstractController { #[Route(path: '/timesheet/', name: 'favorites_timesheets', methods: ['GET'])] - #[Security("is_granted('view_own_timesheet')")] + #[IsGranted('view_own_timesheet')] public function favoriteAction(): Response { return $this->render('partials/recent-activities.html.twig'); } #[Route(path: '/timesheet/add/{id}', name: 'favorites_timesheets_add', methods: ['GET'])] - #[Security("is_granted('view_own_timesheet')")] + #[IsGranted('view_own_timesheet')] public function add(Timesheet $timesheet, FavoriteRecordService $favoriteRecordService): Response { $favoriteRecordService->addFavorite($timesheet); @@ -36,7 +36,7 @@ final class FavoriteController extends AbstractController } #[Route(path: '/timesheet/remove/{id}', name: 'favorites_timesheets_remove', methods: ['GET'])] - #[Security("is_granted('view_own_timesheet')")] + #[IsGranted('view_own_timesheet')] public function remove(Timesheet $timesheet, FavoriteRecordService $favoriteRecordService): Response { $favoriteRecordService->removeFavorite($timesheet); diff --git a/src/Controller/HomepageController.php b/src/Controller/HomepageController.php index ca60efb33..1a6364db7 100644 --- a/src/Controller/HomepageController.php +++ b/src/Controller/HomepageController.php @@ -11,16 +11,16 @@ namespace App\Controller; use App\Configuration\LocaleService; use App\Entity\User; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Homepage controller is a redirect controller with user specific logic. */ #[Route(path: '/homepage')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] final class HomepageController extends AbstractController { public const DEFAULT_ROUTE = 'timesheet'; diff --git a/src/Controller/InvoiceController.php b/src/Controller/InvoiceController.php index 2e2de6190..4d7f376ad 100644 --- a/src/Controller/InvoiceController.php +++ b/src/Controller/InvoiceController.php @@ -37,7 +37,7 @@ use App\Repository\Query\InvoiceQuery; use App\Utils\DataTable; use App\Utils\PageSetup; use Exception; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\File\UploadedFile; @@ -46,13 +46,15 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * Controller used to create invoices and manage invoice templates. */ #[Route(path: '/invoice')] -#[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('view_invoice')")] +#[IsGranted('IS_AUTHENTICATED_FULLY')] +#[IsGranted('view_invoice')] final class InvoiceController extends AbstractController { public function __construct( @@ -64,7 +66,7 @@ final class InvoiceController extends AbstractController } #[Route(path: '/', name: 'invoice', methods: ['GET', 'POST'])] - #[Security("is_granted('create_invoice')")] + #[IsGranted('create_invoice')] public function indexAction(Request $request, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$this->templateRepository->hasTemplate()) { @@ -127,7 +129,8 @@ final class InvoiceController extends AbstractController } #[Route(path: '/preview/{customer}/{token}', name: 'invoice_preview', methods: ['GET'])] - #[Security("is_granted('access', customer) and is_granted('create_invoice')")] + #[IsGranted('create_invoice')] + #[IsGranted('access', 'customer')] public function previewAction(Customer $customer, string $token, Request $request): Response { if (!$this->templateRepository->hasTemplate()) { @@ -167,7 +170,8 @@ final class InvoiceController extends AbstractController } #[Route(path: '/save-invoice/{customer}/{token}', name: 'invoice_create', methods: ['GET'])] - #[Security("is_granted('access', customer) and is_granted('create_invoice')")] + #[IsGranted('create_invoice')] + #[IsGranted('access', 'customer')] public function createInvoiceAction(Customer $customer, string $token, Request $request, CustomerRepository $customerRepository): Response { if (!$this->templateRepository->hasTemplate()) { @@ -214,7 +218,8 @@ final class InvoiceController extends AbstractController } #[Route(path: '/change-status/{id}/{status}/{token}', name: 'admin_invoice_status', methods: ['GET', 'POST'])] - #[Security("is_granted('access', invoice.getCustomer()) and is_granted('create_invoice')")] + #[IsGranted('create_invoice')] + #[IsGranted(new Expression("is_granted('access', subject.getCustomer())"), 'invoice')] public function changeStatusAction(Invoice $invoice, string $status, string $token, Request $request, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$csrfTokenManager->isTokenValid(new CsrfToken('invoice.status', $token))) { @@ -250,7 +255,8 @@ final class InvoiceController extends AbstractController } #[Route(path: '/edit/{id}', name: 'admin_invoice_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('access', invoice.getCustomer()) and is_granted('create_invoice')")] + #[IsGranted('create_invoice')] + #[IsGranted(new Expression("is_granted('access', subject.getCustomer())"), 'invoice')] public function editAction(Invoice $invoice, Request $request): Response { $form = $this->createInvoiceEditForm($invoice); @@ -275,7 +281,8 @@ final class InvoiceController extends AbstractController } #[Route(path: '/delete/{id}/{token}', name: 'admin_invoice_delete', methods: ['GET'])] - #[Security("is_granted('access', invoice.getCustomer()) and is_granted('delete_invoice')")] + #[IsGranted('delete_invoice')] + #[IsGranted(new Expression("is_granted('access', subject.getCustomer())"), 'invoice')] public function deleteInvoiceAction(Invoice $invoice, string $token, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$csrfTokenManager->isTokenValid(new CsrfToken('invoice.status', $token))) { @@ -297,7 +304,8 @@ final class InvoiceController extends AbstractController } #[Route(path: '/download/{id}', name: 'admin_invoice_download', methods: ['GET'])] - #[Security("is_granted('access', invoice.getCustomer()) and is_granted('view_invoice')")] + #[IsGranted('view_invoice')] + #[IsGranted(new Expression("is_granted('access', subject.getCustomer())"), 'invoice')] public function downloadAction(Invoice $invoice): Response { $file = $this->service->getInvoiceFile($invoice); @@ -312,7 +320,7 @@ final class InvoiceController extends AbstractController } #[Route(path: '/show/{page}', defaults: ['page' => 1], requirements: ['page' => '[1-9]\d*'], name: 'admin_invoice_list', methods: ['GET'])] - #[Security("is_granted('view_invoice')")] + #[IsGranted('view_invoice')] public function showInvoicesAction(Request $request, int $page): Response { $invoice = null; @@ -371,7 +379,7 @@ final class InvoiceController extends AbstractController } #[Route(path: '/export', name: 'invoice_export', methods: ['GET'])] - #[Security("is_granted('view_invoice')")] + #[IsGranted('view_invoice')] public function exportAction(Request $request, EntityWithMetaFieldsExporter $exporter) { $query = new InvoiceArchiveQuery(); @@ -394,7 +402,7 @@ final class InvoiceController extends AbstractController } #[Route(path: '/template/{page}', requirements: ['page' => '[1-9]\d*'], defaults: ['page' => 1], name: 'admin_invoice_template', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_invoice_template')")] + #[IsGranted('manage_invoice_template')] public function listTemplateAction(int $page): Response { $query = new BaseQuery(); @@ -431,14 +439,14 @@ final class InvoiceController extends AbstractController } #[Route(path: '/template/{id}/edit', name: 'admin_invoice_template_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_invoice_template')")] + #[IsGranted('manage_invoice_template')] public function editTemplateAction(InvoiceTemplate $template, Request $request): Response { return $this->renderTemplateForm($template, $request); } #[Route(path: '/document_upload', name: 'admin_invoice_document_upload', methods: ['GET', 'POST'])] - #[Security("is_granted('upload_invoice_template')")] + #[IsGranted('upload_invoice_template')] public function uploadDocumentAction(Request $request, string $projectDirectory, InvoiceDocumentRepository $documentRepository) { $dir = $documentRepository->getUploadDirectory(); @@ -538,7 +546,7 @@ final class InvoiceController extends AbstractController } #[Route(path: '/document/{id}/delete/{token}', name: 'invoice_document_delete', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_invoice_template')")] + #[IsGranted('manage_invoice_template')] public function deleteDocument(string $id, string $token, CsrfTokenManagerInterface $csrfTokenManager, InvoiceDocumentRepository $documentRepository): Response { $document = $documentRepository->findByName($id); @@ -581,14 +589,14 @@ final class InvoiceController extends AbstractController } #[Route(path: '/template/create/{id}', name: 'admin_invoice_template_copy', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_invoice_template')")] + #[IsGranted('manage_invoice_template')] public function copyTemplateAction(Request $request, InvoiceTemplate $copyFrom): Response { return $this->createTemplate($request, $copyFrom); } #[Route(path: '/template/create', name: 'admin_invoice_template_create', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_invoice_template')")] + #[IsGranted('manage_invoice_template')] public function createTemplateAction(Request $request): Response { return $this->createTemplate($request, null); @@ -608,7 +616,7 @@ final class InvoiceController extends AbstractController } #[Route(path: '/template/{id}/delete/{csrfToken}', name: 'admin_invoice_template_delete', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_invoice_template')")] + #[IsGranted('manage_invoice_template')] public function deleteTemplate(InvoiceTemplate $template, string $csrfToken, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$csrfTokenManager->isTokenValid(new CsrfToken('invoice.delete_template', $csrfToken))) { diff --git a/src/Controller/PermissionController.php b/src/Controller/PermissionController.php index e0f074304..fe3003143 100644 --- a/src/Controller/PermissionController.php +++ b/src/Controller/PermissionController.php @@ -22,19 +22,20 @@ use App\Repository\UserRepository; use App\Security\RolePermissionManager; use App\Security\RoleService; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; 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\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to manage user roles and role permissions. */ #[Route(path: '/admin/permissions')] -#[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('role_permissions')")] +#[IsGranted('IS_AUTHENTICATED_FULLY')] +#[IsGranted('role_permissions')] final class PermissionController extends AbstractController { public const TOKEN_NAME = 'user_role_permissions'; @@ -44,7 +45,7 @@ final class PermissionController extends AbstractController } #[Route(path: '', name: 'admin_user_permissions', methods: ['GET', 'POST'])] - #[Security("is_granted('role_permissions')")] + #[IsGranted('role_permissions')] public function permissions(EventDispatcherInterface $dispatcher, CsrfTokenManagerInterface $csrfTokenManager, RoleService $roleService) { $all = $this->roleRepository->findAll(); @@ -161,7 +162,7 @@ final class PermissionController extends AbstractController } #[Route(path: '/roles/create', name: 'admin_user_roles', methods: ['GET', 'POST'])] - #[Security("is_granted('role_permissions')")] + #[IsGranted('role_permissions')] public function createRole(Request $request): Response { $role = new Role(); @@ -195,7 +196,7 @@ final class PermissionController extends AbstractController } #[Route(path: '/roles/{id}/delete/{csrfToken}', name: 'admin_user_role_delete', methods: ['GET', 'POST'])] - #[Security("is_granted('role_permissions')")] + #[IsGranted('role_permissions')] public function deleteRole(Role $role, string $csrfToken, UserRepository $userRepository, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$this->isCsrfTokenValid(self::TOKEN_NAME, $csrfToken)) { @@ -225,7 +226,7 @@ final class PermissionController extends AbstractController } #[Route(path: '/roles/{id}/{name}/{value}/{csrfToken}', name: 'admin_user_permission_save', methods: ['POST'])] - #[Security("is_granted('role_permissions')")] + #[IsGranted('role_permissions')] public function savePermission(Role $role, string $name, bool $value, string $csrfToken, RolePermissionRepository $rolePermissionRepository, CsrfTokenManagerInterface $csrfTokenManager): Response { if (!$this->isCsrfTokenValid(self::TOKEN_NAME, $csrfToken)) { diff --git a/src/Controller/PluginController.php b/src/Controller/PluginController.php index 89536899c..8725ccf79 100644 --- a/src/Controller/PluginController.php +++ b/src/Controller/PluginController.php @@ -11,15 +11,15 @@ namespace App\Controller; use App\Plugin\PluginManager; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Contracts\Cache\CacheInterface; use Symfony\Contracts\Cache\ItemInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; #[Route(path: '/admin/plugins')] -#[Security("is_granted('plugins')")] +#[IsGranted('plugins')] final class PluginController extends AbstractController { #[Route(path: '/', name: 'plugins', methods: ['GET'])] diff --git a/src/Controller/ProfileController.php b/src/Controller/ProfileController.php index 2e20b6449..1625680de 100644 --- a/src/Controller/ProfileController.php +++ b/src/Controller/ProfileController.php @@ -32,18 +32,19 @@ use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh; use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin; use Endroid\QrCode\Writer\PngWriter; use Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Totp\TotpAuthenticatorInterface; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * User profile controller */ #[Route(path: '/profile')] -#[Security("(is_granted('view_own_profile') or is_granted('view_other_profile'))")] +#[IsGranted(new Expression("is_granted('view_own_profile') or is_granted('view_other_profile')"))] final class ProfileController extends AbstractController { #[Route(path: '/', name: 'my_profile', methods: ['GET'])] @@ -53,7 +54,7 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}', name: 'user_profile', methods: ['GET'])] - #[Security("is_granted('view', profile)")] + #[IsGranted('view', 'profile')] public function indexAction(User $profile, TimesheetRepository $repository, TimesheetStatisticService $statisticService): Response { $dateFactory = $this->getDateTimeFactory(); @@ -79,7 +80,7 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/edit', name: 'user_profile_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', profile)")] + #[IsGranted('edit', 'profile')] public function editAction(User $profile, Request $request, UserRepository $userRepository): Response { $form = $this->createEditForm($profile); @@ -101,7 +102,8 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/password', name: 'user_profile_password', methods: ['GET', 'POST'])] - #[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('password', profile)")] + #[IsGranted('IS_AUTHENTICATED_FULLY')] + #[IsGranted('password', 'profile')] public function passwordAction(User $profile, Request $request, UserService $userService): Response { $form = $this->createPasswordForm($profile); @@ -123,7 +125,8 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/api-token', name: 'user_profile_api_token', methods: ['GET', 'POST'])] - #[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('api-token', profile)")] + #[IsGranted('IS_AUTHENTICATED_FULLY')] + #[IsGranted('api-token', 'profile')] public function apiTokenAction(User $profile, Request $request, UserService $userService): Response { $form = $this->createApiTokenForm($profile); @@ -145,7 +148,8 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/roles', name: 'user_profile_roles', methods: ['GET', 'POST'])] - #[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('roles', profile)")] + #[IsGranted('IS_AUTHENTICATED_FULLY')] + #[IsGranted('roles', 'profile')] public function rolesAction(User $profile, Request $request, UserRepository $userRepository): Response { $isSuperAdmin = $profile->isSuperAdmin(); @@ -175,7 +179,7 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/teams', name: 'user_profile_teams', methods: ['GET', 'POST'])] - #[Security("is_granted('teams', profile)")] + #[IsGranted('teams', 'profile')] public function teamsAction(User $profile, Request $request, UserRepository $userRepository, TeamRepository $teamRepository): Response { $originalMembers = new ArrayCollection(); @@ -210,7 +214,7 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/prefs', name: 'user_profile_preferences', methods: ['GET', 'POST'])] - #[Security("is_granted('preferences', profile)")] + #[IsGranted('preferences', 'profile')] public function preferencesAction(User $profile, Request $request, EventDispatcherInterface $dispatcher, UserRepository $userRepository): Response { // we need to prepare the user preferences, which is done via an EventSubscriber @@ -336,7 +340,8 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/2fa', name: 'user_profile_2fa', methods: ['GET', 'POST'])] - #[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('2fa', profile)")] + #[IsGranted('IS_AUTHENTICATED_FULLY')] + #[IsGranted('2fa', 'profile')] public function twoFactorAction(User $profile, Request $request, UserService $userService, TotpAuthenticatorInterface $totpAuthenticator): Response { if (!$profile->hasTotpSecret()) { @@ -382,7 +387,8 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/2fa_deactivate', name: 'user_profile_2fa_deactivate', methods: ['POST'])] - #[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('2fa', profile)")] + #[IsGranted('IS_AUTHENTICATED_FULLY')] + #[IsGranted('2fa', 'profile')] public function deactivateTwoFactorAction(User $profile, Request $request, UserService $userService, TotpAuthenticatorInterface $totpAuthenticator): Response { if ($profile->hasTotpSecret()) { @@ -401,7 +407,7 @@ final class ProfileController extends AbstractController } #[Route(path: '/{username}/totp.png', name: 'user_profile_2fa_image', methods: ['GET'])] - #[Security("is_granted('2fa', profile)")] + #[IsGranted('2fa', 'profile')] public function displayTotpQrCode(User $profile, TotpAuthenticatorInterface $totpAuthenticator): Response { if (!$profile->hasTotpSecret()) { diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php index 661c5b367..ac7c02f9a 100644 --- a/src/Controller/ProjectController.php +++ b/src/Controller/ProjectController.php @@ -40,20 +40,21 @@ use App\Repository\TeamRepository; use App\Utils\Context; use App\Utils\DataTable; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Csrf\CsrfToken; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to manage projects. */ #[Route(path: '/admin/project')] -#[Security("is_granted('view_project') or is_granted('view_teamlead_project') or is_granted('view_team_project')")] +#[IsGranted(new Expression("is_granted('view_project') or is_granted('view_teamlead_project') or is_granted('view_team_project')"))] final class ProjectController extends AbstractController { public function __construct(private ProjectRepository $repository, private SystemConfiguration $configuration, private EventDispatcherInterface $dispatcher, private ProjectService $projectService) @@ -132,7 +133,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/permissions', name: 'admin_project_permissions', methods: ['GET', 'POST'])] - #[Security("is_granted('permissions', project)")] + #[IsGranted('permissions', 'project')] public function teamPermissions(Project $project, Request $request) { $form = $this->createForm(ProjectTeamPermissionForm::class, $project, [ @@ -165,14 +166,14 @@ final class ProjectController extends AbstractController } #[Route(path: '/create/{customer}', name: 'admin_project_create_with_customer', methods: ['GET', 'POST'])] - #[Security("is_granted('create_project')")] + #[IsGranted('create_project')] public function createWithCustomerAction(Request $request, Customer $customer) { return $this->createProject($request, $customer); } #[Route(path: '/create', name: 'admin_project_create', methods: ['GET', 'POST'])] - #[Security("is_granted('create_project')")] + #[IsGranted('create_project')] public function createAction(Request $request) { return $this->createProject($request, null); @@ -204,7 +205,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/comment_delete/{token}', name: 'project_comment_delete', methods: ['GET'])] - #[Security("is_granted('edit', comment.getProject()) and is_granted('comments', comment.getProject())")] + #[IsGranted(new Expression("is_granted('edit', subject.getProject()) and is_granted('comments', subject.getProject())"), 'comment')] public function deleteCommentAction(ProjectComment $comment, string $token, CsrfTokenManagerInterface $csrfTokenManager) { $projectId = $comment->getProject()->getId(); @@ -227,7 +228,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/comment_add', name: 'project_comment_add', methods: ['POST'])] - #[Security("is_granted('comments', project)")] + #[IsGranted('comments', 'project')] public function addCommentAction(Project $project, Request $request) { $comment = new ProjectComment($project); @@ -247,7 +248,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/comment_pin/{token}', name: 'project_comment_pin', methods: ['GET'])] - #[Security("is_granted('edit', comment.getProject()) and is_granted('comments', comment.getProject())")] + #[IsGranted(new Expression("is_granted('edit', subject.getProject()) and is_granted('comments', subject.getProject())"), 'comment')] public function pinCommentAction(ProjectComment $comment, string $token, CsrfTokenManagerInterface $csrfTokenManager) { $projectId = $comment->getProject()->getId(); @@ -271,7 +272,8 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/create_team', name: 'project_team_create', methods: ['GET'])] - #[Security("is_granted('create_team') and is_granted('permissions', project)")] + #[IsGranted('create_team')] + #[IsGranted('permissions', 'project')] public function createDefaultTeamAction(Project $project, TeamRepository $teamRepository) { $defaultTeam = $teamRepository->findOneBy(['name' => $project->getName()]); @@ -295,7 +297,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/activities/{page}', defaults: ['page' => 1], name: 'project_activities', methods: ['GET', 'POST'])] - #[Security("is_granted('view', project)")] + #[IsGranted('view', 'project')] public function activitiesAction(Project $project, int $page, ActivityRepository $activityRepository) { $query = new ActivityQuery(); @@ -319,7 +321,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/details', name: 'project_details', methods: ['GET', 'POST'])] - #[Security("is_granted('view', project)")] + #[IsGranted('view', 'project')] public function detailsAction(Project $project, TeamRepository $teamRepository, ProjectRateRepository $rateRepository, ProjectStatisticService $statisticService, CsrfTokenManagerInterface $csrfTokenManager) { $event = new ProjectMetaDefinitionEvent($project); @@ -380,14 +382,14 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/rate/{rate}', name: 'admin_project_rate_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', project)")] + #[IsGranted('edit', 'project')] public function editRateAction(Project $project, ProjectRate $rate, Request $request, ProjectRateRepository $repository): Response { return $this->rateFormAction($project, $rate, $request, $repository, $this->generateUrl('admin_project_rate_edit', ['id' => $project->getId(), 'rate' => $rate->getId()])); } #[Route(path: '/{id}/rate', name: 'admin_project_rate_add', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', project)")] + #[IsGranted('edit', 'project')] public function addRateAction(Project $project, Request $request, ProjectRateRepository $repository): Response { $rate = new ProjectRate(); @@ -424,7 +426,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/edit', name: 'admin_project_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', project)")] + #[IsGranted('edit', 'project')] public function editAction(Project $project, Request $request) { $editForm = $this->createEditForm($project); @@ -449,7 +451,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/duplicate/{token}', name: 'admin_project_duplicate', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', project)")] + #[IsGranted('edit', 'project')] public function duplicateAction(Project $project, string $token, ProjectDuplicationService $projectDuplicationService, CsrfTokenManagerInterface $csrfTokenManager) { if (!$csrfTokenManager->isTokenValid(new CsrfToken('project.duplicate', $token))) { @@ -468,7 +470,7 @@ final class ProjectController extends AbstractController } #[Route(path: '/{id}/delete', name: 'admin_project_delete', methods: ['GET', 'POST'])] - #[Security("is_granted('delete', project)")] + #[IsGranted('delete', 'project')] public function deleteAction(Project $project, Request $request, ProjectStatisticService $statisticService) { $stats = $statisticService->getProjectStatistics($project); diff --git a/src/Controller/QuickEntryController.php b/src/Controller/QuickEntryController.php index 6ae14ee9b..1d17ffad9 100644 --- a/src/Controller/QuickEntryController.php +++ b/src/Controller/QuickEntryController.php @@ -17,15 +17,15 @@ use App\Repository\Query\TimesheetQuery; use App\Repository\TimesheetRepository; use App\Timesheet\TimesheetService; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to enter times in weekly form. */ #[Route(path: '/quick_entry')] -#[Security("is_granted('quick-entry')")] +#[IsGranted('quick-entry')] final class QuickEntryController extends AbstractController { public function __construct(private SystemConfiguration $configuration, private TimesheetService $timesheetService, private TimesheetRepository $repository) diff --git a/src/Controller/Reporting/CustomerMonthlyProjectsController.php b/src/Controller/Reporting/CustomerMonthlyProjectsController.php index 8ebc516c6..f0a8ca840 100644 --- a/src/Controller/Reporting/CustomerMonthlyProjectsController.php +++ b/src/Controller/Reporting/CustomerMonthlyProjectsController.php @@ -18,13 +18,14 @@ use App\Reporting\CustomerMonthlyProjects\CustomerMonthlyProjectsRepository; use App\Repository\Query\UserQuery; use App\Repository\UserRepository; use PhpOffice\PhpSpreadsheet\Reader\Html; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/reporting/customer/monthly_projects')] -#[Security("is_granted('report:customer') and is_granted('report:other')")] +#[IsGranted('report:customer')] +#[IsGranted('report:other')] final class CustomerMonthlyProjectsController extends AbstractController { #[Route(path: '/view', name: 'report_customer_monthly_projects', methods: ['GET', 'POST'])] diff --git a/src/Controller/Reporting/ProjectDateRangeController.php b/src/Controller/Reporting/ProjectDateRangeController.php index 343e8f72a..d3b53fc08 100644 --- a/src/Controller/Reporting/ProjectDateRangeController.php +++ b/src/Controller/Reporting/ProjectDateRangeController.php @@ -14,14 +14,16 @@ use App\Form\Model\DateRange; use App\Project\ProjectStatisticService; use App\Reporting\ProjectDateRange\ProjectDateRangeForm; use App\Reporting\ProjectDateRange\ProjectDateRangeQuery; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; final class ProjectDateRangeController extends AbstractController { #[Route(path: '/reporting/project_daterange', name: 'report_project_daterange', methods: ['GET', 'POST'])] - #[Security("is_granted('report:project') and is_granted('budget_any', 'project')")] + #[IsGranted('report:project')] + #[IsGranted(new Expression("is_granted('budget_any', 'project')"))] public function __invoke(Request $request, ProjectStatisticService $service) { $dateFactory = $this->getDateTimeFactory(); diff --git a/src/Controller/Reporting/ProjectDetailsController.php b/src/Controller/Reporting/ProjectDetailsController.php index 9bd09439e..774607c54 100644 --- a/src/Controller/Reporting/ProjectDetailsController.php +++ b/src/Controller/Reporting/ProjectDetailsController.php @@ -14,14 +14,16 @@ use App\Project\ProjectStatisticService; use App\Reporting\ProjectDetails\ProjectDetailsForm; use App\Reporting\ProjectDetails\ProjectDetailsQuery; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; final class ProjectDetailsController extends AbstractController { #[Route(path: '/reporting/project_details', name: 'report_project_details', methods: ['GET'])] - #[Security("is_granted('report:project') and is_granted('details', 'project')")] + #[IsGranted('report:project')] + #[IsGranted(new Expression("is_granted('details', 'project')"))] public function __invoke(Request $request, ProjectStatisticService $service) { $dateFactory = $this->getDateTimeFactory(); diff --git a/src/Controller/Reporting/ProjectInactiveController.php b/src/Controller/Reporting/ProjectInactiveController.php index ae8cbe91a..90bbe2524 100644 --- a/src/Controller/Reporting/ProjectInactiveController.php +++ b/src/Controller/Reporting/ProjectInactiveController.php @@ -13,14 +13,16 @@ use App\Controller\AbstractController; use App\Project\ProjectStatisticService; use App\Reporting\ProjectInactive\ProjectInactiveForm; use App\Reporting\ProjectInactive\ProjectInactiveQuery; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; final class ProjectInactiveController extends AbstractController { #[Route(path: '/reporting/project_inactive', name: 'report_project_inactive', methods: ['GET', 'POST'])] - #[Security("is_granted('report:project') and is_granted('budget_any', 'project')")] + #[IsGranted('report:project')] + #[IsGranted(new Expression("is_granted('budget_any', 'project')"))] public function __invoke(Request $request, ProjectStatisticService $service) { $dateFactory = $this->getDateTimeFactory(); diff --git a/src/Controller/Reporting/ProjectViewController.php b/src/Controller/Reporting/ProjectViewController.php index 2b2a4b710..d7461a6db 100644 --- a/src/Controller/Reporting/ProjectViewController.php +++ b/src/Controller/Reporting/ProjectViewController.php @@ -13,14 +13,16 @@ use App\Controller\AbstractController; use App\Project\ProjectStatisticService; use App\Reporting\ProjectView\ProjectViewForm; use App\Reporting\ProjectView\ProjectViewQuery; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; final class ProjectViewController extends AbstractController { #[Route(path: '/reporting/project_view', name: 'report_project_view', methods: ['GET', 'POST'])] - #[Security("is_granted('report:project') and is_granted('budget_any', 'project')")] + #[IsGranted('report:project')] + #[IsGranted(new Expression("is_granted('budget_any', 'project')"))] public function __invoke(Request $request, ProjectStatisticService $service) { $dateFactory = $this->getDateTimeFactory(); diff --git a/src/Controller/Reporting/ReportUsersMonthController.php b/src/Controller/Reporting/ReportUsersMonthController.php index 8ca2d5ab1..38a7321be 100644 --- a/src/Controller/Reporting/ReportUsersMonthController.php +++ b/src/Controller/Reporting/ReportUsersMonthController.php @@ -19,13 +19,13 @@ use App\Repository\Query\UserQuery; use App\Repository\UserRepository; use App\Timesheet\TimesheetStatisticService; use PhpOffice\PhpSpreadsheet\Reader\Html; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/reporting/users')] -#[Security("is_granted('report:other')")] +#[IsGranted('report:other')] final class ReportUsersMonthController extends AbstractController { #[Route(path: '/month', name: 'report_monthly_users', methods: ['GET', 'POST'])] diff --git a/src/Controller/Reporting/ReportUsersWeekController.php b/src/Controller/Reporting/ReportUsersWeekController.php index a96f62bcc..f4c7bcba2 100644 --- a/src/Controller/Reporting/ReportUsersWeekController.php +++ b/src/Controller/Reporting/ReportUsersWeekController.php @@ -19,13 +19,13 @@ use App\Repository\Query\UserQuery; use App\Repository\UserRepository; use App\Timesheet\TimesheetStatisticService; use PhpOffice\PhpSpreadsheet\Reader\Html; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/reporting/users')] -#[Security("is_granted('report:other')")] +#[IsGranted('report:other')] final class ReportUsersWeekController extends AbstractController { #[Route(path: '/week', name: 'report_weekly_users', methods: ['GET', 'POST'])] diff --git a/src/Controller/Reporting/ReportUsersYearController.php b/src/Controller/Reporting/ReportUsersYearController.php index 35fb45444..20806468e 100644 --- a/src/Controller/Reporting/ReportUsersYearController.php +++ b/src/Controller/Reporting/ReportUsersYearController.php @@ -21,13 +21,13 @@ use App\Repository\UserRepository; use App\Timesheet\TimesheetStatisticService; use Exception; use PhpOffice\PhpSpreadsheet\Reader\Html; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/reporting/users')] -#[Security("is_granted('report:other')")] +#[IsGranted('report:other')] final class ReportUsersYearController extends AbstractController { /** diff --git a/src/Controller/Reporting/UserMonthController.php b/src/Controller/Reporting/UserMonthController.php index 47048ba3f..ff0bab892 100644 --- a/src/Controller/Reporting/UserMonthController.php +++ b/src/Controller/Reporting/UserMonthController.php @@ -13,14 +13,14 @@ use App\Model\DailyStatistic; use App\Reporting\MonthByUser\MonthByUser; use App\Reporting\MonthByUser\MonthByUserForm; use Exception; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Exception\AccessDeniedException; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/reporting/user')] -#[Security("is_granted('report:user')")] +#[IsGranted('report:user')] final class UserMonthController extends AbstractUserReportController { /** diff --git a/src/Controller/Reporting/UserWeekController.php b/src/Controller/Reporting/UserWeekController.php index ed9122c53..1fd5c91a7 100644 --- a/src/Controller/Reporting/UserWeekController.php +++ b/src/Controller/Reporting/UserWeekController.php @@ -13,14 +13,14 @@ use App\Model\DailyStatistic; use App\Reporting\WeekByUser\WeekByUser; use App\Reporting\WeekByUser\WeekByUserForm; use Exception; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Exception\AccessDeniedException; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/reporting/user')] -#[Security("is_granted('report:user')")] +#[IsGranted('report:user')] final class UserWeekController extends AbstractUserReportController { /** diff --git a/src/Controller/Reporting/UserYearController.php b/src/Controller/Reporting/UserYearController.php index 082ac1b3a..1e0a6058a 100644 --- a/src/Controller/Reporting/UserYearController.php +++ b/src/Controller/Reporting/UserYearController.php @@ -17,14 +17,14 @@ use App\Reporting\YearByUser\YearByUser; use App\Reporting\YearByUser\YearByUserForm; use DateTime; use Exception; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Exception\AccessDeniedException; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/reporting/user')] -#[Security("is_granted('report:user')")] +#[IsGranted('report:user')] final class UserYearController extends AbstractUserReportController { /** diff --git a/src/Controller/ReportingController.php b/src/Controller/ReportingController.php index 6d5d97081..e9bcd39d1 100644 --- a/src/Controller/ReportingController.php +++ b/src/Controller/ReportingController.php @@ -11,15 +11,15 @@ namespace App\Controller; use App\Reporting\ReportingService; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to render reports. */ #[Route(path: '/reporting')] -#[Security("is_granted('view_reporting')")] +#[IsGranted('view_reporting')] final class ReportingController extends AbstractController { #[Route(path: '/', name: 'reporting', methods: ['GET'])] diff --git a/src/Controller/SystemConfigurationController.php b/src/Controller/SystemConfigurationController.php index e2d4215ae..69a7145bf 100644 --- a/src/Controller/SystemConfigurationController.php +++ b/src/Controller/SystemConfigurationController.php @@ -36,7 +36,6 @@ use App\Utils\PageSetup; use App\Validator\Constraints\ColorChoices; use App\Validator\Constraints\DateTimeFormat; use App\Validator\Constraints\TimeFormat; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\Extension\Core\Type\CountryType; use Symfony\Component\Form\Extension\Core\Type\CurrencyType; @@ -47,6 +46,7 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Validator\Constraints\GreaterThanOrEqual; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; @@ -57,7 +57,8 @@ use Symfony\Component\Validator\Constraints\Regex; * Controller used for executing system relevant tasks. */ #[Route(path: '/admin/system-config')] -#[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('system_configuration')")] +#[IsGranted('IS_AUTHENTICATED_FULLY')] +#[IsGranted('system_configuration')] final class SystemConfigurationController extends AbstractController { public function __construct(private EventDispatcherInterface $eventDispatcher, private ConfigurationRepository $repository, private SystemConfiguration $systemConfiguration, private LockdownService $lockdownService) diff --git a/src/Controller/TagController.php b/src/Controller/TagController.php index fd7025322..b18400b81 100644 --- a/src/Controller/TagController.php +++ b/src/Controller/TagController.php @@ -18,14 +18,14 @@ use App\Repository\Query\TagQuery; use App\Repository\TagRepository; use App\Utils\DataTable; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/admin/tags')] -#[Security("is_granted('view_tag')")] +#[IsGranted('view_tag')] final class TagController extends AbstractController { /** @@ -76,7 +76,7 @@ final class TagController extends AbstractController } #[Route(path: '/{id}/edit', name: 'tags_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_tag')")] + #[IsGranted('manage_tag')] public function editAction(Tag $tag, TagRepository $repository, Request $request) { $editForm = $this->createForm(TagEditForm::class, $tag, [ @@ -108,7 +108,7 @@ final class TagController extends AbstractController } #[Route(path: '/create', name: 'tags_create', methods: ['GET', 'POST'])] - #[Security("is_granted('manage_tag')")] + #[IsGranted('manage_tag')] public function createAction(TagRepository $repository, Request $request) { $tag = new Tag(); @@ -142,7 +142,7 @@ final class TagController extends AbstractController } #[Route(path: '/multi-delete', name: 'tags_multi_delete', methods: ['POST'])] - #[Security("is_granted('delete_tag')")] + #[IsGranted('delete_tag')] public function multiDelete(TagRepository $repository, Request $request) { $form = $this->getMultiUpdateForm($repository); diff --git a/src/Controller/TeamController.php b/src/Controller/TeamController.php index 346770c36..6d1e23d3d 100644 --- a/src/Controller/TeamController.php +++ b/src/Controller/TeamController.php @@ -18,14 +18,14 @@ use App\Repository\Query\TeamQuery; use App\Repository\TeamRepository; use App\Utils\DataTable; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/admin/teams')] -#[Security("is_granted('view_team')")] +#[IsGranted('view_team')] final class TeamController extends AbstractController { public function __construct(private TeamRepository $repository) @@ -81,14 +81,15 @@ final class TeamController extends AbstractController * @return Response */ #[Route(path: '/create', name: 'admin_team_create', methods: ['GET', 'POST'])] - #[Security("is_granted('create_team')")] + #[IsGranted('create_team')] public function createTeam(Request $request): Response { return $this->renderEditScreen(new Team(''), $request, true); } #[Route(path: '/{id}/duplicate', name: 'team_duplicate', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', team) and is_granted('create_team')")] + #[IsGranted('create_team')] + #[IsGranted('edit', 'team')] public function duplicateTeam(Team $team, Request $request) { $newTeam = clone $team; @@ -103,14 +104,14 @@ final class TeamController extends AbstractController } #[Route(path: '/{id}/edit', name: 'admin_team_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', team)")] + #[IsGranted('edit', 'team')] public function editAction(Team $team, Request $request) { return $this->renderEditScreen($team, $request); } #[Route(path: '/{id}/edit_member', name: 'admin_team_member', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', team)")] + #[IsGranted('edit', 'team')] public function editMemberAction(Team $team, Request $request) { $editForm = $this->createForm(TeamEditForm::class, $team, [ diff --git a/src/Controller/TimesheetAbstractController.php b/src/Controller/TimesheetAbstractController.php index b770ea1ee..ae65db2d2 100644 --- a/src/Controller/TimesheetAbstractController.php +++ b/src/Controller/TimesheetAbstractController.php @@ -167,14 +167,13 @@ abstract class TimesheetAbstractController extends AbstractController protected function create(Request $request): Response { - $entry = $this->service->createNewTimesheet($this->getUser()); + $entry = $this->service->createNewTimesheet($this->getUser(), $request); $preForm = $this->createFormForGetRequest(TimesheetPreCreateForm::class, $entry, [ 'include_user' => $this->includeUserInForms('create'), ]); $preForm->submit($request->query->all(), false); - $this->service->prepareNewTimesheet($entry, $request); $createForm = $this->getCreateForm($entry); $createForm->handleRequest($request); diff --git a/src/Controller/TimesheetController.php b/src/Controller/TimesheetController.php index e27b1d522..632593883 100644 --- a/src/Controller/TimesheetController.php +++ b/src/Controller/TimesheetController.php @@ -13,19 +13,19 @@ use App\Entity\Timesheet; use App\Event\TimesheetMetaDisplayEvent; use App\Export\ServiceExport; use App\Form\TimesheetEditForm; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/timesheet')] -#[Security("is_granted('view_own_timesheet')")] +#[IsGranted('view_own_timesheet')] final class TimesheetController extends TimesheetAbstractController { #[Route(path: '/', defaults: ['page' => 1], name: 'timesheet', methods: ['GET'])] #[Route(path: '/page/{page}', requirements: ['page' => '[1-9]\d*'], name: 'timesheet_paginated', methods: ['GET'])] - #[Security("is_granted('view_own_timesheet')")] + #[IsGranted('view_own_timesheet')] public function indexAction(int $page, Request $request): Response { $query = $this->createDefaultQuery(); @@ -35,42 +35,42 @@ final class TimesheetController extends TimesheetAbstractController } #[Route(path: '/export/', name: 'timesheet_export', methods: ['GET', 'POST'])] - #[Security("is_granted('export_own_timesheet')")] + #[IsGranted('export_own_timesheet')] public function exportAction(Request $request, ServiceExport $serviceExport): Response { return $this->export($request, $serviceExport); } #[Route(path: '/{id}/edit', name: 'timesheet_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', entry)")] + #[IsGranted('edit', 'entry')] public function editAction(Timesheet $entry, Request $request): Response { return $this->edit($entry, $request); } #[Route(path: '/{id}/duplicate', name: 'timesheet_duplicate', methods: ['GET', 'POST'])] - #[Security("is_granted('duplicate', entry)")] + #[IsGranted('duplicate', 'entry')] public function duplicateAction(Timesheet $entry, Request $request): Response { return $this->duplicate($entry, $request); } #[Route(path: '/multi-update', name: 'timesheet_multi_update', methods: ['POST'])] - #[Security("is_granted('edit_own_timesheet')")] + #[IsGranted('edit_own_timesheet')] public function multiUpdateAction(Request $request): Response { return $this->multiUpdate($request); } #[Route(path: '/multi-delete', name: 'timesheet_multi_delete', methods: ['POST'])] - #[Security("is_granted('delete_own_timesheet')")] + #[IsGranted('delete_own_timesheet')] public function multiDeleteAction(Request $request): Response { return $this->multiDelete($request); } #[Route(path: '/create', name: 'timesheet_create', methods: ['GET', 'POST'])] - #[Security("is_granted('create_own_timesheet')")] + #[IsGranted('create_own_timesheet')] public function createAction(Request $request): Response { return $this->create($request); diff --git a/src/Controller/TimesheetTeamController.php b/src/Controller/TimesheetTeamController.php index d09813623..501692509 100644 --- a/src/Controller/TimesheetTeamController.php +++ b/src/Controller/TimesheetTeamController.php @@ -21,19 +21,19 @@ use App\Form\TimesheetMultiUserEditForm; use App\Repository\Query\TimesheetQuery; use App\Utils\PageSetup; use Doctrine\Common\Collections\ArrayCollection; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/team/timesheet')] -#[Security("is_granted('view_other_timesheet')")] +#[IsGranted('view_other_timesheet')] final class TimesheetTeamController extends TimesheetAbstractController { #[Route(path: '/', defaults: ['page' => 1], name: 'admin_timesheet', methods: ['GET'])] #[Route(path: '/page/{page}', requirements: ['page' => '[1-9]\d*'], name: 'admin_timesheet_paginated', methods: ['GET'])] - #[Security("is_granted('view_other_timesheet')")] + #[IsGranted('view_other_timesheet')] public function indexAction(int $page, Request $request): Response { $query = $this->createDefaultQuery(); @@ -43,35 +43,35 @@ final class TimesheetTeamController extends TimesheetAbstractController } #[Route(path: '/export/', name: 'admin_timesheet_export', methods: ['GET', 'POST'])] - #[Security("is_granted('export_other_timesheet')")] + #[IsGranted('export_other_timesheet')] public function exportAction(Request $request, ServiceExport $serviceExport): Response { return $this->export($request, $serviceExport); } #[Route(path: '/{id}/edit', name: 'admin_timesheet_edit', methods: ['GET', 'POST'])] - #[Security("is_granted('edit', entry)")] + #[IsGranted('edit', 'entry')] public function editAction(Timesheet $entry, Request $request): Response { return $this->edit($entry, $request); } #[Route(path: '/{id}/duplicate', name: 'admin_timesheet_duplicate', methods: ['GET', 'POST'])] - #[Security("is_granted('duplicate', entry)")] + #[IsGranted('duplicate', 'entry')] public function duplicateAction(Timesheet $entry, Request $request): Response { return $this->duplicate($entry, $request); } #[Route(path: '/create', name: 'admin_timesheet_create', methods: ['GET', 'POST'])] - #[Security("is_granted('create_other_timesheet')")] + #[IsGranted('create_other_timesheet')] public function createAction(Request $request): Response { return $this->create($request); } #[Route(path: '/create_mu', name: 'admin_timesheet_create_multiuser', methods: ['GET', 'POST'])] - #[Security("is_granted('create_other_timesheet')")] + #[IsGranted('create_other_timesheet')] public function createForMultiUserAction(Request $request): Response { $entry = new MultiUserTimesheet(); @@ -150,14 +150,14 @@ final class TimesheetTeamController extends TimesheetAbstractController } #[Route(path: '/multi-update', name: 'admin_timesheet_multi_update', methods: ['POST'])] - #[Security("is_granted('edit_other_timesheet')")] + #[IsGranted('edit_other_timesheet')] public function multiUpdateAction(Request $request): Response { return $this->multiUpdate($request); } #[Route(path: '/multi-delete', name: 'admin_timesheet_multi_delete', methods: ['POST'])] - #[Security("is_granted('delete_other_timesheet')")] + #[IsGranted('delete_other_timesheet')] public function multiDeleteAction(Request $request): Response { return $this->multiDelete($request); diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index e35ae0a7d..fa6d7fcd1 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -25,19 +25,20 @@ use App\Repository\UserRepository; use App\User\UserService; use App\Utils\DataTable; use App\Utils\PageSetup; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; /** * Controller used to manage users in the admin part of the site. */ #[Route(path: '/admin/user')] -#[Security("is_granted('IS_AUTHENTICATED_FULLY') and is_granted('view_user')")] +#[IsGranted('IS_AUTHENTICATED_FULLY')] +#[IsGranted('view_user')] final class UserController extends AbstractController { public function __construct(private UserPasswordHasherInterface $passwordHasher, private UserRepository $repository, private EventDispatcherInterface $dispatcher) @@ -110,7 +111,7 @@ final class UserController extends AbstractController } #[Route(path: '/create', name: 'admin_user_create', methods: ['GET', 'POST'])] - #[Security("is_granted('create_user')")] + #[IsGranted('create_user')] public function createAction(Request $request, SystemConfiguration $config, UserRepository $userRepository): Response { $user = $this->createNewDefaultUser($config); @@ -139,7 +140,7 @@ final class UserController extends AbstractController } #[Route(path: '/{id}/delete', name: 'admin_user_delete', methods: ['GET', 'POST'])] - #[Security("is_granted('delete', userToDelete)")] + #[IsGranted('delete', 'userToDelete')] public function deleteAction(User $userToDelete, Request $request, TimesheetRepository $repository, UserService $userService): Response { // $userToDelete MUST not be called $user, as $user is always the current user! @@ -191,7 +192,7 @@ final class UserController extends AbstractController } #[Route(path: '/export', name: 'user_export', methods: ['GET'])] - #[Security("is_granted('view_user')")] + #[IsGranted('view_user')] public function exportAction(Request $request, UserExporter $exporter) { $query = new UserQuery(); diff --git a/src/Controller/WidgetController.php b/src/Controller/WidgetController.php index 02cda44ec..3ad83953d 100644 --- a/src/Controller/WidgetController.php +++ b/src/Controller/WidgetController.php @@ -9,16 +9,16 @@ namespace App\Controller; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/widgets')] -#[Security("is_granted('IS_AUTHENTICATED_REMEMBERED')")] +#[IsGranted('IS_AUTHENTICATED_REMEMBERED')] final class WidgetController extends AbstractController { #[Route(path: '/working-time/{year}/{week}', requirements: ['year' => '[1-9]\d*', 'week' => '[0-9]\d*'], name: 'widgets_working_time_chart', methods: ['GET'])] - #[Security("is_granted('view_own_timesheet')")] + #[IsGranted('view_own_timesheet')] public function workingtimechartAction($year, $week): Response { return $this->render('widget/paginatedworkingtimechart.html.twig', [ diff --git a/src/Controller/WizardController.php b/src/Controller/WizardController.php index 0810a6abc..9e944ea37 100644 --- a/src/Controller/WizardController.php +++ b/src/Controller/WizardController.php @@ -15,18 +15,18 @@ use App\Form\Type\LanguageType; use App\Form\Type\SkinType; use App\Form\Type\TimezoneType; use App\User\UserService; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Security\Http\Attribute\IsGranted; #[Route(path: '/wizard')] -#[Security("is_granted('IS_AUTHENTICATED_FULLY')")] +#[IsGranted('IS_AUTHENTICATED_FULLY')] final class WizardController extends AbstractController { #[Route(path: '/{wizard}', name: 'wizard', methods: ['GET', 'POST'])] - #[Security("is_granted('view_own_timesheet')")] + #[IsGranted('view_own_timesheet')] public function wizard(Request $request, UserService $userService, string $wizard): Response { $user = $this->getUser(); diff --git a/src/DataFixtures/InvoiceFixtures.php b/src/DataFixtures/InvoiceFixtures.php index ff665b729..330382e4e 100644 --- a/src/DataFixtures/InvoiceFixtures.php +++ b/src/DataFixtures/InvoiceFixtures.php @@ -92,7 +92,7 @@ final class InvoiceFixtures extends Fixture ]; } - protected function generatePaymentDetails(Generator $faker): string + private function generatePaymentDetails(Generator $faker): string { return 'Acme Bank' . PHP_EOL . @@ -101,7 +101,7 @@ final class InvoiceFixtures extends Fixture ; } - protected function generateContact(Generator $faker): string + private function generateContact(Generator $faker): string { return 'Phone: ' . $faker->phoneNumber() . PHP_EOL . @@ -110,7 +110,7 @@ final class InvoiceFixtures extends Fixture ; } - protected function generateAddress(Generator $faker): string + private function generateAddress(Generator $faker): string { return $faker->streetAddress() . PHP_EOL . diff --git a/src/DataFixtures/TeamFixtures.php b/src/DataFixtures/TeamFixtures.php index 7bbddad29..ddc2ea045 100644 --- a/src/DataFixtures/TeamFixtures.php +++ b/src/DataFixtures/TeamFixtures.php @@ -40,7 +40,7 @@ final class TeamFixtures extends Fixture * @param ObjectManager $manager * @return array */ - protected function getAllUsers(ObjectManager $manager): array + private function getAllUsers(ObjectManager $manager): array { $all = []; /** @var User[] $entries */ @@ -56,7 +56,7 @@ final class TeamFixtures extends Fixture * @param ObjectManager $manager * @return array */ - protected function getAllProjects(ObjectManager $manager): array + private function getAllProjects(ObjectManager $manager): array { $all = []; diff --git a/src/DataFixtures/TimesheetFixtures.php b/src/DataFixtures/TimesheetFixtures.php index 8d54080c8..99cea4c95 100644 --- a/src/DataFixtures/TimesheetFixtures.php +++ b/src/DataFixtures/TimesheetFixtures.php @@ -117,6 +117,7 @@ final class TimesheetFixtures extends Fixture implements FixtureGroupInterface } $allTags = $this->getAllTags($manager); + /** @var array $entries */ $entries = $this->findRandom($manager, Timesheet::class, min($all, self::ADD_TAGS_MAX_ENTRIES)); foreach ($entries as $temp) { $tagAmount = rand(0, self::MAX_TAG_PER_ENTRY); @@ -132,9 +133,17 @@ final class TimesheetFixtures extends Fixture implements FixtureGroupInterface $manager->clear(); } - private function findRandom(ObjectManager $manager, string $class, int $amount) + /** + * @template T of object + * @param ObjectManager $manager + * @param class-string $class + * @param int $amount + * @return array + */ + private function findRandom(ObjectManager $manager, string $class, int $amount): array { $qb = $manager->getRepository($class)->createQueryBuilder('entity'); + /** @var array $limits */ $limits = $qb ->select('MIN(entity.id)', 'MAX(entity.id)') ->getQuery() @@ -150,18 +159,17 @@ final class TimesheetFixtures extends Fixture implements FixtureGroupInterface $qb = $manager->getRepository($class)->createQueryBuilder('entity'); - return $qb - ->where($qb->expr()->in('entity.id', $ids)) - ->setMaxResults($amount) - ->getQuery() - ->getResult(); + /** @var array $result */ + $result = $qb->where($qb->expr()->in('entity.id', $ids))->setMaxResults($amount)->getQuery()->getResult(); + + return $result; } /** * @param ObjectManager $manager * @return array */ - protected function getAllTags(ObjectManager $manager): array + private function getAllTags(ObjectManager $manager): array { return $this->findRandom($manager, Tag::class, 50); } @@ -170,7 +178,7 @@ final class TimesheetFixtures extends Fixture implements FixtureGroupInterface * @param ObjectManager $manager * @return array */ - protected function getAllUsers(ObjectManager $manager): array + private function getAllUsers(ObjectManager $manager): array { $all = []; /** @var User[] $entries */ @@ -186,7 +194,7 @@ final class TimesheetFixtures extends Fixture implements FixtureGroupInterface * @param ObjectManager $manager * @return array */ - protected function getAllProjects(ObjectManager $manager): array + private function getAllProjects(ObjectManager $manager): array { return $this->findRandom($manager, Project::class, 50); } @@ -195,12 +203,12 @@ final class TimesheetFixtures extends Fixture implements FixtureGroupInterface * @param ObjectManager $manager * @return array */ - protected function getAllActivities(ObjectManager $manager): array + private function getAllActivities(ObjectManager $manager): array { return $this->findRandom($manager, Activity::class, 50); } - private function createTimesheetEntry(User $user, Activity $activity, Project $project, ?string $description, bool $setEndDate) + private function createTimesheetEntry(User $user, Activity $activity, Project $project, ?string $description, bool $setEndDate): Timesheet { $start = $this->getRandomFirstDay(); $start = $start->modify('- ' . (rand(1, 86400)) . ' seconds'); diff --git a/src/DataFixtures/UserFixtures.php b/src/DataFixtures/UserFixtures.php index 52b649d90..2e8e3688f 100644 --- a/src/DataFixtures/UserFixtures.php +++ b/src/DataFixtures/UserFixtures.php @@ -59,10 +59,8 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface /** * Default users for all test cases - * - * @param ObjectManager $manager */ - private function loadDefaultAccounts(ObjectManager $manager) + private function loadDefaultAccounts(ObjectManager $manager): void { $allUsers = $this->getUserDefinition(); foreach ($allUsers as $userData) { @@ -74,8 +72,8 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface $user->setRoles([$userData[4]]); $user->setAvatar($userData[5]); $user->setEnabled($userData[6]); - $user->setPassword($this->passwordHasher->hashPassword($user, self::DEFAULT_PASSWORD)); - $user->setApiToken($this->passwordHasher->hashPassword($user, self::DEFAULT_API_TOKEN)); + $user->setPassword($this->passwordHasher->hashPassword($user, $userData[8])); + $user->setApiToken($this->passwordHasher->hashPassword($user, $userData[9])); $manager->persist($user); $prefs = $this->getUserPreferences($user, $userData[7]); @@ -117,11 +115,9 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface } /** - * Generate randomized test users, which don't have API access. - * - * @param ObjectManager $manager + * Generate randomized test users, without API access. */ - private function loadTestUsers(ObjectManager $manager) + private function loadTestUsers(ObjectManager $manager): void { $faker = Factory::create(); $existingName = []; @@ -161,10 +157,7 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface $manager->clear(); } - /** - * @return array - */ - protected function getUserDefinition(): array + private function getUserDefinition(): array { // alias = $userData[0] // title = $userData[1] @@ -174,6 +167,8 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface // avatar = $userData[5] // enabled = $userData[6] // timezone = $userData[7] + // password = $userData[8] + // api = $userData[9] return [ [ @@ -185,6 +180,20 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface self::DEFAULT_AVATAR, true, 'America/Vancouver', + self::DEFAULT_PASSWORD, + self::DEFAULT_API_TOKEN, + ], + [ + 'John Doe', + 'Developer', + 'user', + 'user@example.com', + User::ROLE_USER, + self::DEFAULT_AVATAR, + true, + 'America/Vancouver', + 'password', + 'password', ], // inactive user to test login [ @@ -196,6 +205,8 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface self::DEFAULT_AVATAR, false, 'Australia/Sydney', + self::DEFAULT_PASSWORD, + self::DEFAULT_API_TOKEN, ], [ 'Tony Maier', @@ -206,6 +217,20 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface 'https://en.gravatar.com/userimage/3533186/bf2163b1dd23f3107a028af0195624e9.jpeg', true, 'Asia/Bangkok', + self::DEFAULT_PASSWORD, + self::DEFAULT_API_TOKEN, + ], + [ + 'Tony Maier', + 'Head of Sales', + 'teamlead', + 'teamlead@example.com', + User::ROLE_TEAMLEAD, + 'https://en.gravatar.com/userimage/3533186/bf2163b1dd23f3107a028af0195624e9.jpeg', + true, + 'Asia/Bangkok', + 'password', + 'password', ], // no avatar to test default image macro [ @@ -217,6 +242,20 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface null, true, 'Europe/London', + self::DEFAULT_PASSWORD, + self::DEFAULT_API_TOKEN, + ], + [ + 'Anna Smith', + 'Administrator', + 'administrator', + 'administrator@example.com', + User::ROLE_ADMIN, + null, + true, + 'Europe/London', + 'password', + 'password', ], // no alias to test twig username macro [ @@ -228,7 +267,21 @@ final class UserFixtures extends Fixture implements FixtureGroupInterface '/touch-icon-192x192.png', true, 'Europe/Berlin', - ] + self::DEFAULT_PASSWORD, + self::DEFAULT_API_TOKEN, + ], + [ + null, + 'Super Administrator', + 'super_admin', + 'super_admin@example.com', + User::ROLE_SUPER_ADMIN, + '/touch-icon-192x192.png', + true, + 'Europe/Berlin', + 'password', + 'password', + ], ]; } } diff --git a/src/Entity/Customer.php b/src/Entity/Customer.php index 16ab4252d..4ef9b3d01 100644 --- a/src/Entity/Customer.php +++ b/src/Entity/Customer.php @@ -107,7 +107,7 @@ class Customer implements EntityWithMetaFields, EntityWithBudget #[Serializer\Expose] #[Serializer\Groups(['Customer'])] #[Exporter\Expose(label: 'currency')] - private string $currency = self::DEFAULT_CURRENCY; + private ?string $currency = self::DEFAULT_CURRENCY; #[ORM\Column(name: 'phone', type: 'string', length: 30, nullable: true)] #[Assert\Length(max: 30)] #[Serializer\Expose] @@ -197,11 +197,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->id; } - public function setName(?string $name): Customer + public function setName(?string $name): void { $this->name = $name; - - return $this; } public function getName(): ?string @@ -209,11 +207,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->name; } - public function setNumber(?string $number): Customer + public function setNumber(?string $number): void { $this->number = $number; - - return $this; } public function getNumber(): ?string @@ -221,11 +217,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->number; } - public function setComment(?string $comment): Customer + public function setComment(?string $comment): void { $this->comment = $comment; - - return $this; } public function getComment(): ?string @@ -233,11 +227,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->comment; } - public function setVisible(bool $visible): Customer + public function setVisible(bool $visible): void { $this->visible = $visible; - - return $this; } public function isVisible(): bool @@ -255,11 +247,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->billable; } - public function setCompany(?string $company): Customer + public function setCompany(?string $company): void { $this->company = $company; - - return $this; } public function getCompany(): ?string @@ -272,18 +262,14 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->vatId; } - public function setVatId(?string $vatId): Customer + public function setVatId(?string $vatId): void { $this->vatId = $vatId; - - return $this; } - public function setContact(?string $contact): Customer + public function setContact(?string $contact): void { $this->contact = $contact; - - return $this; } public function getContact(): ?string @@ -291,11 +277,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->contact; } - public function setAddress(?string $address): Customer + public function setAddress(?string $address): void { $this->address = $address; - - return $this; } public function getAddress(): ?string @@ -303,11 +287,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->address; } - public function setCountry(?string $country): Customer + public function setCountry(?string $country): void { $this->country = $country; - - return $this; } public function getCountry(): ?string @@ -315,23 +297,19 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->country; } - public function setCurrency(string $currency): Customer + public function setCurrency(?string $currency): void { $this->currency = $currency; - - return $this; } - public function getCurrency(): string + public function getCurrency(): ?string { return $this->currency; } - public function setPhone(?string $phone): Customer + public function setPhone(?string $phone): void { $this->phone = $phone; - - return $this; } public function getPhone(): ?string @@ -339,11 +317,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->phone; } - public function setFax(?string $fax): Customer + public function setFax(?string $fax): void { $this->fax = $fax; - - return $this; } public function getFax(): ?string @@ -351,11 +327,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->fax; } - public function setMobile(?string $mobile): Customer + public function setMobile(?string $mobile): void { $this->mobile = $mobile; - - return $this; } public function getMobile(): ?string @@ -363,11 +337,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->mobile; } - public function setEmail(?string $mail): Customer + public function setEmail(?string $mail): void { $this->email = $mail; - - return $this; } public function getEmail(): ?string @@ -375,11 +347,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->email; } - public function setHomepage(?string $homepage): Customer + public function setHomepage(?string $homepage): void { $this->homepage = $homepage; - - return $this; } public function getHomepage(): ?string @@ -387,11 +357,9 @@ class Customer implements EntityWithMetaFields, EntityWithBudget return $this->homepage; } - public function setTimezone(string $timezone): Customer + public function setTimezone(?string $timezone): void { $this->timezone = $timezone; - - return $this; } public function getTimezone(): ?string diff --git a/src/Entity/Timesheet.php b/src/Entity/Timesheet.php index ac751bf2a..0ab12cba2 100644 --- a/src/Entity/Timesheet.php +++ b/src/Entity/Timesheet.php @@ -90,6 +90,8 @@ class Timesheet implements EntityWithMetaFields, ExportableItem #[Assert\NotNull] private ?DateTime $date = null; /** + * Time records start date-time. + * * Attention: Accessor MUST be used, otherwise date will be serialized in UTC. */ #[ORM\Column(name: 'start_time', type: 'datetime', nullable: false)] @@ -100,6 +102,8 @@ class Timesheet implements EntityWithMetaFields, ExportableItem #[Serializer\Accessor(getter: 'getBegin')] private ?DateTime $begin = null; /** + * Time records end date-time. + * * Attention: Accessor MUST be used, otherwise date will be serialized in UTC. */ #[ORM\Column(name: 'end_time', type: 'datetime', nullable: true)] diff --git a/src/Entity/User.php b/src/Entity/User.php index eb7c3ebd2..9acbd5a26 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -165,7 +165,7 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas #[ORM\Column(name: 'email', type: 'string', length: 180, nullable: false)] #[Assert\NotBlank(groups: ['Registration', 'UserCreate', 'Profile'])] #[Assert\Length(min: 2, max: 180)] - #[Assert\Email(groups: ['Registration', 'UserCreate', 'Profile'])] + #[Assert\Email(mode: 'html5', groups: ['Registration', 'UserCreate', 'Profile'])] private ?string $email = null; #[ORM\Column(name: 'account', type: 'string', length: 30, nullable: true)] #[Assert\Length(max: 30, groups: ['Registration', 'UserCreate', 'Profile'])] diff --git a/src/EventSubscriber/MenuBuilderSubscriber.php b/src/EventSubscriber/MenuBuilderSubscriber.php index 7fa169033..9876b4026 100644 --- a/src/EventSubscriber/MenuBuilderSubscriber.php +++ b/src/EventSubscriber/MenuBuilderSubscriber.php @@ -14,9 +14,9 @@ use App\Event\ConfigureMainMenuEvent; use App\Utils\MenuItemModel; use KevinPapst\TablerBundle\Event\MenuEvent; use KevinPapst\TablerBundle\Model\MenuItemInterface; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Security\Core\Security; /** * Class MenuBuilder configures the main navigation. diff --git a/src/EventSubscriber/MenuFavoritesSubscriber.php b/src/EventSubscriber/MenuFavoritesSubscriber.php index de52cdb32..41b5f0505 100644 --- a/src/EventSubscriber/MenuFavoritesSubscriber.php +++ b/src/EventSubscriber/MenuFavoritesSubscriber.php @@ -12,8 +12,8 @@ namespace App\EventSubscriber; use App\Entity\User; use App\Event\ConfigureMainMenuEvent; use App\Utils\MenuItemModel; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Security\Core\Security; final class MenuFavoritesSubscriber implements EventSubscriberInterface { diff --git a/src/EventSubscriber/UserDetailsSubscriber.php b/src/EventSubscriber/UserDetailsSubscriber.php index ca47205ab..6a25b0368 100644 --- a/src/EventSubscriber/UserDetailsSubscriber.php +++ b/src/EventSubscriber/UserDetailsSubscriber.php @@ -12,9 +12,9 @@ namespace App\EventSubscriber; use App\Entity\User; use App\Utils\MenuItemModel; use KevinPapst\TablerBundle\Event\UserDetailsEvent; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; -use Symfony\Component\Security\Core\Security; /** * @internal diff --git a/src/Export/Base/AbstractSpreadsheetRenderer.php b/src/Export/Base/AbstractSpreadsheetRenderer.php index 58ac27fef..abfd7ffbf 100644 --- a/src/Export/Base/AbstractSpreadsheetRenderer.php +++ b/src/Export/Base/AbstractSpreadsheetRenderer.php @@ -29,11 +29,11 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Style\Border; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; -use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; /** diff --git a/src/Form/Extension/UserExtension.php b/src/Form/Extension/UserExtension.php index 647a09c3a..854f01f0b 100644 --- a/src/Form/Extension/UserExtension.php +++ b/src/Form/Extension/UserExtension.php @@ -10,10 +10,10 @@ namespace App\Form\Extension; use App\Entity\User; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Security\Core\Security; final class UserExtension extends AbstractTypeExtension { diff --git a/src/Form/TimesheetPreCreateForm.php b/src/Form/TimesheetPreCreateForm.php index d1af5fead..f5a08874c 100644 --- a/src/Form/TimesheetPreCreateForm.php +++ b/src/Form/TimesheetPreCreateForm.php @@ -10,6 +10,7 @@ namespace App\Form; use App\Form\Type\DescriptionType; +use App\Form\Type\MetaFieldsCollectionType; use App\Form\Type\TagsInputType; use App\Form\Type\UserType; use Symfony\Component\Form\AbstractType; @@ -29,6 +30,7 @@ final class TimesheetPreCreateForm extends AbstractType $this->addActivity($builder, null, null, ['required' => false]); $builder->add('description', DescriptionType::class, ['required' => false]); $builder->add('tags', TagsInputType::class, ['required' => false]); + $builder->add('metaFields', MetaFieldsCollectionType::class); if ($options['include_user']) { $builder->add('user', UserType::class, ['required' => false]); } diff --git a/src/Form/Type/QuickEntryTimesheetType.php b/src/Form/Type/QuickEntryTimesheetType.php index 96c059aa1..b9986ea9f 100644 --- a/src/Form/Type/QuickEntryTimesheetType.php +++ b/src/Form/Type/QuickEntryTimesheetType.php @@ -10,13 +10,13 @@ namespace App\Form\Type; use App\Entity\Timesheet; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\Security\Core\Security; final class QuickEntryTimesheetType extends AbstractType { diff --git a/src/Invoice/InvoiceModel.php b/src/Invoice/InvoiceModel.php index 66028d524..01f46a58a 100644 --- a/src/Invoice/InvoiceModel.php +++ b/src/Invoice/InvoiceModel.php @@ -229,12 +229,11 @@ final class InvoiceModel public function getCurrency(): string { - if (null === $this->getCustomer()) { - // this should be set from the configuration - return Customer::DEFAULT_CURRENCY; + if (null !== $this->getCustomer() && $this->getCustomer()->getCurrency() !== null) { + return $this->getCustomer()->getCurrency(); } - return $this->getCustomer()->getCurrency(); + return Customer::DEFAULT_CURRENCY; } public function toArray(): array diff --git a/src/Timesheet/FavoriteRecordService.php b/src/Timesheet/FavoriteRecordService.php index 9e7b66bb9..3fbdfae0a 100644 --- a/src/Timesheet/FavoriteRecordService.php +++ b/src/Timesheet/FavoriteRecordService.php @@ -62,7 +62,7 @@ final class FavoriteRecordService $bookmark = new Bookmark(); $bookmark->setUser($user); $bookmark->setType('favorite'); - $bookmark->setName('timesheet'); + $bookmark->setName('recent'); } return $bookmark; diff --git a/src/Twig/LocaleFormatExtensions.php b/src/Twig/LocaleFormatExtensions.php index 3eda75487..a66e6f6e0 100644 --- a/src/Twig/LocaleFormatExtensions.php +++ b/src/Twig/LocaleFormatExtensions.php @@ -17,7 +17,7 @@ use App\Utils\FormFormatConverter; use App\Utils\JavascriptFormatConverter; use App\Utils\LocaleFormatter; use DateTime; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Contracts\Translation\LocaleAwareInterface; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; diff --git a/src/Twig/Runtime/WidgetExtension.php b/src/Twig/Runtime/WidgetExtension.php index 0ac4620e3..524e3549b 100644 --- a/src/Twig/Runtime/WidgetExtension.php +++ b/src/Twig/Runtime/WidgetExtension.php @@ -13,7 +13,7 @@ use App\Entity\User; use App\Widget\WidgetException; use App\Widget\WidgetInterface; use App\Widget\WidgetService; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Twig\Environment; use Twig\Extension\RuntimeExtensionInterface; diff --git a/src/Utils/ProfileManager.php b/src/Utils/ProfileManager.php index f7edb35e4..1bef12871 100644 --- a/src/Utils/ProfileManager.php +++ b/src/Utils/ProfileManager.php @@ -11,6 +11,7 @@ namespace App\Utils; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\SessionInterface; final class ProfileManager { @@ -52,7 +53,7 @@ final class ProfileManager return $profile; } - public function setProfile(Session $session, string $profile): void + public function setProfile(SessionInterface $session, string $profile): void { if ($profile === self::PROFILE_MOBILE) { $session->set(self::SESSION_PROFILE, $profile); diff --git a/src/Validator/Constraints/ColorChoices.php b/src/Validator/Constraints/ColorChoices.php index ecdb57229..798c400b2 100644 --- a/src/Validator/Constraints/ColorChoices.php +++ b/src/Validator/Constraints/ColorChoices.php @@ -16,7 +16,7 @@ final class ColorChoices extends Constraint public const COLOR_CHOICES_ERROR = 'ui5hffg-dsfef3-1234-5678-2g8jkfr56d84'; public const COLOR_CHOICES_NAME_ERROR = 'ui5hffg-dsfef3-1234-5679-2g8jkfr56d84'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::COLOR_CHOICES_ERROR => 'COLOR_CHOICES_ERROR', self::COLOR_CHOICES_NAME_ERROR => 'COLOR_CHOICES_NAME_ERROR', ]; diff --git a/src/Validator/Constraints/DateTimeFormat.php b/src/Validator/Constraints/DateTimeFormat.php index 0ecf53a65..e2a470a05 100644 --- a/src/Validator/Constraints/DateTimeFormat.php +++ b/src/Validator/Constraints/DateTimeFormat.php @@ -15,7 +15,7 @@ final class DateTimeFormat extends Constraint { public const INVALID_FORMAT = 'kimai-datetime-00'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::INVALID_FORMAT => 'The given value is not a valid datetime format.', ]; diff --git a/src/Validator/Constraints/HexColor.php b/src/Validator/Constraints/HexColor.php index 49f438b6d..fe10c71c4 100644 --- a/src/Validator/Constraints/HexColor.php +++ b/src/Validator/Constraints/HexColor.php @@ -16,7 +16,7 @@ final class HexColor extends Constraint { public const HEX_COLOR_ERROR = 'xd5hffg-dsfef3-426a-83d7-2g8jkfr56d84'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::HEX_COLOR_ERROR => 'HEX_COLOR_ERROR', ]; diff --git a/src/Validator/Constraints/Project.php b/src/Validator/Constraints/Project.php index 0b3e8bab1..0e8519008 100644 --- a/src/Validator/Constraints/Project.php +++ b/src/Validator/Constraints/Project.php @@ -16,7 +16,7 @@ final class Project extends Constraint { public const END_BEFORE_BEGIN_ERROR = 'kimai-project-00'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::END_BEFORE_BEGIN_ERROR => 'End date must not be earlier then start date.', ]; diff --git a/src/Validator/Constraints/Role.php b/src/Validator/Constraints/Role.php index f1ec68603..6aca28892 100644 --- a/src/Validator/Constraints/Role.php +++ b/src/Validator/Constraints/Role.php @@ -16,7 +16,7 @@ final class Role extends Constraint { public const ROLE_ERROR = 'xd5hffg-dsfef3-426a-83d7-1f2d33hs5d84'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::ROLE_ERROR => 'ROLE_ERROR', ]; diff --git a/src/Validator/Constraints/RoleName.php b/src/Validator/Constraints/RoleName.php index dda1de0de..d89de2642 100644 --- a/src/Validator/Constraints/RoleName.php +++ b/src/Validator/Constraints/RoleName.php @@ -16,7 +16,7 @@ final class RoleName extends Constraint { public const ROLE_NAME_ERROR = 'xd5hffg-dsfef3-426a-83d7-1f2d33hs5d85'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::ROLE_NAME_ERROR => 'ROLE_NAME_ERROR', ]; diff --git a/src/Validator/Constraints/Team.php b/src/Validator/Constraints/Team.php index cb4ae3214..441a0008f 100644 --- a/src/Validator/Constraints/Team.php +++ b/src/Validator/Constraints/Team.php @@ -16,7 +16,7 @@ final class Team extends Constraint { public const MISSING_TEAMLEAD = 'kimai-team-001'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::MISSING_TEAMLEAD => 'At least one team leader must be assigned to the team.', ]; diff --git a/src/Validator/Constraints/TimeFormat.php b/src/Validator/Constraints/TimeFormat.php index 40e1e1c3d..4a81983a7 100644 --- a/src/Validator/Constraints/TimeFormat.php +++ b/src/Validator/Constraints/TimeFormat.php @@ -15,7 +15,7 @@ final class TimeFormat extends Constraint { public const INVALID_FORMAT = 'kimai-time-00'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::INVALID_FORMAT => 'The given value is not a valid time.', ]; diff --git a/src/Validator/Constraints/TimesheetBasic.php b/src/Validator/Constraints/TimesheetBasic.php index 47ce19bca..b5fccbf8c 100644 --- a/src/Validator/Constraints/TimesheetBasic.php +++ b/src/Validator/Constraints/TimesheetBasic.php @@ -23,7 +23,7 @@ final class TimesheetBasic extends TimesheetConstraint public const PROJECT_ALREADY_ENDED = 'kimai-timesheet-92'; public const PROJECT_DISALLOWS_GLOBAL_ACTIVITY = 'kimai-timesheet-93'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::MISSING_BEGIN_ERROR => 'You must submit a begin date.', self::END_BEFORE_BEGIN_ERROR => 'End date must not be earlier then start date.', self::MISSING_ACTIVITY_ERROR => 'An activity needs to be selected.', diff --git a/src/Validator/Constraints/TimesheetExported.php b/src/Validator/Constraints/TimesheetExported.php index f3767df41..df37d914b 100644 --- a/src/Validator/Constraints/TimesheetExported.php +++ b/src/Validator/Constraints/TimesheetExported.php @@ -13,7 +13,7 @@ final class TimesheetExported extends TimesheetConstraint { public const TIMESHEET_EXPORTED = 'kimai-timesheet-exported-01'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::TIMESHEET_EXPORTED => 'This timesheet is already exported.', ]; diff --git a/src/Validator/Constraints/TimesheetExportedValidator.php b/src/Validator/Constraints/TimesheetExportedValidator.php index 9978e281b..179daec41 100644 --- a/src/Validator/Constraints/TimesheetExportedValidator.php +++ b/src/Validator/Constraints/TimesheetExportedValidator.php @@ -10,7 +10,7 @@ namespace App\Validator\Constraints; use App\Entity\Timesheet as TimesheetEntity; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; diff --git a/src/Validator/Constraints/TimesheetFutureTimes.php b/src/Validator/Constraints/TimesheetFutureTimes.php index b40286cc9..d052cfe1e 100644 --- a/src/Validator/Constraints/TimesheetFutureTimes.php +++ b/src/Validator/Constraints/TimesheetFutureTimes.php @@ -13,7 +13,7 @@ final class TimesheetFutureTimes extends TimesheetConstraint { public const BEGIN_IN_FUTURE_ERROR = 'kimai-timesheet-future-times-01'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::BEGIN_IN_FUTURE_ERROR => 'The begin date cannot be in the future.', ]; diff --git a/src/Validator/Constraints/TimesheetLockdown.php b/src/Validator/Constraints/TimesheetLockdown.php index 49521bf22..1ba70425c 100644 --- a/src/Validator/Constraints/TimesheetLockdown.php +++ b/src/Validator/Constraints/TimesheetLockdown.php @@ -13,7 +13,7 @@ final class TimesheetLockdown extends TimesheetConstraint { public const PERIOD_LOCKED = 'kimai-timesheet-lockdown-01'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::PERIOD_LOCKED => 'This period is locked, please choose a later date.', ]; diff --git a/src/Validator/Constraints/TimesheetLockdownValidator.php b/src/Validator/Constraints/TimesheetLockdownValidator.php index 22254415e..4a01508a6 100644 --- a/src/Validator/Constraints/TimesheetLockdownValidator.php +++ b/src/Validator/Constraints/TimesheetLockdownValidator.php @@ -11,7 +11,7 @@ namespace App\Validator\Constraints; use App\Entity\Timesheet as TimesheetEntity; use App\Timesheet\LockdownService; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; diff --git a/src/Validator/Constraints/TimesheetLongRunning.php b/src/Validator/Constraints/TimesheetLongRunning.php index faac2e46f..537eb882e 100644 --- a/src/Validator/Constraints/TimesheetLongRunning.php +++ b/src/Validator/Constraints/TimesheetLongRunning.php @@ -14,7 +14,7 @@ final class TimesheetLongRunning extends TimesheetConstraint public const LONG_RUNNING = 'kimai-timesheet-long-running-01'; public const MAXIMUM = 'kimai-timesheet-long-running-02'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::LONG_RUNNING => 'TIMESHEET_LONG_RUNNING', self::MAXIMUM => 'MAXIMUM', ]; diff --git a/src/Validator/Constraints/TimesheetMultiUpdate.php b/src/Validator/Constraints/TimesheetMultiUpdate.php index 46d01a44e..8b3c0c8eb 100644 --- a/src/Validator/Constraints/TimesheetMultiUpdate.php +++ b/src/Validator/Constraints/TimesheetMultiUpdate.php @@ -22,7 +22,7 @@ final class TimesheetMultiUpdate extends Constraint public const DISABLED_CUSTOMER_ERROR = 'ts-multi-update-89'; public const HOURLY_RATE_FIXED_RATE = 'ts-multi-update-90'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::MISSING_ACTIVITY_ERROR => 'You need to choose an activity, if the project should be changed.', self::MISSING_PROJECT_ERROR => 'A project needs to be selected.', self::ACTIVITY_PROJECT_MISMATCH_ERROR => 'Project mismatch: chosen project does not match the activity project.', diff --git a/src/Validator/Constraints/TimesheetMultiUser.php b/src/Validator/Constraints/TimesheetMultiUser.php index 48907d06e..f9c8c969a 100644 --- a/src/Validator/Constraints/TimesheetMultiUser.php +++ b/src/Validator/Constraints/TimesheetMultiUser.php @@ -16,7 +16,7 @@ final class TimesheetMultiUser extends Constraint { public const MISSING_USER_OR_TEAM = 'ts-multi-user-01'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::MISSING_USER_OR_TEAM => 'You must select at least one user or team.', ]; diff --git a/src/Validator/Constraints/TimesheetOverlapping.php b/src/Validator/Constraints/TimesheetOverlapping.php index 1dec1469e..35ff6eba2 100644 --- a/src/Validator/Constraints/TimesheetOverlapping.php +++ b/src/Validator/Constraints/TimesheetOverlapping.php @@ -13,7 +13,7 @@ final class TimesheetOverlapping extends TimesheetConstraint { public const RECORD_OVERLAPPING = 'kimai-timesheet-overlapping-01'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::RECORD_OVERLAPPING => 'You already have an entry for this time.', ]; diff --git a/src/Validator/Constraints/TimesheetRestart.php b/src/Validator/Constraints/TimesheetRestart.php index 91a199122..751c66d06 100644 --- a/src/Validator/Constraints/TimesheetRestart.php +++ b/src/Validator/Constraints/TimesheetRestart.php @@ -13,7 +13,7 @@ final class TimesheetRestart extends TimesheetConstraint { public const START_DISALLOWED = 'kimai-timesheet-restart-01'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::START_DISALLOWED => 'You are not allowed to start this timesheet record.', ]; diff --git a/src/Validator/Constraints/TimesheetRestartValidator.php b/src/Validator/Constraints/TimesheetRestartValidator.php index 30c1e9a19..4333bcba2 100644 --- a/src/Validator/Constraints/TimesheetRestartValidator.php +++ b/src/Validator/Constraints/TimesheetRestartValidator.php @@ -11,7 +11,7 @@ namespace App\Validator\Constraints; use App\Entity\Timesheet as TimesheetEntity; use App\Timesheet\TrackingModeService; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\UnexpectedTypeException; diff --git a/src/Validator/Constraints/TimesheetZeroDuration.php b/src/Validator/Constraints/TimesheetZeroDuration.php index cbdd45658..16bde215f 100644 --- a/src/Validator/Constraints/TimesheetZeroDuration.php +++ b/src/Validator/Constraints/TimesheetZeroDuration.php @@ -13,7 +13,7 @@ final class TimesheetZeroDuration extends TimesheetConstraint { public const ZERO_DURATION_ERROR = 'kimai-timesheet-zero-duration-01'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::ZERO_DURATION_ERROR => 'Duration cannot be zero.', ]; diff --git a/src/Validator/Constraints/User.php b/src/Validator/Constraints/User.php index 41584a72d..0bcfcc8c3 100644 --- a/src/Validator/Constraints/User.php +++ b/src/Validator/Constraints/User.php @@ -19,7 +19,7 @@ final class User extends Constraint public const USER_EXISTING_EMAIL_AS_NAME = 'kimai-user-02'; public const USER_EXISTING_NAME_AS_EMAIL = 'kimai-user-03'; - protected static $errorNames = [ + protected const ERROR_NAMES = [ self::USER_EXISTING_EMAIL => 'The email is already used.', self::USER_EXISTING_NAME => 'The username is already used.', self::USER_EXISTING_EMAIL_AS_NAME => 'An equal username is already used.', diff --git a/symfony.lock b/symfony.lock index d1ff80867..33194aac0 100644 --- a/symfony.lock +++ b/symfony.lock @@ -379,15 +379,6 @@ "sebastian/version": { "version": "2.0.1" }, - "sensio/framework-extra-bundle": { - "version": "4.0", - "recipe": { - "repo": "github.com/symfony/recipes", - "branch": "master", - "version": "4.0", - "ref": "aaddfdf43cdecd4cf91f992052d76c2cadc04543" - } - }, "setasign/fpdi": { "version": "1.6.2" }, diff --git a/templates/invoice/renderer/default.pdf.twig b/templates/invoice/renderer/default.pdf.twig index ee6173a0c..3cfbe1b9a 100644 --- a/templates/invoice/renderer/default.pdf.twig +++ b/templates/invoice/renderer/default.pdf.twig @@ -32,10 +32,10 @@ {{ 'contact'|trans }}: - {{ model.template.contact|nl2str(' – ') }} + {{ model.template.contact|nl2str(' – ') }}
{{ 'invoice_bank_account'|trans }}: - {{ model.template.paymentDetails|nl2str(' – ') }} + {{ model.template.paymentDetails|nl2str(' – ') }} {{ 'export.page_of'|trans({'%page%': '{PAGENO}', '%pages%': '{nb}'}) }} diff --git a/templates/invoice/renderer/invoice.html.twig b/templates/invoice/renderer/invoice.html.twig index 3c8dbd56a..5ade51cfc 100644 --- a/templates/invoice/renderer/invoice.html.twig +++ b/templates/invoice/renderer/invoice.html.twig @@ -138,11 +138,11 @@

- {{ 'address'|trans }}: {{ model.template.company }} – {{ model.template.address|nl2str(' – ') }} + {{ 'address'|trans }}: {{ model.template.company }} – {{ model.template.address|nl2str(' – ') }}
- {{ 'invoice_bank_account'|trans }}: {{ model.template.paymentDetails|nl2str(' – ') }} + {{ 'invoice_bank_account'|trans }}: {{ model.template.paymentDetails|nl2str(' – ') }}
- {{ 'contact'|trans }}: {{ model.template.contact|nl2str(' – ') }} + {{ 'contact'|trans }}: {{ model.template.contact|nl2str(' – ') }}

{% endblock %} diff --git a/templates/invoice/renderer/service-date.pdf.twig b/templates/invoice/renderer/service-date.pdf.twig index 3b6e02c4e..de14028fa 100644 --- a/templates/invoice/renderer/service-date.pdf.twig +++ b/templates/invoice/renderer/service-date.pdf.twig @@ -18,7 +18,7 @@
- {{ model.template.company }} – {{ model.template.address|nl2str(' – ') }} + {{ model.template.company }} – {{ model.template.address|nl2str(' – ') }} {% if model.template.vatId is not empty %} – {{ 'vat_id'|trans }}: {{ model.template.vatId }} {% endif %} diff --git a/templates/user/stats.html.twig b/templates/user/stats.html.twig index c6895df6a..d0ff6dd26 100644 --- a/templates/user/stats.html.twig +++ b/templates/user/stats.html.twig @@ -18,11 +18,11 @@ } %} {% if user.accountNumber is not empty %} {% set datagrid = datagrid|merge({ - 'account_number' : (user.accountNumber ?? '–'), + 'account_number' : (user.accountNumber ?? '–'), }) %} {% endif %} {% set datagrid = datagrid|merge({ - 'profile.first_entry' : (firstTimesheet is not null ? firstTimesheet|date_short : '–'), + 'profile.first_entry' : (firstTimesheet is not null ? firstTimesheet|date_short : '–'), 'profile.registration_date' : user.registeredAt|date_short, }) %} {% set seeOwnRate = false %} diff --git a/tests/API/ApiDocControllerTest.php b/tests/API/ApiDocControllerTest.php index bba4b4bac..3e4e67c71 100644 --- a/tests/API/ApiDocControllerTest.php +++ b/tests/API/ApiDocControllerTest.php @@ -110,7 +110,7 @@ class ApiDocControllerTest extends ControllerBaseTest $this->assertArrayHasKey('security', $json); $this->assertArrayHasKey('X-AUTH-USER', $json['security'][0]); - $this->assertArrayHasKey('X-AUTH-TOKEN', $json['security'][1]); + $this->assertArrayHasKey('X-AUTH-TOKEN', $json['security'][0]); $this->assertArrayHasKey('components', $json); $this->assertArrayHasKey('schemas', $json['components']); diff --git a/tests/API/ProjectControllerTest.php b/tests/API/ProjectControllerTest.php index b093bc324..ce4f49701 100644 --- a/tests/API/ProjectControllerTest.php +++ b/tests/API/ProjectControllerTest.php @@ -111,25 +111,45 @@ class ProjectControllerTest extends APIControllerBaseTest $customer = $em->getRepository(Customer::class)->find(1); - $customer2 = (new Customer('first one'))->setVisible(false)->setCountry('de')->setTimezone('Europe/Berlin'); + $customer2 = new Customer('first one'); + $customer2->setVisible(false); + $customer2->setCountry('de'); + $customer2->setTimezone('Europe/Berlin'); $em->persist($customer2); - $customer3 = (new Customer('second one'))->setCountry('at')->setTimezone('Europe/Vienna'); + $customer3 = new Customer('second one'); + $customer3->setCountry('at'); + $customer3->setTimezone('Europe/Vienna'); $em->persist($customer3); - $project = (new Project())->setName('first')->setVisible(false)->setCustomer($customer2); + $project = new Project(); + $project->setName('first'); + $project->setVisible(false); + $project->setCustomer($customer2); $em->persist($project); - $project = (new Project())->setName('second')->setVisible(false)->setCustomer($customer); + $project = new Project(); + $project->setName('second'); + $project->setVisible(false); + $project->setCustomer($customer); $em->persist($project); - $project = (new Project())->setName('third')->setVisible(true)->setCustomer($customer2); + $project = new Project(); + $project->setName('third'); + $project->setVisible(true); + $project->setCustomer($customer2); $em->persist($project); - $project = (new Project())->setName('fourth')->setVisible(true)->setCustomer($customer3); + $project = new Project(); + $project->setName('fourth'); + $project->setVisible(true); + $project->setCustomer($customer3); $em->persist($project); - $project = (new Project())->setName('fifth')->setVisible(true)->setCustomer($customer); + $project = new Project(); + $project->setName('fifth'); + $project->setVisible(true); + $project->setCustomer($customer); // add meta fields $meta = new ProjectMeta(); @@ -227,25 +247,23 @@ class ProjectControllerTest extends APIControllerBaseTest $client = $this->getClientForAuthenticatedUser(User::ROLE_USER); $em = $this->getEntityManager(); - $customer = (new Customer('first one')) - ->setVisible(true) - ->setCountry('de') - ->setTimezone('Europe/Berlin') - ; + $customer = new Customer('first one'); + $customer->setVisible(true); + $customer->setCountry('de'); + $customer->setTimezone('Europe/Berlin'); $em->persist($customer); $orderDate = new \DateTime('2019-11-29 14:35:17', new \DateTimeZone('Pacific/Tongatapu')); $startDate = new \DateTime('2020-01-07 18:19:20', new \DateTimeZone('Pacific/Tongatapu')); $endDate = new \DateTime('2021-03-23 00:00:01', new \DateTimeZone('Pacific/Tongatapu')); - $project = (new Project()) - ->setName('first') - ->setVisible(true) - ->setCustomer($customer) - ->setOrderDate($orderDate) - ->setStart($startDate) - ->setEnd($endDate) - ; + $project = new Project(); + $project->setName('first'); + $project->setVisible(true); + $project->setCustomer($customer); + $project->setOrderDate($orderDate); + $project->setStart($startDate); + $project->setEnd($endDate); $em->persist($project); $em->flush(); diff --git a/tests/API/Serializer/ValidationFailedExceptionErrorHandlerTest.php b/tests/API/Serializer/ValidationFailedExceptionErrorHandlerTest.php index 67123f44a..526a87b1e 100644 --- a/tests/API/Serializer/ValidationFailedExceptionErrorHandlerTest.php +++ b/tests/API/Serializer/ValidationFailedExceptionErrorHandlerTest.php @@ -16,8 +16,8 @@ use JMS\Serializer\GraphNavigatorInterface; use JMS\Serializer\JsonSerializationVisitor; use JMS\Serializer\SerializationContext; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\Security\Core\Security; use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Contracts\Translation\TranslatorInterface; diff --git a/tests/API/TimesheetControllerTest.php b/tests/API/TimesheetControllerTest.php index 9ca9e3427..ca5befd17 100644 --- a/tests/API/TimesheetControllerTest.php +++ b/tests/API/TimesheetControllerTest.php @@ -467,11 +467,19 @@ class TimesheetControllerTest extends APIControllerBaseTest $client = $this->getClientForAuthenticatedUser(User::ROLE_USER); $em = $this->getEntityManager(); - $customer = (new Customer('foo-bar-1'))->setVisible(false)->setCountry('DE')->setTimezone('Europe/Berlin'); + $customer = new Customer('foo-bar-1'); + $customer->setVisible(false); + $customer->setCountry('DE'); + $customer->setTimezone('Europe/Berlin'); $em->persist($customer); - $project = (new Project())->setName('foo-bar-2')->setVisible(true)->setCustomer($customer); + $project = new Project(); + $project->setName('foo-bar-2'); + $project->setVisible(true); + $project->setCustomer($customer); $em->persist($project); - $activity = (new Activity())->setName('foo-bar-3')->setVisible(true); + $activity = new Activity(); + $activity->setName('foo-bar-3'); + $activity->setVisible(true); $em->persist($activity); $em->flush(); @@ -493,11 +501,19 @@ class TimesheetControllerTest extends APIControllerBaseTest $client = $this->getClientForAuthenticatedUser(User::ROLE_USER); $em = $this->getEntityManager(); - $customer = (new Customer('foo-bar-1'))->setVisible(true)->setCountry('DE')->setTimezone('Europe/Berlin'); + $customer = new Customer('foo-bar-1'); + $customer->setVisible(true); + $customer->setCountry('DE'); + $customer->setTimezone('Europe/Berlin'); $em->persist($customer); - $project = (new Project())->setName('foo-bar-2')->setVisible(true)->setCustomer($customer); + $project = new Project(); + $project->setName('foo-bar-2'); + $project->setVisible(true); + $project->setCustomer($customer); $em->persist($project); - $activity = (new Activity())->setName('foo-bar-3')->setVisible(false); + $activity = new Activity(); + $activity->setName('foo-bar-3'); + $activity->setVisible(false); $em->persist($activity); $em->flush(); @@ -517,12 +533,17 @@ class TimesheetControllerTest extends APIControllerBaseTest $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $em = $this->getEntityManager(); - $customer = (new Customer('foo-bar-1'))->setCountry('DE')->setTimezone('Europe/Berlin'); + $customer = new Customer('foo-bar-1'); + $customer->setCountry('DE'); + $customer->setTimezone('Europe/Berlin'); $customer->setBillable(false); $em->persist($customer); - $project = (new Project())->setName('foo-bar-2')->setCustomer($customer); + $project = new Project(); + $project->setName('foo-bar-2'); + $project->setCustomer($customer); $em->persist($project); - $activity = (new Activity())->setName('foo-bar-3'); + $activity = new Activity(); + $activity->setName('foo-bar-3'); $em->persist($activity); $em->flush(); @@ -547,12 +568,17 @@ class TimesheetControllerTest extends APIControllerBaseTest $client = $this->getClientForAuthenticatedUser(User::ROLE_TEAMLEAD); $em = $this->getEntityManager(); - $customer = (new Customer('foo-bar-1'))->setCountry('DE')->setTimezone('Europe/Berlin'); + $customer = new Customer('foo-bar-1'); + $customer->setCountry('DE'); + $customer->setTimezone('Europe/Berlin'); $customer->setBillable(false); $em->persist($customer); - $project = (new Project())->setName('foo-bar-2')->setCustomer($customer); + $project = new Project(); + $project->setName('foo-bar-2'); + $project->setCustomer($customer); $em->persist($project); - $activity = (new Activity())->setName('foo-bar-3'); + $activity = new Activity(); + $activity->setName('foo-bar-3'); $em->persist($activity); $em->flush(); diff --git a/tests/Controller/Auth/SamlControllerTest.php b/tests/Controller/Auth/SamlControllerTest.php index 497c89fa6..37eef1b90 100644 --- a/tests/Controller/Auth/SamlControllerTest.php +++ b/tests/Controller/Auth/SamlControllerTest.php @@ -18,11 +18,11 @@ use App\Tests\Mocks\Saml\SamlAuthFactoryFactory; use App\Tests\Mocks\SystemConfigurationFactory; use OneLogin\Saml2\Auth; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\Security\Core\Security; /** * @group integration diff --git a/tests/DependencyInjection/Compiler/ExportServiceCompilerPassTest.php b/tests/DependencyInjection/Compiler/ExportServiceCompilerPassTest.php new file mode 100644 index 000000000..eeac830e1 --- /dev/null +++ b/tests/DependencyInjection/Compiler/ExportServiceCompilerPassTest.php @@ -0,0 +1,69 @@ +setParameter('kimai.export.documents', []); // TODO we could test that as well + + $definition = new Definition(ServiceExport::class); + $container->setDefinition(ServiceExport::class, $definition); + + $renderers = [CsvRenderer::class, HtmlRenderer::class]; + foreach ($renderers as $renderer) { + $container->register($renderer)->addTag(Kernel::TAG_EXPORT_RENDERER); + } + + $exporters = [PDFRenderer::class, XlsxRenderer::class]; + foreach ($exporters as $exporter) { + $container->register($exporter)->addTag(Kernel::TAG_TIMESHEET_EXPORTER); + } + + $repositories = [TimesheetExportRepository::class]; + foreach ($repositories as $repository) { + $container->register($repository)->addTag(Kernel::TAG_EXPORT_REPOSITORY); + } + + return $container; + } + + public function testCallsAreAdded(): void + { + $container = $this->getContainer(); + $sut = new ExportServiceCompilerPass(); + $sut->process($container); + + $definition = $container->findDefinition(ServiceExport::class); + $methods = $definition->getMethodCalls(); + + self::assertCount(5, $methods); + self::assertTrue($definition->hasMethodCall('addRenderer')); + self::assertTrue($definition->hasMethodCall('addTimesheetExporter')); + self::assertTrue($definition->hasMethodCall('addExportRepository')); + } +} diff --git a/tests/DependencyInjection/Compiler/InvoiceServiceCompilerPassTest.php b/tests/DependencyInjection/Compiler/InvoiceServiceCompilerPassTest.php new file mode 100644 index 000000000..6b61e35f8 --- /dev/null +++ b/tests/DependencyInjection/Compiler/InvoiceServiceCompilerPassTest.php @@ -0,0 +1,76 @@ +setDefinition(ServiceInvoice::class, $definition); + + $renderers = [DocxRenderer::class]; + foreach ($renderers as $renderer) { + $container->register($renderer)->addTag(Kernel::TAG_INVOICE_RENDERER); + } + + $numberGenerators = [DateNumberGenerator::class, ConfigurableNumberGenerator::class]; + foreach ($numberGenerators as $numberGenerator) { + $container->register($numberGenerator)->addTag(Kernel::TAG_INVOICE_NUMBER_GENERATOR); + } + + $calculators = [DefaultCalculator::class, UserInvoiceCalculator::class, ShortInvoiceCalculator::class]; + foreach ($calculators as $calculator) { + $container->register($calculator)->addTag(Kernel::TAG_INVOICE_CALCULATOR); + } + + $repositories = [TimesheetInvoiceItemRepository::class]; + foreach ($repositories as $repository) { + $container->register($repository)->addTag(Kernel::TAG_INVOICE_REPOSITORY); + } + + return $container; + } + + public function testCallsAreAdded(): void + { + $container = $this->getContainer(); + $sut = new InvoiceServiceCompilerPass(); + $sut->process($container); + + $definition = $container->findDefinition(ServiceInvoice::class); + $methods = $definition->getMethodCalls(); + + self::assertCount(7, $methods); + self::assertTrue($definition->hasMethodCall('addRenderer')); + self::assertTrue($definition->hasMethodCall('addNumberGenerator')); + self::assertTrue($definition->hasMethodCall('addCalculator')); + self::assertTrue($definition->hasMethodCall('addInvoiceItemRepository')); + } +} diff --git a/tests/DependencyInjection/Compiler/TwigContextCompilerPassTest.php b/tests/DependencyInjection/Compiler/TwigContextCompilerPassTest.php new file mode 100644 index 000000000..4a9ca45c7 --- /dev/null +++ b/tests/DependencyInjection/Compiler/TwigContextCompilerPassTest.php @@ -0,0 +1,65 @@ +setParameter('kimai.invoice.documents', []); // TODO we could test that as well + $container->setParameter('kimai.export.documents', []); // TODO we could test that as well + + $definition = new Definition('twig'); + $container->setDefinition('twig', $definition); + + $definition = new Definition('twig.loader.native_filesystem'); + $container->setDefinition('twig.loader.native_filesystem', $definition); + + $definition = new Definition(ServiceExport::class); + $container->setDefinition(ServiceExport::class, $definition); + + $definition = new Definition(Context::class); + $container->setDefinition(Context::class, $definition); + + $definition = new Definition(Configuration::class); + $container->setDefinition(Configuration::class, $definition); + + return $container; + } + + public function testCallsAreAdded(): void + { + $container = $this->getContainer(); + $sut = new TwigContextCompilerPass(); + $sut->process($container); + + $definition = $container->findDefinition('twig'); + $methods = $definition->getMethodCalls(); + + self::assertCount(2, $methods); + self::assertTrue($definition->hasMethodCall('addGlobal')); + self::assertEquals('addGlobal', $methods[0][0]); + self::assertEquals('kimai_context', $methods[0][1][0]); + self::assertEquals('addGlobal', $methods[1][0]); + self::assertEquals('kimai_config', $methods[1][1][0]); + } +} diff --git a/tests/DependencyInjection/Compiler/WidgetCompilerPassTest.php b/tests/DependencyInjection/Compiler/WidgetCompilerPassTest.php new file mode 100644 index 000000000..d3a266abe --- /dev/null +++ b/tests/DependencyInjection/Compiler/WidgetCompilerPassTest.php @@ -0,0 +1,53 @@ +setDefinition(WidgetService::class, $definition); + + $widgets = [ActiveTimesheets::class, ActiveUsersMonth::class]; + foreach ($widgets as $widget) { + $container->register($widget)->addTag(Kernel::TAG_WIDGET); + } + + return $container; + } + + public function testCallsAreAdded(): void + { + $container = $this->getContainer(); + $sut = new WidgetCompilerPass(); + $sut->process($container); + + $definition = $container->findDefinition(WidgetService::class); + $methods = $definition->getMethodCalls(); + + self::assertCount(2, $methods); + self::assertTrue($definition->hasMethodCall('registerWidget')); + } +} diff --git a/tests/Entity/CustomerTest.php b/tests/Entity/CustomerTest.php index 724d4d93f..8d836fbec 100644 --- a/tests/Entity/CustomerTest.php +++ b/tests/Entity/CustomerTest.php @@ -65,7 +65,7 @@ class CustomerTest extends AbstractEntityTest self::assertEquals('foo-bar', $sut->getName()); self::assertEquals('foo-bar', (string) $sut); - self::assertInstanceOf(Customer::class, $sut->setVisible(false)); + $sut->setVisible(false); self::assertFalse($sut->isVisible()); $sut->setVisible(false); @@ -73,7 +73,7 @@ class CustomerTest extends AbstractEntityTest $sut->setVisible(true); self::assertTrue($sut->isVisible()); - self::assertInstanceOf(Customer::class, $sut->setComment('hello world')); + $sut->setComment('hello world'); self::assertEquals('hello world', $sut->getComment()); self::assertFalse($sut->hasColor()); @@ -85,35 +85,38 @@ class CustomerTest extends AbstractEntityTest self::assertNull($sut->getColor()); self::assertFalse($sut->hasColor()); - self::assertInstanceOf(Customer::class, $sut->setCompany('test company')); + $sut->setCompany('test company'); self::assertEquals('test company', $sut->getCompany()); - self::assertInstanceOf(Customer::class, $sut->setContact('test contact')); + $sut->setContact('test contact'); self::assertEquals('test contact', $sut->getContact()); - self::assertInstanceOf(Customer::class, $sut->setPhone('0123456789')); + $sut->setPhone('0123456789'); self::assertEquals('0123456789', $sut->getPhone()); - self::assertInstanceOf(Customer::class, $sut->setFax('asdfghjkl')); + $sut->setFax('asdfghjkl'); self::assertEquals('asdfghjkl', $sut->getFax()); - self::assertInstanceOf(Customer::class, $sut->setMobile('76576534')); + $sut->setMobile('76576534'); self::assertEquals('76576534', $sut->getMobile()); - self::assertInstanceOf(Customer::class, $sut->setEmail('test@example.com')); + $sut->setEmail('test@example.com'); self::assertEquals('test@example.com', $sut->getEmail()); - self::assertInstanceOf(Customer::class, $sut->setHomepage('https://www.example.com')); + $sut->setHomepage('https://www.example.com'); self::assertEquals('https://www.example.com', $sut->getHomepage()); - self::assertInstanceOf(Customer::class, $sut->setVatId('ID 1234567890')); + $sut->setVatId('ID 1234567890'); self::assertEquals('ID 1234567890', $sut->getVatId()); - self::assertInstanceOf(Customer::class, $sut->setCountry(null)); + $sut->setCountry(null); self::assertNull($sut->getCountry()); - self::assertInstanceOf(Customer::class, $sut->setCurrency('USD')); + $sut->setCurrency('USD'); self::assertEquals('USD', $sut->getCurrency()); + + $sut->setCurrency(null); + self::assertNull($sut->getCurrency()); } public function testMetaFields() diff --git a/tests/Entity/TimesheetValidationTest.php b/tests/Entity/TimesheetValidationTest.php index 86397a8a0..dd3685f5d 100644 --- a/tests/Entity/TimesheetValidationTest.php +++ b/tests/Entity/TimesheetValidationTest.php @@ -50,11 +50,9 @@ class TimesheetValidationTest extends KernelTestCase $project->setCustomer(new Customer('foo')); $entity = new Timesheet(); - $entity - ->setUser(new User()) - ->setProject($project) - ->setBegin(new \DateTime()) - ; + $entity->setUser(new User()); + $entity->setProject($project); + $entity->setBegin(new \DateTime()); $this->assertHasViolationForField($entity, 'activity'); } @@ -62,11 +60,9 @@ class TimesheetValidationTest extends KernelTestCase public function testValidationNeedsProject() { $entity = new Timesheet(); - $entity - ->setUser(new User()) - ->setActivity(new Activity()) - ->setBegin(new \DateTime()) - ; + $entity->setUser(new User()); + $entity->setActivity(new Activity()); + $entity->setBegin(new \DateTime()); $this->assertHasViolationForField($entity, 'project'); } @@ -79,29 +75,30 @@ class TimesheetValidationTest extends KernelTestCase $activity = (new Activity())->setName('hello-world')->setProject($project); $entity = new Timesheet(); - $entity - ->setUser(new User()) - ->setActivity($activity) - ->setProject($project2) - ->setBegin(new \DateTime()) - ; + $entity->setUser(new User()); + $entity->setActivity($activity); + $entity->setProject($project2); + $entity->setBegin(new \DateTime()); $this->assertHasViolationForField($entity, 'project'); } public function testValidationCustomerInvisible() { - $customer = (new Customer('foo'))->setVisible(false); - $project = (new Project())->setName('foo')->setCustomer($customer); - $activity = (new Activity())->setName('hello-world')->setProject($project); + $customer = new Customer('foo'); + $customer->setVisible(false); + $project = new Project(); + $project->setName('foo'); + $project->setCustomer($customer); + $activity = new Activity(); + $activity->setName('hello-world'); + $activity->setProject($project); $entity = new Timesheet(); - $entity - ->setUser(new User()) - ->setActivity($activity) - ->setProject($project) - ->setBegin(new \DateTime()) - ; + $entity->setUser(new User()); + $entity->setActivity($activity); + $entity->setProject($project); + $entity->setBegin(new \DateTime()); $this->assertHasViolationForField($entity, 'customer'); } @@ -109,13 +106,11 @@ class TimesheetValidationTest extends KernelTestCase private function createStoppedTimesheet(Project $project, Activity $activity, ?int $id = null): Timesheet { $entity = new Timesheet(); - $entity - ->setUser(new User()) - ->setActivity($activity) - ->setProject($project) - ->setBegin(new \DateTime()) - ->setEnd(new \DateTime()) - ; + $entity->setUser(new User()); + $entity->setActivity($activity); + $entity->setProject($project); + $entity->setBegin(new \DateTime()); + $entity->setEnd(new \DateTime()); if ($id !== null) { $o = new \ReflectionClass($entity); @@ -130,9 +125,14 @@ class TimesheetValidationTest extends KernelTestCase public function testValidationCustomerInvisibleDoesNotTriggerOnStoppedEntities() { - $customer = (new Customer('foo'))->setVisible(false); - $project = (new Project())->setName('foo')->setCustomer($customer); - $activity = (new Activity())->setName('hello-world')->setProject($project); + $customer = new Customer('foo'); + $customer->setVisible(false); + $project = new Project(); + $project->setName('foo'); + $project->setCustomer($customer); + $activity = new Activity(); + $activity->setName('hello-world'); + $activity->setProject($project); $entity = $this->createStoppedTimesheet($project, $activity, 99); @@ -141,9 +141,14 @@ class TimesheetValidationTest extends KernelTestCase public function testValidationCustomerInvisibleDoesTriggerOnNewEntities() { - $customer = (new Customer('foo'))->setVisible(false); - $project = (new Project())->setName('foo')->setCustomer($customer); - $activity = (new Activity())->setName('hello-world')->setProject($project); + $customer = new Customer('foo'); + $customer->setVisible(false); + $project = new Project(); + $project->setName('foo'); + $project->setCustomer($customer); + $activity = new Activity(); + $activity->setName('hello-world'); + $activity->setProject($project); $entity = $this->createStoppedTimesheet($project, $activity); @@ -157,12 +162,10 @@ class TimesheetValidationTest extends KernelTestCase $activity = (new Activity())->setName('hello-world')->setProject($project); $entity = new Timesheet(); - $entity - ->setUser(new User()) - ->setActivity($activity) - ->setProject($project) - ->setBegin(new \DateTime()) - ; + $entity->setUser(new User()); + $entity->setActivity($activity); + $entity->setProject($project); + $entity->setBegin(new \DateTime()); $this->assertHasViolationForField($entity, 'project'); } @@ -196,12 +199,10 @@ class TimesheetValidationTest extends KernelTestCase $activity = (new Activity())->setName('hello-world')->setProject($project)->setVisible(false); $entity = new Timesheet(); - $entity - ->setUser(new User()) - ->setActivity($activity) - ->setProject($project) - ->setBegin(new \DateTime()) - ; + $entity->setUser(new User()); + $entity->setActivity($activity); + $entity->setProject($project); + $entity->setBegin(new \DateTime()); $this->assertHasViolationForField($entity, 'activity'); } @@ -209,8 +210,13 @@ class TimesheetValidationTest extends KernelTestCase public function testValidationActivityInvisibleDoesNotTriggerOnStoppedEntities() { $customer = new Customer('foo'); - $project = (new Project())->setName('foo')->setCustomer($customer); - $activity = (new Activity())->setName('hello-world')->setProject($project)->setVisible(false); + $project = new Project(); + $project->setName('foo'); + $project->setCustomer($customer); + $activity = new Activity(); + $activity->setName('hello-world'); + $activity->setProject($project); + $activity->setVisible(false); $entity = $this->createStoppedTimesheet($project, $activity, 2); @@ -220,8 +226,13 @@ class TimesheetValidationTest extends KernelTestCase public function testValidationActivityInvisibleDoesTriggerOnNewEntities() { $customer = new Customer('foo'); - $project = (new Project())->setName('foo')->setCustomer($customer); - $activity = (new Activity())->setName('hello-world')->setProject($project)->setVisible(false); + $project = new Project(); + $project->setName('foo'); + $project->setCustomer($customer); + $activity = new Activity(); + $activity->setName('hello-world'); + $activity->setProject($project); + $activity->setVisible(false); $entity = $this->createStoppedTimesheet($project, $activity); diff --git a/tests/Export/Renderer/AbstractRendererTest.php b/tests/Export/Renderer/AbstractRendererTest.php index 46969cbe2..f92e179a5 100644 --- a/tests/Export/Renderer/AbstractRendererTest.php +++ b/tests/Export/Renderer/AbstractRendererTest.php @@ -30,10 +30,10 @@ use App\Export\TimesheetExportInterface; use App\Repository\Query\TimesheetQuery; use App\Twig\LocaleFormatExtensions; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\Type\TextType; -use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; abstract class AbstractRendererTest extends KernelTestCase diff --git a/tests/Export/Timesheet/AbstractRendererTest.php b/tests/Export/Timesheet/AbstractRendererTest.php index 503f1dce4..25b6fbe98 100644 --- a/tests/Export/Timesheet/AbstractRendererTest.php +++ b/tests/Export/Timesheet/AbstractRendererTest.php @@ -29,10 +29,10 @@ use App\Export\TimesheetExportInterface; use App\Repository\Query\TimesheetQuery; use App\Twig\LocaleFormatExtensions; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Core\Type\TextType; -use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; abstract class AbstractRendererTest extends KernelTestCase diff --git a/tests/Form/Type/QuickEntryTimesheetTypeTest.php b/tests/Form/Type/QuickEntryTimesheetTypeTest.php index 1bf23d654..ebfb04486 100644 --- a/tests/Form/Type/QuickEntryTimesheetTypeTest.php +++ b/tests/Form/Type/QuickEntryTimesheetTypeTest.php @@ -12,9 +12,9 @@ namespace App\Tests\Form\Type; use App\Entity\Timesheet; use App\Entity\User; use App\Form\Type\QuickEntryTimesheetType; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Form\PreloadedExtension; use Symfony\Component\Form\Test\TypeTestCase; -use Symfony\Component\Security\Core\Security; /** * @covers \App\Form\Type\QuickEntryTimesheetType diff --git a/tests/Twig/LocaleFormatExtensionsTest.php b/tests/Twig/LocaleFormatExtensionsTest.php index 76f327c93..eff472ea3 100644 --- a/tests/Twig/LocaleFormatExtensionsTest.php +++ b/tests/Twig/LocaleFormatExtensionsTest.php @@ -15,8 +15,8 @@ use App\Entity\User; use App\Entity\UserPreference; use App\Twig\LocaleFormatExtensions; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Intl\Util\IntlTestHelper; -use Symfony\Component\Security\Core\Security; use Twig\TwigFilter; use Twig\TwigFunction; use Twig\TwigTest; diff --git a/tests/Twig/Runtime/WidgetExtensionTest.php b/tests/Twig/Runtime/WidgetExtensionTest.php index 11c2b37dc..8eb9b7fb0 100644 --- a/tests/Twig/Runtime/WidgetExtensionTest.php +++ b/tests/Twig/Runtime/WidgetExtensionTest.php @@ -14,10 +14,10 @@ use App\Twig\Runtime\WidgetExtension; use App\Widget\Type\More; use App\Widget\WidgetService; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Security; use Twig\Environment; /** diff --git a/tests/Validator/Constraints/ColorChoicesValidatorTest.php b/tests/Validator/Constraints/ColorChoicesValidatorTest.php index 806bf11c5..8e5617b08 100644 --- a/tests/Validator/Constraints/ColorChoicesValidatorTest.php +++ b/tests/Validator/Constraints/ColorChoicesValidatorTest.php @@ -18,10 +18,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\ColorChoices * @covers \App\Validator\Constraints\ColorChoicesValidator + * @extends ConstraintValidatorTestCase */ class ColorChoicesValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): ColorChoicesValidator { return new ColorChoicesValidator(); } diff --git a/tests/Validator/Constraints/DateTimeFormatValidatorTest.php b/tests/Validator/Constraints/DateTimeFormatValidatorTest.php index dfc0e414b..0de579daf 100644 --- a/tests/Validator/Constraints/DateTimeFormatValidatorTest.php +++ b/tests/Validator/Constraints/DateTimeFormatValidatorTest.php @@ -18,10 +18,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\DateTimeFormat * @covers \App\Validator\Constraints\DateTimeFormatValidator + * @extends ConstraintValidatorTestCase */ class DateTimeFormatValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): DateTimeFormatValidator { return new DateTimeFormatValidator(); } diff --git a/tests/Validator/Constraints/DurationValidatorTest.php b/tests/Validator/Constraints/DurationValidatorTest.php index 648aebd0d..7a766918a 100644 --- a/tests/Validator/Constraints/DurationValidatorTest.php +++ b/tests/Validator/Constraints/DurationValidatorTest.php @@ -19,10 +19,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\Duration * @covers \App\Validator\Constraints\DurationValidator + * @extends ConstraintValidatorTestCase */ class DurationValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): DurationValidator { return new DurationValidator(); } diff --git a/tests/Validator/Constraints/HexColorValidatorTest.php b/tests/Validator/Constraints/HexColorValidatorTest.php index 3be0f1a97..80fcc40b3 100644 --- a/tests/Validator/Constraints/HexColorValidatorTest.php +++ b/tests/Validator/Constraints/HexColorValidatorTest.php @@ -18,10 +18,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\HexColor * @covers \App\Validator\Constraints\HexColorValidator + * @extends ConstraintValidatorTestCase */ class HexColorValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): HexColorValidator { return new HexColorValidator(); } diff --git a/tests/Validator/Constraints/ProjectValidatorTest.php b/tests/Validator/Constraints/ProjectValidatorTest.php index cd21e0d27..7e2049462 100644 --- a/tests/Validator/Constraints/ProjectValidatorTest.php +++ b/tests/Validator/Constraints/ProjectValidatorTest.php @@ -19,10 +19,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\Project * @covers \App\Validator\Constraints\ProjectValidator + * @extends ConstraintValidatorTestCase */ class ProjectValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): ProjectValidator { return new ProjectValidator(); } diff --git a/tests/Validator/Constraints/QuickEntryModelValidatorTest.php b/tests/Validator/Constraints/QuickEntryModelValidatorTest.php index e1e71d0ee..ceb7cf850 100644 --- a/tests/Validator/Constraints/QuickEntryModelValidatorTest.php +++ b/tests/Validator/Constraints/QuickEntryModelValidatorTest.php @@ -22,10 +22,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\QuickEntryModel * @covers \App\Validator\Constraints\QuickEntryModelValidator + * @extends ConstraintValidatorTestCase */ class QuickEntryModelValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): QuickEntryModelValidator { return new QuickEntryModelValidator(); } diff --git a/tests/Validator/Constraints/QuickEntryTimesheetValidatorTest.php b/tests/Validator/Constraints/QuickEntryTimesheetValidatorTest.php index 31dc87920..1d37f3c6f 100644 --- a/tests/Validator/Constraints/QuickEntryTimesheetValidatorTest.php +++ b/tests/Validator/Constraints/QuickEntryTimesheetValidatorTest.php @@ -14,23 +14,24 @@ use App\Entity\Timesheet; use App\Validator\Constraints\QuickEntryTimesheet; use App\Validator\Constraints\QuickEntryTimesheetValidator; use App\Validator\Constraints\TimesheetBasic; -use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\ConstraintValidatorInterface; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\QuickEntryTimesheet * @covers \App\Validator\Constraints\QuickEntryTimesheetValidator + * @extends ConstraintValidatorTestCase */ class QuickEntryTimesheetValidatorTest extends ConstraintValidatorTestCase { - protected function createConstraint(): Constraint + protected function createConstraint(): QuickEntryTimesheet { return new QuickEntryTimesheet(); } - protected function createValidator() + protected function createValidator(): ConstraintValidatorInterface { return new QuickEntryTimesheetValidator([new TimesheetBasic()]); } diff --git a/tests/Validator/Constraints/RoleNameValidatorTest.php b/tests/Validator/Constraints/RoleNameValidatorTest.php index 13a887af3..f92475196 100644 --- a/tests/Validator/Constraints/RoleNameValidatorTest.php +++ b/tests/Validator/Constraints/RoleNameValidatorTest.php @@ -20,6 +20,7 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\RoleName * @covers \App\Validator\Constraints\RoleNameValidator + * @extends ConstraintValidatorTestCase */ class RoleNameValidatorTest extends ConstraintValidatorTestCase { diff --git a/tests/Validator/Constraints/RoleValidatorTest.php b/tests/Validator/Constraints/RoleValidatorTest.php index 43ca5dcc5..e55ffcc31 100644 --- a/tests/Validator/Constraints/RoleValidatorTest.php +++ b/tests/Validator/Constraints/RoleValidatorTest.php @@ -20,10 +20,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\Role * @covers \App\Validator\Constraints\RoleValidator + * @extends ConstraintValidatorTestCase */ class RoleValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): RoleValidator { $factory = new RoleServiceFactory($this); $roleService = $factory->create(); diff --git a/tests/Validator/Constraints/TeamValidatorTest.php b/tests/Validator/Constraints/TeamValidatorTest.php index ce041c5ef..6a0f54676 100644 --- a/tests/Validator/Constraints/TeamValidatorTest.php +++ b/tests/Validator/Constraints/TeamValidatorTest.php @@ -21,10 +21,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\Team * @covers \App\Validator\Constraints\TeamValidator + * @extends ConstraintValidatorTestCase */ class TeamValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TeamValidator { return new TeamValidator(); } @@ -33,7 +34,7 @@ class TeamValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate('foo', new NotBlank()); + $this->validator->validate('foo', new NotBlank()); // @phpstan-ignore-line } public function testMissingTeamlead() diff --git a/tests/Validator/Constraints/TimeFormatValidatorTest.php b/tests/Validator/Constraints/TimeFormatValidatorTest.php index 4745e61d6..e21af9ae6 100644 --- a/tests/Validator/Constraints/TimeFormatValidatorTest.php +++ b/tests/Validator/Constraints/TimeFormatValidatorTest.php @@ -19,10 +19,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimeFormat * @covers \App\Validator\Constraints\TimeFormatValidator + * @extends ConstraintValidatorTestCase */ class TimeFormatValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimeFormatValidator { return new TimeFormatValidator(); } diff --git a/tests/Validator/Constraints/TimesheetBasicValidatorTest.php b/tests/Validator/Constraints/TimesheetBasicValidatorTest.php index 72c29297b..e411e950d 100644 --- a/tests/Validator/Constraints/TimesheetBasicValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetBasicValidatorTest.php @@ -23,15 +23,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetBasic * @covers \App\Validator\Constraints\TimesheetBasicValidator + * @extends ConstraintValidatorTestCase */ class TimesheetBasicValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetBasicValidator { return $this->createMyValidator(); } - protected function createMyValidator() + protected function createMyValidator(): TimesheetBasicValidator { $configuration = SystemConfigurationFactory::createStub(['timesheet' => ['rules' => ['require_activity' => true]]]); diff --git a/tests/Validator/Constraints/TimesheetBudgetUsedValidatorTest.php b/tests/Validator/Constraints/TimesheetBudgetUsedValidatorTest.php index 53c6cf221..1f311af51 100644 --- a/tests/Validator/Constraints/TimesheetBudgetUsedValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetBudgetUsedValidatorTest.php @@ -40,10 +40,14 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetBudgetUsed * @covers \App\Validator\Constraints\TimesheetBudgetUsedValidator + * @extends ConstraintValidatorTestCase */ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator(bool $isAllowed = false, ?ActivityBudgetStatisticModel $activityStatisticModel = null, ?ProjectBudgetStatisticModel $projectStatisticModel = null, ?CustomerBudgetStatisticModel $customerStatisticModel = null, ?array $rawData = null, ?Rate $rate = null) + /** + * @param array|null $rawData + */ + protected function createValidator(bool $isAllowed = false, ?ActivityBudgetStatisticModel $activityStatisticModel = null, ?ProjectBudgetStatisticModel $projectStatisticModel = null, ?CustomerBudgetStatisticModel $customerStatisticModel = null, ?array $rawData = null, ?Rate $rate = null): TimesheetBudgetUsedValidator { $configuration = SystemConfigurationFactory::createStub(['timesheet' => ['rules' => ['allow_overbooking_budget' => $isAllowed]]]); @@ -117,7 +121,7 @@ class TimesheetBudgetUsedValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate('foo', new TimesheetBudgetUsed()); + $this->validator->validate('foo', new TimesheetBudgetUsed()); // @phpstan-ignore-line } public function testWithMissingEnd() diff --git a/tests/Validator/Constraints/TimesheetExportedValidatorTest.php b/tests/Validator/Constraints/TimesheetExportedValidatorTest.php index 14e2ded23..00a4a1841 100644 --- a/tests/Validator/Constraints/TimesheetExportedValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetExportedValidatorTest.php @@ -13,7 +13,7 @@ use App\Entity\Timesheet; use App\Entity\User; use App\Validator\Constraints\TimesheetExported; use App\Validator\Constraints\TimesheetExportedValidator; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -21,15 +21,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetExported * @covers \App\Validator\Constraints\TimesheetExportedValidator + * @extends ConstraintValidatorTestCase */ class TimesheetExportedValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetExportedValidator { return $this->createMyValidator(true); } - protected function createMyValidator(bool $allowEdit) + protected function createMyValidator(bool $allowEdit): TimesheetExportedValidator { $auth = $this->createMock(Security::class); $auth->method('getUser')->willReturn(new User()); @@ -58,7 +59,7 @@ class TimesheetExportedValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetExported(['message' => 'myMessage'])); + $this->validator->validate(new NotBlank(), new TimesheetExported(['message' => 'myMessage'])); // @phpstan-ignore-line } public function testTriggersOnMissingPermission() diff --git a/tests/Validator/Constraints/TimesheetFutureTimesValidatorTest.php b/tests/Validator/Constraints/TimesheetFutureTimesValidatorTest.php index 1db91c94d..8825a8557 100644 --- a/tests/Validator/Constraints/TimesheetFutureTimesValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetFutureTimesValidatorTest.php @@ -21,15 +21,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetFutureTimes * @covers \App\Validator\Constraints\TimesheetFutureTimesValidator + * @extends ConstraintValidatorTestCase */ class TimesheetFutureTimesValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetFutureTimesValidator { return $this->createMyValidator(false); } - protected function createMyValidator(bool $allowFutureTimes = false) + protected function createMyValidator(bool $allowFutureTimes = false): TimesheetFutureTimesValidator { $loader = $this->createMock(ConfigLoaderInterface::class); $config = SystemConfigurationFactory::create($loader, [ @@ -59,7 +60,7 @@ class TimesheetFutureTimesValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetFutureTimes(['message' => 'myMessage'])); + $this->validator->validate(new NotBlank(), new TimesheetFutureTimes(['message' => 'myMessage'])); // @phpstan-ignore-line } public function testFutureBeginIsDisallowed() diff --git a/tests/Validator/Constraints/TimesheetLockdownValidatorTest.php b/tests/Validator/Constraints/TimesheetLockdownValidatorTest.php index 2263a4c0a..23be83d30 100644 --- a/tests/Validator/Constraints/TimesheetLockdownValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetLockdownValidatorTest.php @@ -16,7 +16,7 @@ use App\Tests\Mocks\SystemConfigurationFactory; use App\Timesheet\LockdownService; use App\Validator\Constraints\TimesheetLockdown; use App\Validator\Constraints\TimesheetLockdownValidator; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -24,15 +24,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetLockdown * @covers \App\Validator\Constraints\TimesheetLockdownValidator + * @extends ConstraintValidatorTestCase */ class TimesheetLockdownValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetLockdownValidator { return $this->createMyValidator(false, false, null, null, null); } - protected function createMyValidator(bool $allowOverwriteFull, bool $allowOverwriteGrace, ?string $start, ?string $end, ?string $grace) + protected function createMyValidator(bool $allowOverwriteFull, bool $allowOverwriteGrace, ?string $start, ?string $end, ?string $grace): TimesheetLockdownValidator { $auth = $this->createMock(Security::class); $auth->method('getUser')->willReturn(new User()); @@ -74,7 +75,7 @@ class TimesheetLockdownValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetLockdown(['message' => 'myMessage'])); + $this->validator->validate(new NotBlank(), new TimesheetLockdown(['message' => 'myMessage'])); // @phpstan-ignore-line } public function testValidatorWithoutNowConstraint() diff --git a/tests/Validator/Constraints/TimesheetLongRunningValidatorTest.php b/tests/Validator/Constraints/TimesheetLongRunningValidatorTest.php index b18dd6ca6..33e138c41 100644 --- a/tests/Validator/Constraints/TimesheetLongRunningValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetLongRunningValidatorTest.php @@ -21,15 +21,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetLongRunning * @covers \App\Validator\Constraints\TimesheetLongRunningValidator + * @extends ConstraintValidatorTestCase */ class TimesheetLongRunningValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetLongRunningValidator { return $this->createMyValidator(120); } - protected function createMyValidator(int $minutes) + protected function createMyValidator(int $minutes): TimesheetLongRunningValidator { $loader = $this->createMock(ConfigLoaderInterface::class); $config = SystemConfigurationFactory::create($loader, [ @@ -54,7 +55,7 @@ class TimesheetLongRunningValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetLongRunning(['message' => 'myMessage'])); + $this->validator->validate(new NotBlank(), new TimesheetLongRunning(['message' => 'myMessage'])); // @phpstan-ignore-line } public function testLongRunningTriggers() diff --git a/tests/Validator/Constraints/TimesheetMultiUpdateValidatorTest.php b/tests/Validator/Constraints/TimesheetMultiUpdateValidatorTest.php index 52577501b..442c7976d 100644 --- a/tests/Validator/Constraints/TimesheetMultiUpdateValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetMultiUpdateValidatorTest.php @@ -22,10 +22,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetMultiUpdate * @covers \App\Validator\Constraints\TimesheetMultiUpdateValidator + * @extends ConstraintValidatorTestCase */ class TimesheetMultiUpdateValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator($isGranted = true) + protected function createValidator(): TimesheetMultiUpdateValidator { return new TimesheetMultiUpdateValidator(); } diff --git a/tests/Validator/Constraints/TimesheetMultiUserValidatorTest.php b/tests/Validator/Constraints/TimesheetMultiUserValidatorTest.php index 132f77076..09ee4e50f 100644 --- a/tests/Validator/Constraints/TimesheetMultiUserValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetMultiUserValidatorTest.php @@ -19,10 +19,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetMultiUser * @covers \App\Validator\Constraints\TimesheetMultiUserValidator + * @extends ConstraintValidatorTestCase */ class TimesheetMultiUserValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator($isGranted = true) + protected function createValidator(): TimesheetMultiUserValidator { return new TimesheetMultiUserValidator(); } diff --git a/tests/Validator/Constraints/TimesheetOverlappingValidatorTest.php b/tests/Validator/Constraints/TimesheetOverlappingValidatorTest.php index cab1c5c4a..0dbc1fbff 100644 --- a/tests/Validator/Constraints/TimesheetOverlappingValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetOverlappingValidatorTest.php @@ -22,15 +22,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetOverlapping * @covers \App\Validator\Constraints\TimesheetOverlappingValidator + * @extends ConstraintValidatorTestCase */ class TimesheetOverlappingValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetOverlappingValidator { return $this->createMyValidator(false, true); } - protected function createMyValidator(bool $allowOverlappingRecords = false, bool $hasRecords = true) + protected function createMyValidator(bool $allowOverlappingRecords = false, bool $hasRecords = true): TimesheetOverlappingValidator { $loader = $this->createMock(ConfigLoaderInterface::class); $config = SystemConfigurationFactory::create($loader, [ @@ -57,7 +58,7 @@ class TimesheetOverlappingValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetOverlapping(['message' => 'myMessage'])); + $this->validator->validate(new NotBlank(), new TimesheetOverlapping(['message' => 'myMessage'])); // @phpstan-ignore-line } public function testOverlappingDisallowedWithRecords() diff --git a/tests/Validator/Constraints/TimesheetRestartValidatorTest.php b/tests/Validator/Constraints/TimesheetRestartValidatorTest.php index 539c9f301..2e1605fb1 100644 --- a/tests/Validator/Constraints/TimesheetRestartValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetRestartValidatorTest.php @@ -18,7 +18,7 @@ use App\Tests\Mocks\TrackingModeServiceFactory; use App\Validator\Constraints\TimesheetOverlapping; use App\Validator\Constraints\TimesheetRestart; use App\Validator\Constraints\TimesheetRestartValidator; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; @@ -26,15 +26,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetRestart * @covers \App\Validator\Constraints\TimesheetRestartValidator + * @extends ConstraintValidatorTestCase */ class TimesheetRestartValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetRestartValidator { return $this->createMyValidator(false, 'default'); } - protected function createMyValidator(bool $allowed, string $trackingMode) + protected function createMyValidator(bool $allowed, string $trackingMode): TimesheetRestartValidator { $auth = $this->createMock(Security::class); $auth->method('getUser')->willReturn(new User()); @@ -56,7 +57,7 @@ class TimesheetRestartValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetOverlapping(['message' => 'myMessage'])); + $this->validator->validate(new NotBlank(), new TimesheetOverlapping(['message' => 'myMessage'])); // @phpstan-ignore-line } /** diff --git a/tests/Validator/Constraints/TimesheetValidatorTest.php b/tests/Validator/Constraints/TimesheetValidatorTest.php index 3d73570f9..ce1230cce 100644 --- a/tests/Validator/Constraints/TimesheetValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetValidatorTest.php @@ -19,15 +19,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\Timesheet * @covers \App\Validator\Constraints\TimesheetValidator + * @extends ConstraintValidatorTestCase */ class TimesheetValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetValidator { return $this->createMyValidator(); } - protected function createMyValidator(bool $isGranted = true) + protected function createMyValidator(bool $isGranted = true): TimesheetValidator { return new TimesheetValidator([]); } @@ -43,6 +44,6 @@ class TimesheetValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetConstraint(['message' => 'myMessage'])); + $this->validator->validate(new NotBlank(), new TimesheetConstraint(['message' => 'myMessage'])); // @phpstan-ignore-line } } diff --git a/tests/Validator/Constraints/TimesheetZeroDurationValidatorTest.php b/tests/Validator/Constraints/TimesheetZeroDurationValidatorTest.php index b2e43b22f..9ce027f6f 100644 --- a/tests/Validator/Constraints/TimesheetZeroDurationValidatorTest.php +++ b/tests/Validator/Constraints/TimesheetZeroDurationValidatorTest.php @@ -21,15 +21,16 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\TimesheetZeroDuration * @covers \App\Validator\Constraints\TimesheetZeroDurationValidator + * @extends ConstraintValidatorTestCase */ class TimesheetZeroDurationValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): TimesheetZeroDurationValidator { return $this->createMyValidator(false); } - protected function createMyValidator(bool $allowZeroDuration = false) + protected function createMyValidator(bool $allowZeroDuration = false): TimesheetZeroDurationValidator { $loader = $this->createMock(ConfigLoaderInterface::class); $config = SystemConfigurationFactory::create($loader, [ @@ -54,7 +55,7 @@ class TimesheetZeroDurationValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate(new NotBlank(), new TimesheetZeroDuration(['message' => 'Duration cannot be zero.'])); + $this->validator->validate(new NotBlank(), new TimesheetZeroDuration(['message' => 'Duration cannot be zero.'])); // @phpstan-ignore-line } private function prepareTimesheet() diff --git a/tests/Validator/Constraints/UserValidatorTest.php b/tests/Validator/Constraints/UserValidatorTest.php index 9905a66c2..a65f8f3d6 100644 --- a/tests/Validator/Constraints/UserValidatorTest.php +++ b/tests/Validator/Constraints/UserValidatorTest.php @@ -21,10 +21,11 @@ use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @covers \App\Validator\Constraints\User * @covers \App\Validator\Constraints\UserValidator + * @extends ConstraintValidatorTestCase */ class UserValidatorTest extends ConstraintValidatorTestCase { - protected function createValidator() + protected function createValidator(): UserValidator { $userService = $this->createMock(UserService::class); @@ -35,19 +36,19 @@ class UserValidatorTest extends ConstraintValidatorTestCase { $this->expectException(UnexpectedTypeException::class); - $this->validator->validate('foo', new NotBlank()); + $this->validator->validate('foo', new NotBlank()); // @phpstan-ignore-line } public function testNullIsValid() { - $this->validator->validate(null, new User(['message' => 'myMessage'])); + $this->validator->validate(null, new User(['message' => 'myMessage'])); // @phpstan-ignore-line $this->assertNoViolation(); } public function testNonUserIsValid() { - $this->validator->validate(new TestUserEntity(), new User(['message' => 'myMessage'])); + $this->validator->validate(new TestUserEntity(), new User(['message' => 'myMessage'])); // @phpstan-ignore-line $this->assertNoViolation(); } diff --git a/tests/phpstan.neon b/tests/phpstan.neon index 4e907935a..7645d611c 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -10982,11 +10982,6 @@ parameters: count: 6 path: Utils/StringHelperTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\ColorChoicesValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/ColorChoicesValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\ColorChoicesValidatorTest\\:\\:getInvalidColors\\(\\) has no return type specified\\.$#" count: 1 @@ -11012,11 +11007,6 @@ parameters: count: 1 path: Validator/Constraints/ColorChoicesValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\DateTimeFormatValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/DateTimeFormatValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\DateTimeFormatValidatorTest\\:\\:getInvalidData\\(\\) has no return type specified\\.$#" count: 1 @@ -11042,11 +11032,6 @@ parameters: count: 1 path: Validator/Constraints/DateTimeFormatValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\DurationValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/DurationValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\DurationValidatorTest\\:\\:getInvalidData\\(\\) has no return type specified\\.$#" count: 1 @@ -11082,11 +11067,6 @@ parameters: count: 1 path: Validator/Constraints/DurationValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\HexColorValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/HexColorValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\HexColorValidatorTest\\:\\:getInvalidColors\\(\\) has no return type specified\\.$#" count: 1 @@ -11117,11 +11097,6 @@ parameters: count: 1 path: Validator/Constraints/HexColorValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\ProjectValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/ProjectValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\ProjectValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11137,11 +11112,6 @@ parameters: count: 1 path: Validator/Constraints/ProjectValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\QuickEntryModelValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/QuickEntryModelValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\QuickEntryModelValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11177,11 +11147,6 @@ parameters: count: 1 path: Validator/Constraints/QuickEntryModelValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\QuickEntryTimesheetValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/QuickEntryTimesheetValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\QuickEntryTimesheetValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11202,11 +11167,6 @@ parameters: count: 1 path: Validator/Constraints/RoleValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\RoleValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/RoleValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\RoleValidatorTest\\:\\:getInvalidRoles\\(\\) has no return type specified\\.$#" count: 1 @@ -11237,11 +11197,6 @@ parameters: count: 1 path: Validator/Constraints/RoleValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TeamValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TeamValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TeamValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11252,11 +11207,6 @@ parameters: count: 1 path: Validator/Constraints/TeamValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimeFormatValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimeFormatValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimeFormatValidatorTest\\:\\:getInvalidTimes\\(\\) has no return type specified\\.$#" count: 1 @@ -11292,16 +11242,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetBasicValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetBasicValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetBasicValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetBasicValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetBasicValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetBasicValidatorTest\\:\\:getProjectStartEndTestData\\(\\) has no return type specified\\.$#" count: 1 @@ -11357,16 +11297,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetBasicValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetBudgetUsedValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetBudgetUsedValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetBudgetUsedValidatorTest\\:\\:createValidator\\(\\) has parameter \\$rawData with no value type specified in iterable type array\\.$#" - count: 1 - path: Validator/Constraints/TimesheetBudgetUsedValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetBudgetUsedValidatorTest\\:\\:getViolationTestData\\(\\) has no return type specified\\.$#" count: 1 @@ -11422,16 +11352,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetBudgetUsedValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetExportedValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetExportedValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetExportedValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetExportedValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetExportedValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11467,16 +11387,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetExportedValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetFutureTimesValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetFutureTimesValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetFutureTimesValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetFutureTimesValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetFutureTimesValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11497,16 +11407,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetFutureTimesValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetLockdownValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetLockdownValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetLockdownValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetLockdownValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetLockdownValidatorTest\\:\\:getConfigTestData\\(\\) has no return type specified\\.$#" count: 1 @@ -11557,16 +11457,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetLockdownValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetLongRunningValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetLongRunningValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetLongRunningValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetLongRunningValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetLongRunningValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11612,16 +11502,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetLongRunningValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetMultiUpdateValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetMultiUpdateValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetMultiUpdateValidatorTest\\:\\:createValidator\\(\\) has parameter \\$isGranted with no type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetMultiUpdateValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetMultiUpdateValidatorTest\\:\\:testActivityWithoutProject\\(\\) has no return type specified\\.$#" count: 1 @@ -11652,16 +11532,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetMultiUpdateValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetMultiUserValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetMultiUserValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetMultiUserValidatorTest\\:\\:createValidator\\(\\) has parameter \\$isGranted with no type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetMultiUserValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetMultiUserValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11672,16 +11542,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetMultiUserValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetOverlappingValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetOverlappingValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetOverlappingValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetOverlappingValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetOverlappingValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11712,16 +11572,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetOverlappingValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetRestartValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetRestartValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetRestartValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetRestartValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetRestartValidatorTest\\:\\:getTestData\\(\\) has no return type specified\\.$#" count: 1 @@ -11742,16 +11592,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetRestartValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1 @@ -11762,16 +11602,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetZeroDurationValidatorTest\\:\\:createMyValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetZeroDurationValidatorTest.php - - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetZeroDurationValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/TimesheetZeroDurationValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\TimesheetZeroDurationValidatorTest\\:\\:prepareTimesheet\\(\\) has no return type specified\\.$#" count: 1 @@ -11797,11 +11627,6 @@ parameters: count: 1 path: Validator/Constraints/TimesheetZeroDurationValidatorTest.php - - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\UserValidatorTest\\:\\:createValidator\\(\\) has no return type specified\\.$#" - count: 1 - path: Validator/Constraints/UserValidatorTest.php - - message: "#^Method App\\\\Tests\\\\Validator\\\\Constraints\\\\UserValidatorTest\\:\\:testConstraintIsInvalid\\(\\) has no return type specified\\.$#" count: 1