From e9a55ab7f56a75746916dc93cc69174f4855fef7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 1 Mar 2024 13:35:11 +0100 Subject: [PATCH] unit tests working --- composer.lock | 526 +++++++++--------- src/ApiResource/CommentApi.php | 4 +- src/ApiResource/ContactApi.php | 5 +- src/ApiResource/PartnerApi.php | 3 +- src/ApiResource/PostingApi.php | 16 +- src/ApiResource/UserApi.php | 7 +- src/Entity/Comment.php | 18 +- src/Entity/Contact.php | 14 +- src/Entity/MediaObject.php | 1 + src/Entity/Posting.php | 5 + .../AuthenticationSuccessListener.php | 2 +- src/Factory/PostingFactory.php | 2 +- src/Mapper/CommentApiToEntityMapper.php | 26 +- src/Mapper/CommentEntityToApiMapper.php | 7 +- src/Mapper/ContactApiToEntityMapper.php | 4 +- src/Mapper/ContactEntityToApiMapper.php | 8 +- src/Mapper/PartnerApiToEntityMapper.php | 13 +- src/Mapper/PartnerEntityToApiMapper.php | 2 +- src/Mapper/PostingApiToEntityMapper.php | 4 +- src/Mapper/UserApiToEntityMapper.php | 4 +- src/Mapper/UserEntityToApiMapper.php | 4 +- src/Voter/CommentApiVoter.php | 46 ++ src/Voter/PostingApiVoter.php | 8 +- src/Voter/UserApiVoter.php | 3 +- tests/Functional/CommentResourceTest.php | 78 +++ tests/Functional/ContactResourceTest.php | 82 +++ tests/Functional/MediaObjectResourceTest.php | 66 +++ tests/Functional/PartnerResourceTest.php | 79 +++ tests/Functional/PostingResourceTest.php | 23 +- tests/Functional/UserResourceTest.php | 23 +- tests/fixtures/1176.png | Bin 0 -> 3989 bytes 31 files changed, 713 insertions(+), 370 deletions(-) create mode 100644 src/Voter/CommentApiVoter.php create mode 100644 tests/Functional/CommentResourceTest.php create mode 100644 tests/Functional/ContactResourceTest.php create mode 100644 tests/Functional/MediaObjectResourceTest.php create mode 100644 tests/Functional/PartnerResourceTest.php create mode 100644 tests/fixtures/1176.png diff --git a/composer.lock b/composer.lock index a0c4f34..c0b2f2c 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "api-platform/core", - "version": "v3.2.13", + "version": "v3.2.15", "source": { "type": "git", "url": "https://github.com/api-platform/core.git", - "reference": "3b42bafcccd2b530ca7bb920c7a3b9dc249d76ec" + "reference": "42215cf81e477cbf8ff872cf3c00822c9a1b79f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/api-platform/core/zipball/3b42bafcccd2b530ca7bb920c7a3b9dc249d76ec", - "reference": "3b42bafcccd2b530ca7bb920c7a3b9dc249d76ec", + "url": "https://api.github.com/repos/api-platform/core/zipball/42215cf81e477cbf8ff872cf3c00822c9a1b79f8", + "reference": "42215cf81e477cbf8ff872cf3c00822c9a1b79f8", "shasum": "" }, "require": { @@ -168,9 +168,9 @@ ], "support": { "issues": "https://github.com/api-platform/core/issues", - "source": "https://github.com/api-platform/core/tree/v3.2.13" + "source": "https://github.com/api-platform/core/tree/v3.2.15" }, - "time": "2024-02-01T14:41:52+00:00" + "time": "2024-02-29T14:55:13+00:00" }, { "name": "doctrine/cache", @@ -267,16 +267,16 @@ }, { "name": "doctrine/collections", - "version": "2.1.4", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "72328a11443a0de79967104ad36ba7b30bded134" + "reference": "07e16cd7b80a2cffed99e36b541876af172f0257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/72328a11443a0de79967104ad36ba7b30bded134", - "reference": "72328a11443a0de79967104ad36ba7b30bded134", + "url": "https://api.github.com/repos/doctrine/collections/zipball/07e16cd7b80a2cffed99e36b541876af172f0257", + "reference": "07e16cd7b80a2cffed99e36b541876af172f0257", "shasum": "" }, "require": { @@ -288,7 +288,7 @@ "ext-json": "*", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^10.5", "vimeo/psalm": "^5.11" }, "type": "library", @@ -333,7 +333,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.1.4" + "source": "https://github.com/doctrine/collections/tree/2.2.0" }, "funding": [ { @@ -349,7 +349,7 @@ "type": "tidelift" } ], - "time": "2023-10-03T09:22:33+00:00" + "time": "2024-02-25T22:55:36+00:00" }, { "name": "doctrine/common", @@ -905,16 +905,16 @@ }, { "name": "doctrine/inflector", - "version": "2.0.9", + "version": "2.0.10", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "2930cd5ef353871c821d5c43ed030d39ac8cfe65" + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/2930cd5ef353871c821d5c43ed030d39ac8cfe65", - "reference": "2930cd5ef353871c821d5c43ed030d39ac8cfe65", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "shasum": "" }, "require": { @@ -976,7 +976,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.9" + "source": "https://github.com/doctrine/inflector/tree/2.0.10" }, "funding": [ { @@ -992,7 +992,7 @@ "type": "tidelift" } ], - "time": "2024-01-15T18:05:13+00:00" + "time": "2024-02-18T20:23:39+00:00" }, { "name": "doctrine/instantiator", @@ -1245,16 +1245,16 @@ }, { "name": "doctrine/orm", - "version": "2.18.0", + "version": "2.18.1", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "f2176a9ce56cafdfd1624d54bfdb076819083d5b" + "reference": "e6eef1a97d41f1ee244b6e69d7359d00cb3e4c4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/f2176a9ce56cafdfd1624d54bfdb076819083d5b", - "reference": "f2176a9ce56cafdfd1624d54bfdb076819083d5b", + "url": "https://api.github.com/repos/doctrine/orm/zipball/e6eef1a97d41f1ee244b6e69d7359d00cb3e4c4a", + "reference": "e6eef1a97d41f1ee244b6e69d7359d00cb3e4c4a", "shasum": "" }, "require": { @@ -1340,22 +1340,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.18.0" + "source": "https://github.com/doctrine/orm/tree/2.18.1" }, - "time": "2024-01-31T15:53:12+00:00" + "time": "2024-02-22T12:22:44+00:00" }, { "name": "doctrine/persistence", - "version": "3.2.0", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603" + "reference": "f75d11b1bcd0a9b75a9e1cabd80ffe3bc0164bcc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/63fee8c33bef740db6730eb2a750cd3da6495603", - "reference": "63fee8c33bef740db6730eb2a750cd3da6495603", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/f75d11b1bcd0a9b75a9e1cabd80ffe3bc0164bcc", + "reference": "f75d11b1bcd0a9b75a9e1cabd80ffe3bc0164bcc", "shasum": "" }, "require": { @@ -1424,7 +1424,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.2.0" + "source": "https://github.com/doctrine/persistence/tree/3.3.0" }, "funding": [ { @@ -1440,20 +1440,20 @@ "type": "tidelift" } ], - "time": "2023-05-17T18:32:04+00:00" + "time": "2024-03-01T10:11:31+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.1.3", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5" + "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/25a06c7bf4c6b8218f47928654252863ffc890a5", - "reference": "25a06c7bf4c6b8218f47928654252863ffc890a5", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a321d114e0a18e6497f8a2cd6f890e000cc17ecc", + "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc", "shasum": "" }, "require": { @@ -1490,9 +1490,9 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.1.3" + "source": "https://github.com/doctrine/sql-formatter/tree/1.2.0" }, - "time": "2022-05-23T21:33:49+00:00" + "time": "2023-08-16T21:49:04+00:00" }, { "name": "egulias/email-validator", @@ -2223,21 +2223,21 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.0", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc" + "reference": "153ae662783729388a584b4361f2545e4d841e3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fad452781b3d774e3337b0c0b245dd8e5a4455fc", - "reference": "fad452781b3d774e3337b0c0b245dd8e5a4455fc", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", + "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", "phpstan/phpdoc-parser": "^1.13" }, @@ -2275,22 +2275,22 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" }, - "time": "2024-01-11T11:49:22+00:00" + "time": "2024-02-23T11:10:43+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.25.0", + "version": "1.26.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240" + "reference": "231e3186624c03d7e7c890ec662b81e6b0405227" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bd84b629c8de41aa2ae82c067c955e06f1b00240", - "reference": "bd84b629c8de41aa2ae82c067c955e06f1b00240", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227", + "reference": "231e3186624c03d7e7c890ec662b81e6b0405227", "shasum": "" }, "require": { @@ -2322,9 +2322,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.25.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.26.0" }, - "time": "2024-01-04T17:06:16+00:00" + "time": "2024-02-23T16:05:55+00:00" }, { "name": "psr/cache", @@ -2703,16 +2703,16 @@ }, { "name": "symfony/cache", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "2207eceb2433d74df81232d97439bf508cb9e050" + "reference": "fc822951dd360a593224bb2cef90a087d0dff60f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/2207eceb2433d74df81232d97439bf508cb9e050", - "reference": "2207eceb2433d74df81232d97439bf508cb9e050", + "url": "https://api.github.com/repos/symfony/cache/zipball/fc822951dd360a593224bb2cef90a087d0dff60f", + "reference": "fc822951dd360a593224bb2cef90a087d0dff60f", "shasum": "" }, "require": { @@ -2779,7 +2779,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.0.3" + "source": "https://github.com/symfony/cache/tree/v7.0.4" }, "funding": [ { @@ -2795,7 +2795,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/cache-contracts", @@ -2949,16 +2949,16 @@ }, { "name": "symfony/config", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "86a5027869ca3d6bdecae6d5d6c2f77c8f2c1d16" + "reference": "44deeba7233f08f383185ffa37dace3b3bc87364" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/86a5027869ca3d6bdecae6d5d6c2f77c8f2c1d16", - "reference": "86a5027869ca3d6bdecae6d5d6c2f77c8f2c1d16", + "url": "https://api.github.com/repos/symfony/config/zipball/44deeba7233f08f383185ffa37dace3b3bc87364", + "reference": "44deeba7233f08f383185ffa37dace3b3bc87364", "shasum": "" }, "require": { @@ -3004,7 +3004,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/v7.0.3" + "source": "https://github.com/symfony/config/tree/v7.0.4" }, "funding": [ { @@ -3020,20 +3020,20 @@ "type": "tidelift" } ], - "time": "2024-01-30T08:34:29+00:00" + "time": "2024-02-26T07:52:39+00:00" }, { "name": "symfony/console", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c5010d50f1ee4b25cfa0201d9915cf1b14071456" + "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c5010d50f1ee4b25cfa0201d9915cf1b14071456", - "reference": "c5010d50f1ee4b25cfa0201d9915cf1b14071456", + "url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", + "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", "shasum": "" }, "require": { @@ -3097,7 +3097,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.3" + "source": "https://github.com/symfony/console/tree/v7.0.4" }, "funding": [ { @@ -3113,20 +3113,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "e915c6684b8e3ae90a4441f6823ebbb40edf0b92" + "reference": "47f37af245df8457ea63409fc242b3cc825ce5eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e915c6684b8e3ae90a4441f6823ebbb40edf0b92", - "reference": "e915c6684b8e3ae90a4441f6823ebbb40edf0b92", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/47f37af245df8457ea63409fc242b3cc825ce5eb", + "reference": "47f37af245df8457ea63409fc242b3cc825ce5eb", "shasum": "" }, "require": { @@ -3177,7 +3177,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/v7.0.3" + "source": "https://github.com/symfony/dependency-injection/tree/v7.0.4" }, "funding": [ { @@ -3193,7 +3193,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T08:34:29+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3264,16 +3264,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "fbea8d2b5f5c6cf0a2aab882571a047ee9238cb4" + "reference": "aded7ef586f9c75a04627326a5748f29ceba3506" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/fbea8d2b5f5c6cf0a2aab882571a047ee9238cb4", - "reference": "fbea8d2b5f5c6cf0a2aab882571a047ee9238cb4", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/aded7ef586f9c75a04627326a5748f29ceba3506", + "reference": "aded7ef586f9c75a04627326a5748f29ceba3506", "shasum": "" }, "require": { @@ -3350,7 +3350,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.3" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.4" }, "funding": [ { @@ -3366,20 +3366,20 @@ "type": "tidelift" } ], - "time": "2024-01-30T13:55:15+00:00" + "time": "2024-02-04T16:21:40+00:00" }, { "name": "symfony/doctrine-messenger", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-messenger.git", - "reference": "2e31535147212328570717d091e082326963d40e" + "reference": "5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/2e31535147212328570717d091e082326963d40e", - "reference": "2e31535147212328570717d091e082326963d40e", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca", + "reference": "5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca", "shasum": "" }, "require": { @@ -3422,7 +3422,7 @@ "description": "Symfony Doctrine Messenger Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-messenger/tree/v7.0.3" + "source": "https://github.com/symfony/doctrine-messenger/tree/v7.0.4" }, "funding": [ { @@ -3438,20 +3438,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/dotenv", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "4c69bf8ff41bd959050033eccb28ebe4b5c9b012" + "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/4c69bf8ff41bd959050033eccb28ebe4b5c9b012", - "reference": "4c69bf8ff41bd959050033eccb28ebe4b5c9b012", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067", + "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067", "shasum": "" }, "require": { @@ -3496,7 +3496,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v7.0.3" + "source": "https://github.com/symfony/dotenv/tree/v7.0.4" }, "funding": [ { @@ -3512,20 +3512,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-09T10:53:15+00:00" }, { "name": "symfony/error-handler", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "9441608b79577176b6d8e44012cc3d20b4b45242" + "reference": "677b24759decff69e65b1e9d1471d90f95ced880" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/9441608b79577176b6d8e44012cc3d20b4b45242", - "reference": "9441608b79577176b6d8e44012cc3d20b4b45242", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/677b24759decff69e65b1e9d1471d90f95ced880", + "reference": "677b24759decff69e65b1e9d1471d90f95ced880", "shasum": "" }, "require": { @@ -3571,7 +3571,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/v7.0.3" + "source": "https://github.com/symfony/error-handler/tree/v7.0.4" }, "funding": [ { @@ -3587,7 +3587,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/event-dispatcher", @@ -4002,16 +4002,16 @@ }, { "name": "symfony/form", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "76bfa17bf31d86bb00938725f276a84e697491b9" + "reference": "5cfe85c74caf924c7cec2134e169320b464ede84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/76bfa17bf31d86bb00938725f276a84e697491b9", - "reference": "76bfa17bf31d86bb00938725f276a84e697491b9", + "url": "https://api.github.com/repos/symfony/form/zipball/5cfe85c74caf924c7cec2134e169320b464ede84", + "reference": "5cfe85c74caf924c7cec2134e169320b464ede84", "shasum": "" }, "require": { @@ -4078,7 +4078,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v7.0.3" + "source": "https://github.com/symfony/form/tree/v7.0.4" }, "funding": [ { @@ -4094,20 +4094,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-12T11:15:03+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "3584457e3dbea9d6d43726e52c18672489669ff5" + "reference": "b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/3584457e3dbea9d6d43726e52c18672489669ff5", - "reference": "3584457e3dbea9d6d43726e52c18672489669ff5", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21", + "reference": "b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21", "shasum": "" }, "require": { @@ -4145,7 +4145,7 @@ "symfony/mime": "<6.4", "symfony/property-access": "<6.4", "symfony/property-info": "<6.4", - "symfony/scheduler": "<6.4.3|>=7.0.0,<7.0.3", + "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-core": "<6.4", "symfony/security-csrf": "<6.4", "symfony/serializer": "<6.4", @@ -4183,7 +4183,7 @@ "symfony/process": "^6.4|^7.0", "symfony/property-info": "^6.4|^7.0", "symfony/rate-limiter": "^6.4|^7.0", - "symfony/scheduler": "^6.4.3|^7.0.3", + "symfony/scheduler": "^6.4.4|^7.0.4", "symfony/security-bundle": "^6.4|^7.0", "symfony/semaphore": "^6.4|^7.0", "symfony/serializer": "^6.4|^7.0", @@ -4224,7 +4224,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/v7.0.3" + "source": "https://github.com/symfony/framework-bundle/tree/v7.0.4" }, "funding": [ { @@ -4240,20 +4240,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-26T07:52:39+00:00" }, { "name": "symfony/http-client", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "3d2605c07cd14aec294f72f5bf8147702f7a5ada" + "reference": "8384876f49a2316a63f88a9cd12436de6936bee6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/3d2605c07cd14aec294f72f5bf8147702f7a5ada", - "reference": "3d2605c07cd14aec294f72f5bf8147702f7a5ada", + "url": "https://api.github.com/repos/symfony/http-client/zipball/8384876f49a2316a63f88a9cd12436de6936bee6", + "reference": "8384876f49a2316a63f88a9cd12436de6936bee6", "shasum": "" }, "require": { @@ -4316,7 +4316,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.0.3" + "source": "https://github.com/symfony/http-client/tree/v7.0.4" }, "funding": [ { @@ -4332,7 +4332,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/http-client-contracts", @@ -4414,16 +4414,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f24e2568376e98978022fd09ce45e2dd049e67c8" + "reference": "439fdfdd344943254b1ef6278613e79040548045" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f24e2568376e98978022fd09ce45e2dd049e67c8", - "reference": "f24e2568376e98978022fd09ce45e2dd049e67c8", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045", + "reference": "439fdfdd344943254b1ef6278613e79040548045", "shasum": "" }, "require": { @@ -4471,7 +4471,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.0.3" + "source": "https://github.com/symfony/http-foundation/tree/v7.0.4" }, "funding": [ { @@ -4487,20 +4487,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-08T19:22:56+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "6352029d6667e8ac5b54aae95afe10b2706b31ac" + "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6352029d6667e8ac5b54aae95afe10b2706b31ac", - "reference": "6352029d6667e8ac5b54aae95afe10b2706b31ac", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/065e2234d907c0fc4fc942bf223f7cfc016d0ac7", + "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7", "shasum": "" }, "require": { @@ -4548,7 +4548,7 @@ "symfony/process": "^6.4|^7.0", "symfony/property-access": "^6.4|^7.0", "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", "symfony/stopwatch": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3", @@ -4583,7 +4583,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/v7.0.3" + "source": "https://github.com/symfony/http-kernel/tree/v7.0.4" }, "funding": [ { @@ -4599,7 +4599,7 @@ "type": "tidelift" } ], - "time": "2024-01-31T07:32:56+00:00" + "time": "2024-02-27T06:35:35+00:00" }, { "name": "symfony/intl", @@ -4685,16 +4685,16 @@ }, { "name": "symfony/mailer", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "2f71c0f6d62d28784783fdc5477e19dd57065d78" + "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/2f71c0f6d62d28784783fdc5477e19dd57065d78", - "reference": "2f71c0f6d62d28784783fdc5477e19dd57065d78", + "url": "https://api.github.com/repos/symfony/mailer/zipball/72e16d87bf50a3ce195b9470c06bb9d7b816ea85", + "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85", "shasum": "" }, "require": { @@ -4745,7 +4745,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.0.3" + "source": "https://github.com/symfony/mailer/tree/v7.0.4" }, "funding": [ { @@ -4761,20 +4761,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-03T21:34:19+00:00" }, { "name": "symfony/messenger", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "6271373f5dd4cc1750eccb73839d20797bd66072" + "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/6271373f5dd4cc1750eccb73839d20797bd66072", - "reference": "6271373f5dd4cc1750eccb73839d20797bd66072", + "url": "https://api.github.com/repos/symfony/messenger/zipball/804a8997f93313a8f7ed19e8cca3b44fdd18bdec", + "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec", "shasum": "" }, "require": { @@ -4831,7 +4831,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.0.3" + "source": "https://github.com/symfony/messenger/tree/v7.0.4" }, "funding": [ { @@ -4847,7 +4847,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T13:55:15+00:00" + "time": "2024-02-26T07:52:39+00:00" }, { "name": "symfony/mime", @@ -5238,16 +5238,16 @@ }, { "name": "symfony/password-hasher", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "c2447171293bd73dabeae293c8d9d824b444babf" + "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/c2447171293bd73dabeae293c8d9d824b444babf", - "reference": "c2447171293bd73dabeae293c8d9d824b444babf", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/0eba656c16ecdf5588b3ddd2b2337b06173d839f", + "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f", "shasum": "" }, "require": { @@ -5290,7 +5290,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v7.0.3" + "source": "https://github.com/symfony/password-hasher/tree/v7.0.4" }, "funding": [ { @@ -5306,7 +5306,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-12T11:15:03+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -5862,16 +5862,16 @@ }, { "name": "symfony/process", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "937a195147e0c27b2759ade834169ed006d0bc74" + "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/937a195147e0c27b2759ade834169ed006d0bc74", - "reference": "937a195147e0c27b2759ade834169ed006d0bc74", + "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9", + "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9", "shasum": "" }, "require": { @@ -5903,7 +5903,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.0.3" + "source": "https://github.com/symfony/process/tree/v7.0.4" }, "funding": [ { @@ -5919,20 +5919,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/property-access", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "5c7814d1a84bc11254c5bc761d9878b04e708dec" + "reference": "44e3746d4de8d0961a44ee332c74dd0918266127" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/5c7814d1a84bc11254c5bc761d9878b04e708dec", - "reference": "5c7814d1a84bc11254c5bc761d9878b04e708dec", + "url": "https://api.github.com/repos/symfony/property-access/zipball/44e3746d4de8d0961a44ee332c74dd0918266127", + "reference": "44e3746d4de8d0961a44ee332c74dd0918266127", "shasum": "" }, "require": { @@ -5979,7 +5979,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v7.0.3" + "source": "https://github.com/symfony/property-access/tree/v7.0.4" }, "funding": [ { @@ -5995,7 +5995,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-16T13:44:10+00:00" }, { "name": "symfony/property-info", @@ -6242,16 +6242,16 @@ }, { "name": "symfony/security-bundle", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "84984586e74a3c194c17d6b33ccca682ead23e05" + "reference": "1755fb50e4da0a0013569752be763d208d690bcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/84984586e74a3c194c17d6b33ccca682ead23e05", - "reference": "84984586e74a3c194c17d6b33ccca682ead23e05", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/1755fb50e4da0a0013569752be763d208d690bcd", + "reference": "1755fb50e4da0a0013569752be763d208d690bcd", "shasum": "" }, "require": { @@ -6333,7 +6333,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/v7.0.3" + "source": "https://github.com/symfony/security-bundle/tree/v7.0.4" }, "funding": [ { @@ -6349,7 +6349,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/security-core", @@ -6505,16 +6505,16 @@ }, { "name": "symfony/security-http", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "d974526dc43525a17bd588e45f86f382edd57331" + "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/d974526dc43525a17bd588e45f86f382edd57331", - "reference": "d974526dc43525a17bd588e45f86f382edd57331", + "url": "https://api.github.com/repos/symfony/security-http/zipball/f3a70a937128f47366821a9f4b5dbfaa0ba9c862", + "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862", "shasum": "" }, "require": { @@ -6572,7 +6572,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v7.0.3" + "source": "https://github.com/symfony/security-http/tree/v7.0.4" }, "funding": [ { @@ -6588,20 +6588,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-26T07:52:39+00:00" }, { "name": "symfony/serializer", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "6e83031c481e50b6f28e72531660341f1f120e6f" + "reference": "c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/6e83031c481e50b6f28e72531660341f1f120e6f", - "reference": "6e83031c481e50b6f28e72531660341f1f120e6f", + "url": "https://api.github.com/repos/symfony/serializer/zipball/c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb", + "reference": "c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb", "shasum": "" }, "require": { @@ -6667,7 +6667,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/v7.0.3" + "source": "https://github.com/symfony/serializer/tree/v7.0.4" }, "funding": [ { @@ -6683,7 +6683,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T08:34:29+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/service-contracts", @@ -6831,16 +6831,16 @@ }, { "name": "symfony/string", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "524aac4a280b90a4420d8d6a040718d0586505ac" + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/524aac4a280b90a4420d8d6a040718d0586505ac", - "reference": "524aac4a280b90a4420d8d6a040718d0586505ac", + "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", + "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", "shasum": "" }, "require": { @@ -6897,7 +6897,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.3" + "source": "https://github.com/symfony/string/tree/v7.0.4" }, "funding": [ { @@ -6913,20 +6913,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-01T13:17:36+00:00" }, { "name": "symfony/translation", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "7285f25c7dcc74d9ec1232473114274604e50f00" + "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/7285f25c7dcc74d9ec1232473114274604e50f00", - "reference": "7285f25c7dcc74d9ec1232473114274604e50f00", + "url": "https://api.github.com/repos/symfony/translation/zipball/5b75e872f7d135d7abb4613809fadc8d9f3d30a0", + "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0", "shasum": "" }, "require": { @@ -6991,7 +6991,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.0.3" + "source": "https://github.com/symfony/translation/tree/v7.0.4" }, "funding": [ { @@ -7007,7 +7007,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/translation-contracts", @@ -7089,16 +7089,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "414ff6930889262a11ec67f351e9810dd8565b0d" + "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/414ff6930889262a11ec67f351e9810dd8565b0d", - "reference": "414ff6930889262a11ec67f351e9810dd8565b0d", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d16aa4eb5bdaeb6e7407782431dc70530f3b1df5", + "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5", "shasum": "" }, "require": { @@ -7177,7 +7177,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.0.3" + "source": "https://github.com/symfony/twig-bridge/tree/v7.0.4" }, "funding": [ { @@ -7193,20 +7193,20 @@ "type": "tidelift" } ], - "time": "2024-01-30T08:34:29+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/twig-bundle", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "6fbf0cc2b0d0208be4881ff6069665687396b323" + "reference": "acab2368f53491e018bf31ef48b39df55a6812ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/6fbf0cc2b0d0208be4881ff6069665687396b323", - "reference": "6fbf0cc2b0d0208be4881ff6069665687396b323", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef", + "reference": "acab2368f53491e018bf31ef48b39df55a6812ef", "shasum": "" }, "require": { @@ -7261,7 +7261,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/v7.0.3" + "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4" }, "funding": [ { @@ -7277,20 +7277,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/validator", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "03b0c75d7d3df1ef9a0fd9fb8db1e86f83ffa2bb" + "reference": "104bc3620d0ee4091034cfbcdcf82ed727f15b7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/03b0c75d7d3df1ef9a0fd9fb8db1e86f83ffa2bb", - "reference": "03b0c75d7d3df1ef9a0fd9fb8db1e86f83ffa2bb", + "url": "https://api.github.com/repos/symfony/validator/zipball/104bc3620d0ee4091034cfbcdcf82ed727f15b7d", + "reference": "104bc3620d0ee4091034cfbcdcf82ed727f15b7d", "shasum": "" }, "require": { @@ -7355,7 +7355,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v7.0.3" + "source": "https://github.com/symfony/validator/tree/v7.0.4" }, "funding": [ { @@ -7371,20 +7371,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "a7a061abbf6fe3d4a79032cbc5149a4d65a10234" + "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a7a061abbf6fe3d4a79032cbc5149a4d65a10234", - "reference": "a7a061abbf6fe3d4a79032cbc5149a4d65a10234", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670", + "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670", "shasum": "" }, "require": { @@ -7438,7 +7438,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.0.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.0.4" }, "funding": [ { @@ -7454,20 +7454,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-15T11:33:06+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8" + "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", - "reference": "1fb79308cb5fc2b44bff6e8af10a5af6812e05b8", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", + "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", "shasum": "" }, "require": { @@ -7512,7 +7512,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.0.3" + "source": "https://github.com/symfony/var-exporter/tree/v7.0.4" }, "funding": [ { @@ -7528,7 +7528,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-26T10:35:24+00:00" }, { "name": "symfony/web-link", @@ -8679,16 +8679,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.0.0", + "version": "v5.0.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc" + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc", - "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69", + "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69", "shasum": "" }, "require": { @@ -8731,9 +8731,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1" }, - "time": "2024-01-07T17:17:35+00:00" + "time": "2024-02-21T19:24:10+00:00" }, { "name": "phar-io/manifest", @@ -9167,16 +9167,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.16", + "version": "9.6.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f" + "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3767b2c56ce02d01e3491046f33466a1ae60a37f", - "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd", + "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd", "shasum": "" }, "require": { @@ -9250,7 +9250,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.16" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17" }, "funding": [ { @@ -9266,7 +9266,7 @@ "type": "tidelift" } ], - "time": "2024-01-19T07:03:14+00:00" + "time": "2024-02-23T13:14:51+00:00" }, { "name": "sebastian/cli-parser", @@ -10441,16 +10441,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "3330a8f836e7631412c5e07f69b88480d27a20a2" + "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/3330a8f836e7631412c5e07f69b88480d27a20a2", - "reference": "3330a8f836e7631412c5e07f69b88480d27a20a2", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/6cb272cbec4dc7a30a853d2931766b03bea92dda", + "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda", "shasum": "" }, "require": { @@ -10488,7 +10488,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v7.0.3" + "source": "https://github.com/symfony/dom-crawler/tree/v7.0.4" }, "funding": [ { @@ -10504,20 +10504,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-12T11:15:03+00:00" }, { "name": "symfony/maker-bundle", - "version": "v1.54.0", + "version": "v1.55.1", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "a8523cf35d777bf2d8cf5703fa73f378fdc27125" + "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/a8523cf35d777bf2d8cf5703fa73f378fdc27125", - "reference": "a8523cf35d777bf2d8cf5703fa73f378fdc27125", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/11a9d3125c5b93ab4043f0f2e9927fdc55881c17", + "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17", "shasum": "" }, "require": { @@ -10580,7 +10580,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.54.0" + "source": "https://github.com/symfony/maker-bundle/tree/v1.55.1" }, "funding": [ { @@ -10596,20 +10596,20 @@ "type": "tidelift" } ], - "time": "2024-02-06T21:23:55+00:00" + "time": "2024-02-21T13:41:51+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "0a2eeb0d9e68bf01660e3e903f8113508bb46132" + "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/0a2eeb0d9e68bf01660e3e903f8113508bb46132", - "reference": "0a2eeb0d9e68bf01660e3e903f8113508bb46132", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/54ca13ec990a40411ad978e08d994fca6cdd865f", + "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f", "shasum": "" }, "require": { @@ -10661,7 +10661,7 @@ "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.3" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.4" }, "funding": [ { @@ -10677,20 +10677,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-02-08T19:22:56+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v7.0.3", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "320dbcaa6e3a72797a614216703df8b187f19265" + "reference": "542daea1345fe181cbfd52db00717174a838ea0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/320dbcaa6e3a72797a614216703df8b187f19265", - "reference": "320dbcaa6e3a72797a614216703df8b187f19265", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/542daea1345fe181cbfd52db00717174a838ea0a", + "reference": "542daea1345fe181cbfd52db00717174a838ea0a", "shasum": "" }, "require": { @@ -10742,7 +10742,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.0.3" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.0.4" }, "funding": [ { @@ -10758,7 +10758,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T15:41:16+00:00" + "time": "2024-02-22T20:27:20+00:00" }, { "name": "theseer/tokenizer", @@ -10871,16 +10871,16 @@ }, { "name": "zenstruck/browser", - "version": "v1.8.0", + "version": "v1.8.1", "source": { "type": "git", "url": "https://github.com/zenstruck/browser.git", - "reference": "2c504ce46f76abf6e8725218c0eab519f60b62a6" + "reference": "c3a7328df5c2e3750f3aaef3be4805c2021dd6a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zenstruck/browser/zipball/2c504ce46f76abf6e8725218c0eab519f60b62a6", - "reference": "2c504ce46f76abf6e8725218c0eab519f60b62a6", + "url": "https://api.github.com/repos/zenstruck/browser/zipball/c3a7328df5c2e3750f3aaef3be4805c2021dd6a7", + "reference": "c3a7328df5c2e3750f3aaef3be4805c2021dd6a7", "shasum": "" }, "require": { @@ -10934,7 +10934,7 @@ ], "support": { "issues": "https://github.com/zenstruck/browser/issues", - "source": "https://github.com/zenstruck/browser/tree/v1.8.0" + "source": "https://github.com/zenstruck/browser/tree/v1.8.1" }, "funding": [ { @@ -10942,7 +10942,7 @@ "type": "github" } ], - "time": "2024-02-07T17:32:28+00:00" + "time": "2024-02-21T15:32:44+00:00" }, { "name": "zenstruck/callback", diff --git a/src/ApiResource/CommentApi.php b/src/ApiResource/CommentApi.php index 3451bc5..416f836 100644 --- a/src/ApiResource/CommentApi.php +++ b/src/ApiResource/CommentApi.php @@ -54,13 +54,13 @@ class CommentApi #[NotBlank] public ?string $message = null; - #[IsValidOwner] + #[ApiProperty(writable: false)] public ?UserApi $owner = null; #[ApiProperty(writable: false)] public ?string $ownerName = null; - public ?PostingApi $posting = null; + public ?PostingApi $post = null; #[ApiProperty(writable: false)] public ?\DateTimeImmutable $createdAt = null; diff --git a/src/ApiResource/ContactApi.php b/src/ApiResource/ContactApi.php index ca21d46..7311c81 100644 --- a/src/ApiResource/ContactApi.php +++ b/src/ApiResource/ContactApi.php @@ -35,7 +35,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; security: 'is_granted("ROLE_USER")', ), new Patch( - security: 'is_granted("EDIT", object)', + security: 'is_granted("ROLE_USER")', ), new Delete( security: 'is_granted("ROLE_ADMIN")', @@ -59,6 +59,7 @@ class ContactApi #[NotBlank] public ?string $lastName = null; + #[NotBlank] public ?PartnerApi $partner = null; public ?\DateTimeInterface $birthday = null; @@ -79,7 +80,7 @@ class ContactApi * @var array */ #[ApiProperty(writable: false)] - public array $postings = []; + public array $posts = []; #[ApiProperty(writable: false)] public ?\DateTimeImmutable $createdAt = null; diff --git a/src/ApiResource/PartnerApi.php b/src/ApiResource/PartnerApi.php index f1fa9c0..c5f6313 100644 --- a/src/ApiResource/PartnerApi.php +++ b/src/ApiResource/PartnerApi.php @@ -37,7 +37,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; security: 'is_granted("ROLE_USER")', ), new Patch( - security: 'is_granted("EDIT", object)', + security: 'is_granted("ROLE_USER")', ), new Delete( security: 'is_granted("ROLE_ADMIN")', @@ -84,5 +84,6 @@ class PartnerApi /** * @var array */ + #[ApiProperty(writable: false)] public array $contacts = []; } \ No newline at end of file diff --git a/src/ApiResource/PostingApi.php b/src/ApiResource/PostingApi.php index f361b84..55d7263 100644 --- a/src/ApiResource/PostingApi.php +++ b/src/ApiResource/PostingApi.php @@ -20,8 +20,9 @@ use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; -use App\Validator\IsValidOwner; use Symfony\Component\PropertyInfo\Type; +use Symfony\Component\Serializer\Attribute\Groups; +use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints\NotBlank; #[ApiResource( @@ -34,9 +35,11 @@ use Symfony\Component\Validator\Constraints\NotBlank; security: 'is_granted("ROLE_USER")', ), new Post( + denormalizationContext: ['groups' => 'posting_create'], security: 'is_granted("ROLE_USER")', ), new Patch( + denormalizationContext: ['groups' => 'posting_patch'], security: 'is_granted("EDIT", object)', ), new Delete( @@ -55,28 +58,35 @@ class PostingApi public ?int $id = null; #[NotBlank] + #[Groups(['posting_create', 'posting_patch'])] public ?string $headline = null; #[NotBlank] + #[Groups(['posting_create', 'posting_patch'])] public ?string $message = null; - //#[IsValidOwner] #[ApiProperty(writable: false)] public ?UserApi $owner = null; #[ApiProperty(writable: false)] public ?string $ownerName = null; + #[ApiProperty(writable: true)] + #[Groups(['posting_create'])] + #[Assert\NotBlank(groups: ['posting_create'])] public ?PartnerApi $partner = null; + #[ApiProperty(writable: true)] + #[Groups(['posting_create'])] public ?ContactApi $contact = null; /** * @var array */ #[ApiProperty( + writable: false, readableLink: true, - writableLink: true, + writableLink: false, fetchEager: true, builtinTypes: [ new Type( diff --git a/src/ApiResource/UserApi.php b/src/ApiResource/UserApi.php index ac072d0..b47b245 100644 --- a/src/ApiResource/UserApi.php +++ b/src/ApiResource/UserApi.php @@ -30,10 +30,10 @@ use Symfony\Component\Validator\Constraints as Assert; ), new Post( security: 'is_granted("ROLE_ADMIN")', - validationContext: ['groups' => ['Default', 'postValidation']], + validationContext: ['groups' => ['Default', 'postValidation']] ), new Patch( - security: 'is_granted("ROLE_USER")' + security: 'is_granted("is_granted("EDIT", object)")' ), ], security: 'is_granted("ROLE_USER")', @@ -74,7 +74,8 @@ class UserApi /** * @var array */ - public array $postings = []; + #[ApiProperty(writable: false)] + public array $posts = []; #[ApiProperty(writable: false)] public ?\DateTimeImmutable $createdAt = null; diff --git a/src/Entity/Comment.php b/src/Entity/Comment.php index dbb8c32..b1c9b61 100644 --- a/src/Entity/Comment.php +++ b/src/Entity/Comment.php @@ -28,8 +28,10 @@ class Comment #[ORM\Column] private ?\DateTimeImmutable $createdAt = null; - public function __construct() + public function __construct(User $owner, Posting $posting) { + $this->owner = $owner; + $this->posting = $posting; $this->createdAt = new \DateTimeImmutable(); } @@ -62,25 +64,11 @@ class Comment return $this->owner; } - public function setOwner(?User $owner): static - { - $this->owner = $owner; - - return $this; - } - public function getPosting(): ?Posting { return $this->posting; } - public function setPosting(?Posting $posting): static - { - $this->posting = $posting; - - return $this; - } - public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; diff --git a/src/Entity/Contact.php b/src/Entity/Contact.php index 022f6dc..e014c32 100644 --- a/src/Entity/Contact.php +++ b/src/Entity/Contact.php @@ -46,13 +46,13 @@ class Contact private ?\DateTimeImmutable $createdAt = null; #[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class, orphanRemoval: true)] - private Collection $postings; + private Collection $posts; public function __construct(Partner $partner) { $this->partner = $partner; $this->createdAt = new \DateTimeImmutable(); - $this->postings = new ArrayCollection(); + $this->posts = new ArrayCollection(); } public function getId(): ?int @@ -169,15 +169,15 @@ class Contact /** * @return Collection */ - public function getPostings(): Collection + public function getPosts(): Collection { - return $this->postings; + return $this->posts; } public function addPosting(Posting $posting): static { - if (!$this->postings->contains($posting)) { - $this->postings->add($posting); + if (!$this->posts->contains($posting)) { + $this->posts->add($posting); $posting->setContact($this); } @@ -186,7 +186,7 @@ class Contact public function removePosting(Posting $posting): static { - if ($this->postings->removeElement($posting)) { + if ($this->posts->removeElement($posting)) { // set the owning side to null (unless already changed) if ($posting->getContact() === $this) { $posting->setContact(null); diff --git a/src/Entity/MediaObject.php b/src/Entity/MediaObject.php index bb0ff2a..7cea724 100644 --- a/src/Entity/MediaObject.php +++ b/src/Entity/MediaObject.php @@ -23,6 +23,7 @@ use Vich\UploaderBundle\Mapping\Annotation as Vich; #[Vich\Uploadable] #[ORM\Entity] #[ApiResource( + shortName: 'Media', types: ['https://schema.org/MediaObject'], operations: [ new Get(), diff --git a/src/Entity/Posting.php b/src/Entity/Posting.php index 81e9902..998951b 100644 --- a/src/Entity/Posting.php +++ b/src/Entity/Posting.php @@ -70,6 +70,11 @@ class Posting return $this->createdAt; } + public function setOwner(?User $owner): void + { + $this->owner = $owner; + } + public function getOwner(): ?User { return $this->owner; diff --git a/src/EventListener/AuthenticationSuccessListener.php b/src/EventListener/AuthenticationSuccessListener.php index 1575b36..6636592 100644 --- a/src/EventListener/AuthenticationSuccessListener.php +++ b/src/EventListener/AuthenticationSuccessListener.php @@ -38,7 +38,7 @@ class AuthenticationSuccessListener } $userApi = $this->microMapper->map($user, UserApi::class, [ - MicroMapperInterface::MAX_DEPTH => 3, + MicroMapperInterface::MAX_DEPTH => 1, ]); $data['id'] = $this->iriConverter->getIriFromResource($userApi); diff --git a/src/Factory/PostingFactory.php b/src/Factory/PostingFactory.php index ad09452..e3ec9e0 100644 --- a/src/Factory/PostingFactory.php +++ b/src/Factory/PostingFactory.php @@ -46,7 +46,7 @@ final class PostingFactory extends ModelFactory */ protected function getDefaults(): array { - $randomBoolean = (bool)random_int(0, 1); + $randomBoolean = ContactFactory::count() > 0 && (bool)random_int(0, 1); return [ 'headline' => self::faker()->words(random_int(1, 5), true), 'message' => $randomBoolean ? self::faker()->sentence() : self::faker()->sentences(random_int(1, 3), true), diff --git a/src/Mapper/CommentApiToEntityMapper.php b/src/Mapper/CommentApiToEntityMapper.php index 719614b..87763d4 100644 --- a/src/Mapper/CommentApiToEntityMapper.php +++ b/src/Mapper/CommentApiToEntityMapper.php @@ -4,6 +4,7 @@ namespace App\Mapper; use App\ApiResource\CommentApi; use App\Entity\Comment; +use App\Entity\Posting; use App\Entity\User; use App\Repository\CommentRepository; use Symfony\Bundle\SecurityBundle\Security; @@ -28,7 +29,21 @@ class CommentApiToEntityMapper implements MapperInterface $dto = $from; assert($dto instanceof CommentApi); - $entity = $dto->id ? $this->repository->find($dto->id) : new Comment(); + if ($dto->id) { + $entity = $this->repository->find($dto->id); + } else { + $user = $this->security->getUser(); + assert($user instanceof User); + if ($dto->post === null) { + throw new \Exception('Posting missing'); + } + $posting = $this->microMapper->map($dto->post, Posting::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + assert($posting instanceof Posting); + $entity = new Comment($user, $posting); + } + if (!$entity) { throw new \Exception('Comment not found'); } @@ -42,15 +57,6 @@ class CommentApiToEntityMapper implements MapperInterface assert($dto instanceof CommentApi); $entity = $to; assert($entity instanceof Comment); - - if ($dto->owner) { - $entity->setOwner($this->microMapper->map($dto->owner, User::class, [ - MicroMapperInterface::MAX_DEPTH => 1, - ])); - } else { - $entity->setOwner($this->security->getUser()); - } - $entity->setPosting($dto->posting); $entity->setMessage($dto->message); return $entity; diff --git a/src/Mapper/CommentEntityToApiMapper.php b/src/Mapper/CommentEntityToApiMapper.php index 39a878d..2dbbcd0 100644 --- a/src/Mapper/CommentEntityToApiMapper.php +++ b/src/Mapper/CommentEntityToApiMapper.php @@ -15,8 +15,7 @@ use Symfonycasts\MicroMapper\MicroMapperInterface; class CommentEntityToApiMapper implements MapperInterface { public function __construct( - private MicroMapperInterface $microMapper, - private Security $security, + private MicroMapperInterface $microMapper ) { } @@ -41,12 +40,12 @@ class CommentEntityToApiMapper implements MapperInterface $dto->message = $entity->getMessage(); $dto->owner = $this->microMapper->map($entity->getOwner(), UserApi::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); $dto->ownerName = $entity->getOwner()?->getFirstName()." ".$entity->getOwner()?->getLastName(); $dto->posting = $this->microMapper->map($entity->getPosting(), PostingApi::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); $dto->createdAt = $entity->getCreatedAt(); diff --git a/src/Mapper/ContactApiToEntityMapper.php b/src/Mapper/ContactApiToEntityMapper.php index c3976fa..931cef0 100644 --- a/src/Mapper/ContactApiToEntityMapper.php +++ b/src/Mapper/ContactApiToEntityMapper.php @@ -17,7 +17,6 @@ class ContactApiToEntityMapper implements MapperInterface { public function __construct( private ContactRepository $repository, - private Security $security, private MicroMapperInterface $microMapper, ) { @@ -36,7 +35,7 @@ class ContactApiToEntityMapper implements MapperInterface throw new \Exception('Partner missing'); } $partner = $this->microMapper->map($dto->partner, Partner::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); $entity = new Contact($partner); } @@ -58,7 +57,6 @@ class ContactApiToEntityMapper implements MapperInterface $entity->setFirstName($dto->firstName); $entity->setLastName($dto->lastName); - $entity->setPartner($dto->partner); $entity->setBirthday($dto->birthday); $entity->setImage($dto->image); $entity->setPosition($dto->position); diff --git a/src/Mapper/ContactEntityToApiMapper.php b/src/Mapper/ContactEntityToApiMapper.php index 3647aa5..b6ed827 100644 --- a/src/Mapper/ContactEntityToApiMapper.php +++ b/src/Mapper/ContactEntityToApiMapper.php @@ -44,7 +44,7 @@ class ContactEntityToApiMapper implements MapperInterface $dto->lastName = $entity->getLastName(); $dto->partner = $this->microMapper->map( $entity->getPartner(), PartnerApi::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ] ); $dto->birthday = $entity->getBirthday(); @@ -55,11 +55,11 @@ class ContactEntityToApiMapper implements MapperInterface $dto->email = $entity->getEmail(); $dto->createdAt = $entity->getCreatedAt(); - $dto->postings = array_map(function(Posting $posting) { + $dto->posts = array_map(function(Posting $posting) { return $this->microMapper->map($posting, PostingApi::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); - }, $entity->getPostings()->getValues()); + }, $entity->getPosts()->getValues()); return $dto; } diff --git a/src/Mapper/PartnerApiToEntityMapper.php b/src/Mapper/PartnerApiToEntityMapper.php index 8e59559..7cd82d3 100644 --- a/src/Mapper/PartnerApiToEntityMapper.php +++ b/src/Mapper/PartnerApiToEntityMapper.php @@ -19,10 +19,7 @@ use Symfonycasts\MicroMapper\MicroMapperInterface; class PartnerApiToEntityMapper implements MapperInterface { public function __construct( - private PartnerRepository $repository, - private Security $security, - private MicroMapperInterface $microMapper, - private PropertyAccessorInterface $propertyAccessor, + private PartnerRepository $repository ) { @@ -58,14 +55,6 @@ class PartnerApiToEntityMapper implements MapperInterface $entity->setWebsite($dto->website); $entity->setLogo($dto->logo); - $contactEntities = []; - foreach ($dto->contacts as $contactApi) { - $contactEntities[] = $this->microMapper->map($contactApi, Contact::class, [ - MicroMapperInterface::MAX_DEPTH => 0, - ]); - } - $this->propertyAccessor->setValue($entity, 'contacts', $contactEntities); - return $entity; } } diff --git a/src/Mapper/PartnerEntityToApiMapper.php b/src/Mapper/PartnerEntityToApiMapper.php index a6d4e70..5442c34 100644 --- a/src/Mapper/PartnerEntityToApiMapper.php +++ b/src/Mapper/PartnerEntityToApiMapper.php @@ -52,7 +52,7 @@ class PartnerEntityToApiMapper implements MapperInterface $dto->createdAt = $entity->getCreatedAt(); $dto->contacts = array_map(function(Contact $contact) { return $this->microMapper->map($contact, ContactApi::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); }, $entity->getContacts()->getValues()); return $dto; diff --git a/src/Mapper/PostingApiToEntityMapper.php b/src/Mapper/PostingApiToEntityMapper.php index d783a76..9716779 100644 --- a/src/Mapper/PostingApiToEntityMapper.php +++ b/src/Mapper/PostingApiToEntityMapper.php @@ -40,13 +40,13 @@ class PostingApiToEntityMapper implements MapperInterface throw new \Exception('Partner missing'); } $partner = $this->microMapper->map($dto->partner, Partner::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); $contact = null; if ($dto->contact) { assert($dto->contact instanceof ContactApi); $contact = $this->microMapper->map($dto->contact, Contact::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); } assert($partner instanceof Partner); diff --git a/src/Mapper/UserApiToEntityMapper.php b/src/Mapper/UserApiToEntityMapper.php index 4ce3b33..dfe8f84 100644 --- a/src/Mapper/UserApiToEntityMapper.php +++ b/src/Mapper/UserApiToEntityMapper.php @@ -53,9 +53,9 @@ class UserApiToEntityMapper implements MapperInterface } $userPostsEntities = new ArrayCollection(); - foreach ($dto->postings as $userPostApi) { + foreach ($dto->posts as $userPostApi) { $userPostsEntities[] = $this->microMapper->map($userPostApi, Posting::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); } $this->propertyAccessor->setValue($entity, 'postings', $userPostsEntities); diff --git a/src/Mapper/UserEntityToApiMapper.php b/src/Mapper/UserEntityToApiMapper.php index 4b893a1..74f4285 100644 --- a/src/Mapper/UserEntityToApiMapper.php +++ b/src/Mapper/UserEntityToApiMapper.php @@ -41,9 +41,9 @@ class UserEntityToApiMapper implements MapperInterface $dto->firstName = $entity->getFirstName(); $dto->lastName = $entity->getLastName(); - $dto->postings = array_map(function(Posting $posting) { + $dto->posts = array_map(function(Posting $posting) { return $this->microMapper->map($posting, PostingApi::class, [ - MicroMapperInterface::MAX_DEPTH => 0, + MicroMapperInterface::MAX_DEPTH => 1, ]); }, $entity->getPostings()->getValues()); diff --git a/src/Voter/CommentApiVoter.php b/src/Voter/CommentApiVoter.php new file mode 100644 index 0000000..aa02c54 --- /dev/null +++ b/src/Voter/CommentApiVoter.php @@ -0,0 +1,46 @@ +getUser(); + // if the user is anonymous, do not grant access + if (!$user instanceof User) { + return false; + } + + assert($subject instanceof CommentApi); + + // ... (check conditions and return true to grant permission) ... + switch ($attribute) { + case self::EDIT: + if ($subject->owner?->id === $user->getId()) { + return true; + } + break; + } + + return false; + } +} diff --git a/src/Voter/PostingApiVoter.php b/src/Voter/PostingApiVoter.php index 00a880d..e7ab12a 100644 --- a/src/Voter/PostingApiVoter.php +++ b/src/Voter/PostingApiVoter.php @@ -12,13 +12,13 @@ class PostingApiVoter extends Voter { public const EDIT = 'EDIT'; - public function __construct(private Security $security) + public function __construct() { } protected function supports(string $attribute, mixed $subject): bool { - return in_array($attribute, [self::EDIT]) && $subject instanceof PostingApi; + return $attribute === self::EDIT && $subject instanceof PostingApi; } protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool @@ -29,10 +29,6 @@ class PostingApiVoter extends Voter return false; } - if ($this->security->isGranted('ROLE_ADMIN')) { - return true; - } - assert($subject instanceof PostingApi); // ... (check conditions and return true to grant permission) ... diff --git a/src/Voter/UserApiVoter.php b/src/Voter/UserApiVoter.php index 7325600..8d9b9dd 100644 --- a/src/Voter/UserApiVoter.php +++ b/src/Voter/UserApiVoter.php @@ -18,12 +18,11 @@ class UserApiVoter extends Voter protected function supports(string $attribute, mixed $subject): bool { - return in_array($attribute, [self::EDIT]) && $subject instanceof UserApi; + return $attribute === self::EDIT && $subject instanceof UserApi; } protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool { - //dd($subject); $user = $token->getUser(); // if the user is anonymous, do not grant access if (!$user instanceof User) { diff --git a/tests/Functional/CommentResourceTest.php b/tests/Functional/CommentResourceTest.php new file mode 100644 index 0000000..b0fc8cf --- /dev/null +++ b/tests/Functional/CommentResourceTest.php @@ -0,0 +1,78 @@ + + * @date 12.12.23 + */ + + +namespace App\Tests\Functional; + +use App\Enum\PartnerType; +use App\Factory\CommentFactory; +use App\Factory\MediaObjectLogoFactory; +use App\Factory\MediaObjectProfileFactory; +use App\Factory\PartnerFactory; +use App\Factory\PostingFactory; +use App\Factory\UserFactory; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Zenstruck\Browser\Test\HasBrowser; +use Zenstruck\Foundry\Test\Factories; +use Zenstruck\Foundry\Test\ResetDatabase; + +class CommentResourceTest extends KernelTestCase +{ + use HasBrowser; + use ResetDatabase; + use Factories; + + private JWTTokenManagerInterface $JWTManager; + + protected function setUp(): void + { + parent::setUp(); + $this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager'); + } + + public function testPostComment(): void + { + $user = UserFactory::createOne( + [ + 'firstName' => 'Peter', + 'lastName' => 'Test', + 'password' => 'test', + 'email' => 'peter@test.de', + ] + ); + MediaObjectLogoFactory::createOne(); + PartnerFactory::createOne(); + $posting = PostingFactory::createOne(); + CommentFactory::createOne(); + + $token = $this->JWTManager->create($user->object()); + + $this->browser() + ->post('/api/comments' , [ + 'json' => [ + 'message' => 'my comment', + 'post' => '/api/posts/' . $posting->getId(), + ], + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ] + ]) + ->assertSuccessful() + ; + + $this->browser() + ->get('/api/comments', [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ], + ]) + ->assertSuccessful() + ->assertJsonMatches('"hydra:totalItems"', 2) + ->assertJsonMatches('"hydra:member"[1].message', 'my comment') + ; + } +} \ No newline at end of file diff --git a/tests/Functional/ContactResourceTest.php b/tests/Functional/ContactResourceTest.php new file mode 100644 index 0000000..c6f3ce8 --- /dev/null +++ b/tests/Functional/ContactResourceTest.php @@ -0,0 +1,82 @@ + + * @date 12.12.23 + */ + + +namespace App\Tests\Functional; + +use App\Enum\PartnerType; +use App\Factory\MediaObjectLogoFactory; +use App\Factory\MediaObjectProfileFactory; +use App\Factory\PartnerFactory; +use App\Factory\UserFactory; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Zenstruck\Browser\Test\HasBrowser; +use Zenstruck\Foundry\Test\Factories; +use Zenstruck\Foundry\Test\ResetDatabase; + +class ContactResourceTest extends KernelTestCase +{ + use HasBrowser; + use ResetDatabase; + use Factories; + + private JWTTokenManagerInterface $JWTManager; + + protected function setUp(): void + { + parent::setUp(); + $this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager'); + } + + public function testPostContact(): void + { + MediaObjectLogoFactory::createOne(); + $partner = PartnerFactory::createOne(); + $user = UserFactory::createOne( + [ + 'firstName' => 'Peter', + 'lastName' => 'Test', + 'password' => 'test', + 'email' => 'peter@test.de', + ] + ); + + $mediaObject = MediaObjectProfileFactory::createOne(); + + $token = $this->JWTManager->create($user->object()); + + $this->browser() + ->post('/api/contacts' , [ + 'json' => [ + 'firstName' => 'Peter', + 'lastName' => 'Test', + 'partner' => '/api/partners/' . $partner->getId(), + 'birthday' => '1984-02-10', + 'image' => '/api/medias/' . $mediaObject->getId(), + 'position' => 'CEO', + 'phone' => '123456789', + 'email' => 'peter@test2.de', + ], + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ] + ]) + ->assertSuccessful() + ; + + $this->browser() + ->get('/api/contacts', [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ], + ]) + ->assertSuccessful() + ->assertJsonMatches('"hydra:totalItems"', 1) + ->assertJsonMatches('"hydra:member"[0].position', 'CEO') + ; + } +} \ No newline at end of file diff --git a/tests/Functional/MediaObjectResourceTest.php b/tests/Functional/MediaObjectResourceTest.php new file mode 100644 index 0000000..b0c9ec8 --- /dev/null +++ b/tests/Functional/MediaObjectResourceTest.php @@ -0,0 +1,66 @@ + + * @date 01.03.24 + */ + + +namespace App\Tests\Functional; + +use App\Factory\UserFactory; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Zenstruck\Browser\Test\HasBrowser; +use Zenstruck\Foundry\Test\Factories; +use Zenstruck\Foundry\Test\ResetDatabase; + +class MediaObjectResourceTest extends KernelTestCase +{ + use HasBrowser; + use ResetDatabase; + use Factories; + + private JWTTokenManagerInterface $JWTManager; + private string $projectDir; + + protected function setUp(): void + { + parent::setUp(); + $this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager'); + $this->projectDir = self::getContainer()->get('kernel')->getProjectDir(); + } + + public function testCreateAMediaObject(): void + { + $path = $this->projectDir . '/tests/fixtures/'; + $srcFile = $path . '1176.png'; + $dstFile = $path . '1176_upload.png'; + copy($srcFile, $dstFile); + + $file = new UploadedFile($dstFile, 'image.png'); + + $user = UserFactory::createOne( + [ + 'firstName' => 'Peter', + 'lastName' => 'Test', + 'password' => 'test', + 'email' => 'peter@test.de', + ] + ); + $token = $this->JWTManager->create($user->object()); + + $this->browser() + ->post('/api/medias', [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + 'Content-Type' => 'multipart/form-data' + ], + 'files' => [ + 'file' => $file, + ], + ]) + ->assertSuccessful() + ; + } +} diff --git a/tests/Functional/PartnerResourceTest.php b/tests/Functional/PartnerResourceTest.php new file mode 100644 index 0000000..8fd908a --- /dev/null +++ b/tests/Functional/PartnerResourceTest.php @@ -0,0 +1,79 @@ + + * @date 12.12.23 + */ + + +namespace App\Tests\Functional; + +use App\Enum\PartnerType; +use App\Factory\MediaObjectLogoFactory; +use App\Factory\UserFactory; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; +use Zenstruck\Browser\Test\HasBrowser; +use Zenstruck\Foundry\Test\Factories; +use Zenstruck\Foundry\Test\ResetDatabase; + +class PartnerResourceTest extends KernelTestCase +{ + use HasBrowser; + use ResetDatabase; + use Factories; + + private JWTTokenManagerInterface $JWTManager; + + protected function setUp(): void + { + parent::setUp(); + $this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager'); + } + + public function testPostPartner(): void + { + $user = UserFactory::createOne( + [ + 'email' => 'peter@test.de', + 'firstName' => 'Peter', + 'lastName' => 'Test', + 'password' => 'test', + ] + ); + + $mediaObject = MediaObjectLogoFactory::createOne(); + $token = $this->JWTManager->create($user->object()); + + $this->browser() + ->post('/api/partners' , [ + 'json' => [ + 'name' => 'test customer', + 'type' => PartnerType::Customer, + 'street' => 'test street', + 'streetNo' => '11', + 'zip' => '22335', + 'city' => 'test city', + 'country' => 'test country', + 'website' => 'wwe.test.de', + 'logo' => '/api/medias/' . $mediaObject->getId(), + ], + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + 'Content-Type' => 'application/ld+json' + ] + ]) + ->assertSuccessful() + ; + + $this->browser() + ->get('/api/partners', [ + 'headers' => [ + 'Authorization' => 'Bearer ' . $token, + ], + ]) + ->assertSuccessful() + ->assertJsonMatches('"hydra:totalItems"', 1) + ->assertJsonMatches('"hydra:member"[0].name', 'test customer') + ; + } +} \ No newline at end of file diff --git a/tests/Functional/PostingResourceTest.php b/tests/Functional/PostingResourceTest.php index bc92ac0..7326001 100644 --- a/tests/Functional/PostingResourceTest.php +++ b/tests/Functional/PostingResourceTest.php @@ -13,6 +13,7 @@ use App\Factory\MediaObjectProfileFactory; use App\Factory\PartnerFactory; use App\Factory\PostingFactory; use App\Factory\UserFactory; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Zenstruck\Browser\Test\HasBrowser; use Zenstruck\Foundry\Test\Factories; @@ -24,9 +25,17 @@ class PostingResourceTest extends KernelTestCase use ResetDatabase; use Factories; + private JWTTokenManagerInterface $JWTManager; + + protected function setUp(): void + { + parent::setUp(); + $this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager'); + } + public function testPostPosting(): void { - UserFactory::createOne( + $user = UserFactory::createOne( [ 'email' => 'peter@test.de', 'firstName' => 'Peter', @@ -41,17 +50,7 @@ class PostingResourceTest extends KernelTestCase $contact = ContactFactory::createOne(); PostingFactory::createOne(); - $response = $this->browser() - ->post('/auth', [ - 'json' => [ - 'email' => 'peter@test.de', - 'password' => 'test', - ] - ]) - ->assertSuccessful() - ->content(); - $authResponseData = json_decode($response, true); - $token = $authResponseData['token']; + $token = $this->JWTManager->create($user->object()); $this->browser() ->post('/api/posts' , [ diff --git a/tests/Functional/UserResourceTest.php b/tests/Functional/UserResourceTest.php index 8e20daa..f28288d 100644 --- a/tests/Functional/UserResourceTest.php +++ b/tests/Functional/UserResourceTest.php @@ -8,6 +8,7 @@ namespace App\Tests\Functional; use App\Factory\UserFactory; +use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Zenstruck\Browser\Json; use Zenstruck\Browser\Test\HasBrowser; @@ -20,6 +21,14 @@ class UserResourceTest extends KernelTestCase use ResetDatabase; use Factories; + private JWTTokenManagerInterface $JWTManager; + + protected function setUp(): void + { + parent::setUp(); + $this->JWTManager = self::getContainer()->get('lexik_jwt_authentication.jwt_manager'); + } + public function testPostUser(): void { UserFactory::createOne( @@ -79,7 +88,7 @@ class UserResourceTest extends KernelTestCase public function testPostUserNoAdmin(): void { - UserFactory::createOne( + $user = UserFactory::createOne( [ 'email' => 'peter@test.de', 'firstName' => 'Peter', @@ -87,18 +96,8 @@ class UserResourceTest extends KernelTestCase 'password' => 'test', ] ); - $response = $this->browser() - ->post('/auth', [ - 'json' => [ - 'email' => 'peter@test.de', - 'password' => 'test', - ] - ]) - ->assertSuccessful() - ->content(); - $authResponseData = json_decode($response, true); - $token = $authResponseData['token']; + $token = $this->JWTManager->create($user->object()); $this->browser() ->post('/api/users' , [ 'json' => [ diff --git a/tests/fixtures/1176.png b/tests/fixtures/1176.png new file mode 100644 index 0000000000000000000000000000000000000000..54a8ef6d64ec964458d7f3b493346842901e721f GIT binary patch literal 3989 zcmeH~`8O1b7r+OZ%uM!?EjvA9Dv~8T!!Rbx7-C}bNMoC48+#$qWZyC*MYge%Y}qPf zOJ1R|Hre+*B~%RG-uJ!tM|{uuo^$WH+i&;YbMEKHVJu8I!6IM)0KjRAGQt7?EWcb9 z00-MIL#)Kv{4#9*2vZvl4vtT=mNUOXkT2?*KLC(%@Rzd4Visb5C4~c!xBzP(*MMMW z5&;k#9DKpUo9OT2>`S=dLvnk(r7Z#gur^@KY>>yt$80Po{xARU!2eJOfME}QEjeH* z0Bd0lU}0rD!45ph0Rlr#adL6<@bd9P1x^bIi-?{P6PJ*bl9rJ@`FQlrKF}kNT+0EW^3JUC93G z{>=MAF8M0s9|Lz+nt_OjUL-^?`S!6Gyx1#(w%@FkyX-%$*yb3i6r2`Z;bXaclsh#O z_xwxUhn0_Cp7YbDa+x`|!yH~By({s}s{4W8lHU)~-<3rlG*0A3XUO@xIP5<+J?lKz z{3duZEiR+|dh@{wvRIZ>2E`E8XF#hL~B$-{kQ@72~ELuu&gLdhiitwH!6MSeUbBBcvFC=7ps7^k(t5PoP z%t#uRy#BRiuKsR_oj9E~avAwJ%QL_L-|fff{Q~CLL3+TgBxDzX?pk;8v1MEz?juHc z=(pk;1Ih&WMt6rAe~!_b7)oB}@Q^zErhk1ybCBSvKJefk>oujbZmC>KS!{-2<5iAA zcBKMYqZp2i_Q*a{&7PZb^*cr@lDyn16;G*!??w$P#C8I*euxdaD~h=*)_*iGVX&C5 zEw7?>b_Y8yU5Uxw)sODu5QAgm2=GTm(dL;>kHCn4dJIdZoEwEpJv*AvD^fJi=_*C2 z2G~VLLdras;|G(WBmI8JtO_K0lnh&<-uW@wI54sMW0U*nd*GU&V~ou=>)x3$?`{DJ z;+>3^T^aT&ieDwy*xN$}akx^zwBnT!XnBh!J$mT!#Qu7@@dJ_}MG1SaJA8??0lX-! z!GgY=N~TiU5LK+G_!Pb)IR6#6rg>Eu3W21sM(m2?%Gyvl1p=t7^~>yL6Q_v#n2Pxe zvgK)fjRuQu!{xl7zQ+ZT%hxfmIBZFowrp_%pDw7ur1YvFAC|u)Qi%_PteR6r>GyER zX-63yCfg_7)UP5-Zy8BP=)bhjvr#hV{cJ2PQZ^RAVsi-f69@fp@LYjI1Ul|BuXJ~PtrX0p^IMxT9cLPQ0#F}B0(Y9 ziXy0>S0w!W#<}9hwGrv;#0EbRdJ=NM1h(M|tc2zi!#;#fls=kkagsVFWDg~Z<`lKv zA-TXlAINcP#)(pt#d7=K%$46UDMb6d!V&Z?R{e z4w|(OGO#lbz5paTWvI^5~m6nO5`+i&Koem`zVC(m`KyiM)Nk*hbPr!%g0^CrLV+ z)K6YewX)@HQ(08P&WKax6&vXk+oBulNH20qaTx2vD(0U9jhlyaIo%&oMlj@$nwa}$ zZUCYllX-Vgd-^NgPC0K6EVpU!8>dFg-jH5PJMrZ$MT$7J$YP^JYF;p;P%i?Ypo?at zh{ylrwONCeoqP!ucox}_Lm5txBzVOjKyvJUQMH=+zM^tD?Lq_{7IKO;U8n~}Q5Vb-r^^@NyDs}vZ8Ro})4~}1>MZ~vAfMuW!5;@ST zEJR`fbRq=nTL?W>YGZM;wDm|K|Jlc@u9rn>Aae7KqKazAtofdqY==Q zb3+$Iyyk-$-vp54)xlGjNdVg zd0b6`vSU;SlhO!*Y~>}!E32AO&S_?cZ+X$*J6oNqlIh7awQA_^ zmhxdKbcXLoAUXs9R>U%Z_$6Hv7Kx~aeQSn>`V?PY=rJ4Fi*maCQ<%!<158LfJuJjQ z`29|YeNQMF-l=6VRR1WrlVOb3N`i9@)|cdOi=nk5;o0sC^}KCus_JZfhY;t1Qsv~C zk{X;;wX%L40^^=n&w{VI>&k>f#S80!`14wb!XqwlA@uay9@Sg!^uycEo5i8vby~xk zJN=H~tdD#Z*BFWHG5BjLYGm^DCX17tp3#WZ4o%;eSP`3(#4QgnyqnX4{sfPMm(-*; zSzSs38O(Zvi9JbQ3stCsU~Y`9ibTRnF^n5A+e#Tp>W02??+udw4pXpAME>yT70mZd zEI7pBL!Y=F3P2qTi$XLq2Td-i>CbA*?K;D*s?4j&x1mh0;;^a46DP=>P-qujZRnnm zjd*_E`x+%9{wX$c4&~AbxMMcv6q%DUPo_GH)PNN9N+`~_oxw;&{l&(y(86OTY0}{_W?6Pk zkS|>wIl0uA)&^Qr&4@Xnif#S94f6IUhbqyi0RN_Ja`u$$GXKlr^(F|YA{N^!(VE)i z5R_Bk`T;CUGhrTio#(4t@@M)F_s0~SD4lj^=c_qNyQCr+xv+4*bb7;Ey>jvMnS9=S zylmM|KF;sEdw-mR?QH2&T=C_`bbF63a!kVWEbfSAVpLDPG&@se;h3w@tFJ>#*}K~P zXUdp6RuB99f|>u^Yi>?G|Lykno!89pC&lD3DY*uJJnxccT0u}X$0jNR-Yy_HgXpUT zu7*Tk!`**kr8(iwl}VK}GJyy!7Z<27E?UMsnr5k5b6b_K+Z}wzpC4_cJy=b8kbLnPhz*Shh{b>s<%Os+iKp9B zpBQMiJ8>nx{ToJlM|4db9utFUm4DO9{NM0mfLNDf(5bc@|Da8}Xx`=tlGIy4YL!tq zkFDPmHBuYv96rgqKCaAIkS_HMZXp^QyeM_u(>NqB#P~A4_U6R-2o3oGZ#Vw0Z2b!F<&78n(Sko5Scy4U_GJ{2!|Ih~KWy9;i6;{(3J=krqbP2&bt3 E09R5S9smFU literal 0 HcmV?d00001