diff --git a/.github/workflows/js.yml b/.github/workflows/js.yml
index cd5d161..7b0eec5 100644
--- a/.github/workflows/js.yml
+++ b/.github/workflows/js.yml
@@ -13,7 +13,7 @@ on:
- package.json
- .github/workflows/js.yml
branches:
- - main
+ - trunk
jobs:
eslint:
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index 5a21f32..300a848 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -11,7 +11,7 @@ on:
- composer.json
- .github/workflows/php.yml
branches:
- - main
+ - trunk
workflow_dispatch:
jobs:
@@ -73,6 +73,6 @@ jobs:
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run Infection
- run: composer infection
+ run: composer infection -- --min-msi=95
env:
INFECTION_DASHBOARD_API_KEY: ${{ secrets.INFECTION_DASHBOARD_API_KEY }}
\ No newline at end of file
diff --git a/.platform.app.yaml b/.platform.app.yaml
index 38c9e87..abf824c 100644
--- a/.platform.app.yaml
+++ b/.platform.app.yaml
@@ -27,6 +27,14 @@ variables:
CORS_ALLOW_ORIGIN: '*'
DATABASE_URL: mysql://user:@database.internal:3306/main
+crons:
+ snapshot:
+ spec: 0 0 * * *
+ cmd: |
+ # only run for the production environment, aka trunk
+ if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
+ croncape bin/console report:turnover
+ fi
# The hooks that will be performed when the package is deployed.
hooks:
diff --git a/composer.json b/composer.json
index 535f16d..7284cda 100644
--- a/composer.json
+++ b/composer.json
@@ -11,21 +11,23 @@
"doctrine/doctrine-bundle": "^2.10",
"doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.16",
+ "guzzlehttp/guzzle": "^7.8",
"guzzlehttp/psr7": "^2.6",
"nelmio/cors-bundle": "^2.3",
"shopware/app-bundle": "^2.0",
- "symfony/console": "7.0.*",
- "symfony/dotenv": "7.0.*",
- "symfony/http-foundation": "7.0.*",
+ "symfony/console": "^7.0",
+ "symfony/dotenv": "^7.0",
+ "symfony/http-foundation": "^7.0",
"symfony/flex": "^2",
- "symfony/framework-bundle": "7.0.*",
+ "symfony/framework-bundle": "^7.0",
"symfony/monolog-bundle": "^3.8",
- "symfony/property-access": "7.0.*",
- "symfony/runtime": "7.0.*",
- "symfony/serializer": "7.0.*",
- "symfony/uid": "7.0.*",
+ "symfony/property-access": "^7.0",
+ "symfony/psr-http-message-bridge": "^7.0",
+ "symfony/runtime": "^7.0",
+ "symfony/serializer": "^7.0",
+ "symfony/uid": "^7.0",
"symfony/webpack-encore-bundle": "^2.0",
- "symfony/yaml": "7.0.*"
+ "symfony/yaml": "^7.0"
},
"config": {
"allow-plugins": {
diff --git a/composer.lock b/composer.lock
index cb64c29..878403c 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": "4bd7f67f98c6ba8778dc21ede5cd91ce",
+ "content-hash": "7a6c3c4a4c2c703e15f5de85203b21ff",
"packages": [
{
"name": "braintree/braintree_php",
@@ -327,16 +327,16 @@
},
{
"name": "doctrine/dbal",
- "version": "3.7.2",
+ "version": "3.7.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "0ac3c270590e54910715e9a1a044cc368df282b2"
+ "reference": "ce594cbc39a4866c544f1a970d285ff0548221ad"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/0ac3c270590e54910715e9a1a044cc368df282b2",
- "reference": "0ac3c270590e54910715e9a1a044cc368df282b2",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/ce594cbc39a4866c544f1a970d285ff0548221ad",
+ "reference": "ce594cbc39a4866c544f1a970d285ff0548221ad",
"shasum": ""
},
"require": {
@@ -352,14 +352,14 @@
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.1",
- "phpstan/phpstan": "1.10.42",
+ "phpstan/phpstan": "1.10.56",
"phpstan/phpstan-strict-rules": "^1.5",
- "phpunit/phpunit": "9.6.13",
+ "phpunit/phpunit": "9.6.15",
"psalm/plugin-phpunit": "0.18.4",
"slevomat/coding-standard": "8.13.1",
- "squizlabs/php_codesniffer": "3.7.2",
- "symfony/cache": "^5.4|^6.0",
- "symfony/console": "^4.4|^5.4|^6.0",
+ "squizlabs/php_codesniffer": "3.8.1",
+ "symfony/cache": "^5.4|^6.0|^7.0",
+ "symfony/console": "^4.4|^5.4|^6.0|^7.0",
"vimeo/psalm": "4.30.0"
},
"suggest": {
@@ -420,7 +420,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
- "source": "https://github.com/doctrine/dbal/tree/3.7.2"
+ "source": "https://github.com/doctrine/dbal/tree/3.7.3"
},
"funding": [
{
@@ -436,7 +436,7 @@
"type": "tidelift"
}
],
- "time": "2023-11-19T08:06:58+00:00"
+ "time": "2024-01-21T07:53:09+00:00"
},
{
"name": "doctrine/deprecations",
@@ -1378,6 +1378,215 @@
},
"time": "2022-05-23T21:33:49+00:00"
},
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104",
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0.1",
+ "guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-curl": "*",
+ "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:35:24+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223",
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/2.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:19:20+00:00"
+ },
{
"name": "guzzlehttp/psr7",
"version": "2.6.2",
@@ -2643,31 +2852,31 @@
},
{
"name": "symfony/cache",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/cache.git",
- "reference": "378e30a864c868d635353f103a5a5e7569f029ec"
+ "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/cache/zipball/378e30a864c868d635353f103a5a5e7569f029ec",
- "reference": "378e30a864c868d635353f103a5a5e7569f029ec",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/14a75869bbb41cb35bc5d9d322473928c6f3f978",
+ "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"psr/cache": "^2.0|^3.0",
"psr/log": "^1.1|^2|^3",
"symfony/cache-contracts": "^2.5|^3",
"symfony/service-contracts": "^2.5|^3",
- "symfony/var-exporter": "^6.4|^7.0"
+ "symfony/var-exporter": "^6.3.6|^7.0"
},
"conflict": {
- "doctrine/dbal": "<3.6",
- "symfony/dependency-injection": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/var-dumper": "<6.4"
+ "doctrine/dbal": "<2.13.1",
+ "symfony/dependency-injection": "<5.4",
+ "symfony/http-kernel": "<5.4",
+ "symfony/var-dumper": "<5.4"
},
"provide": {
"psr/cache-implementation": "2.0|3.0",
@@ -2676,15 +2885,15 @@
},
"require-dev": {
"cache/integration-tests": "dev-master",
- "doctrine/dbal": "^3.6|^4",
+ "doctrine/dbal": "^2.13.1|^3|^4",
"predis/predis": "^1.1|^2.0",
"psr/simple-cache": "^1.0|^2.0|^3.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/filesystem": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0"
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/filesystem": "^5.4|^6.0|^7.0",
+ "symfony/http-kernel": "^5.4|^6.0|^7.0",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -2719,7 +2928,7 @@
"psr6"
],
"support": {
- "source": "https://github.com/symfony/cache/tree/v7.0.2"
+ "source": "https://github.com/symfony/cache/tree/v6.4.2"
},
"funding": [
{
@@ -2735,7 +2944,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-29T15:37:40+00:00"
+ "time": "2023-12-29T15:34:34+00:00"
},
{
"name": "symfony/cache-contracts",
@@ -2815,34 +3024,34 @@
},
{
"name": "symfony/config",
- "version": "v7.0.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "8789646600f4e7e451dde9e1dc81cfa429f3857a"
+ "reference": "5d33e0fb707d603330e0edfd4691803a1253572e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/8789646600f4e7e451dde9e1dc81cfa429f3857a",
- "reference": "8789646600f4e7e451dde9e1dc81cfa429f3857a",
+ "url": "https://api.github.com/repos/symfony/config/zipball/5d33e0fb707d603330e0edfd4691803a1253572e",
+ "reference": "5d33e0fb707d603330e0edfd4691803a1253572e",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/filesystem": "^6.4|^7.0",
+ "symfony/filesystem": "^5.4|^6.0|^7.0",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
- "symfony/finder": "<6.4",
+ "symfony/finder": "<5.4",
"symfony/service-contracts": "<2.5"
},
"require-dev": {
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
+ "symfony/finder": "^5.4|^6.0|^7.0",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/yaml": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -2870,7 +3079,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.0"
+ "source": "https://github.com/symfony/config/tree/v6.4.0"
},
"funding": [
{
@@ -2886,7 +3095,7 @@
"type": "tidelift"
}
],
- "time": "2023-11-09T08:30:23+00:00"
+ "time": "2023-11-09T08:28:32+00:00"
},
{
"name": "symfony/console",
@@ -2983,39 +3192,40 @@
},
{
"name": "symfony/dependency-injection",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "bd25ef7c937b9da12510bdc4f1c66728f19620e3"
+ "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/bd25ef7c937b9da12510bdc4f1c66728f19620e3",
- "reference": "bd25ef7c937b9da12510bdc4f1c66728f19620e3",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/226ea431b1eda6f0d9f5a4b278757171960bb195",
+ "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"psr/container": "^1.1|^2.0",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/service-contracts": "^3.3",
- "symfony/var-exporter": "^6.4|^7.0"
+ "symfony/service-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^6.2.10|^7.0"
},
"conflict": {
"ext-psr": "<1.1|>=2",
- "symfony/config": "<6.4",
- "symfony/finder": "<6.4",
- "symfony/yaml": "<6.4"
+ "symfony/config": "<6.1",
+ "symfony/finder": "<5.4",
+ "symfony/proxy-manager-bridge": "<6.3",
+ "symfony/yaml": "<5.4"
},
"provide": {
"psr/container-implementation": "1.1|2.0",
"symfony/service-implementation": "1.1|2.0|3.0"
},
"require-dev": {
- "symfony/config": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/config": "^6.1|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/yaml": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3043,7 +3253,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.2"
+ "source": "https://github.com/symfony/dependency-injection/tree/v6.4.2"
},
"funding": [
{
@@ -3059,7 +3269,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-28T19:18:20+00:00"
+ "time": "2023-12-28T19:16:56+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -3130,65 +3340,67 @@
},
{
"name": "symfony/doctrine-bridge",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/doctrine-bridge.git",
- "reference": "9c0ce8ff41c25fbee07cd3235e9d6f0d6505b8b3"
+ "reference": "da33f27c1dd9946afecfd1585b867551df71bf53"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/9c0ce8ff41c25fbee07cd3235e9d6f0d6505b8b3",
- "reference": "9c0ce8ff41c25fbee07cd3235e9d6f0d6505b8b3",
+ "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/da33f27c1dd9946afecfd1585b867551df71bf53",
+ "reference": "da33f27c1dd9946afecfd1585b867551df71bf53",
"shasum": ""
},
"require": {
- "doctrine/event-manager": "^2",
+ "doctrine/event-manager": "^1.2|^2",
"doctrine/persistence": "^3.1",
- "php": ">=8.2",
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
- "doctrine/dbal": "<3.6",
+ "doctrine/dbal": "<2.13.1",
"doctrine/lexer": "<1.1",
"doctrine/orm": "<2.15",
- "symfony/cache": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/form": "<6.4",
- "symfony/http-foundation": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/lock": "<6.4",
- "symfony/messenger": "<6.4",
- "symfony/property-info": "<6.4",
- "symfony/security-bundle": "<6.4",
+ "symfony/cache": "<5.4",
+ "symfony/dependency-injection": "<6.2",
+ "symfony/form": "<5.4.21|>=6,<6.2.7",
+ "symfony/http-foundation": "<6.3",
+ "symfony/http-kernel": "<6.2",
+ "symfony/lock": "<6.3",
+ "symfony/messenger": "<5.4",
+ "symfony/property-info": "<5.4",
+ "symfony/security-bundle": "<5.4",
"symfony/security-core": "<6.4",
"symfony/validator": "<6.4"
},
"require-dev": {
"doctrine/collections": "^1.0|^2.0",
"doctrine/data-fixtures": "^1.1",
- "doctrine/dbal": "^3.6|^4",
+ "doctrine/dbal": "^2.13.1|^3|^4",
"doctrine/orm": "^2.15|^3",
"psr/log": "^1|^2|^3",
- "symfony/cache": "^6.4|^7.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/doctrine-messenger": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/lock": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/property-info": "^6.4|^7.0",
+ "symfony/cache": "^5.4|^6.0|^7.0",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^6.2|^7.0",
+ "symfony/doctrine-messenger": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/form": "^5.4.21|^6.2.7|^7.0",
+ "symfony/http-kernel": "^6.3|^7.0",
+ "symfony/lock": "^6.3|^7.0",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/property-access": "^5.4|^6.0|^7.0",
+ "symfony/property-info": "^5.4|^6.0|^7.0",
+ "symfony/proxy-manager-bridge": "^6.4",
"symfony/security-core": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/uid": "^6.4|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/translation": "^5.4|^6.0|^7.0",
+ "symfony/uid": "^5.4|^6.0|^7.0",
"symfony/validator": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0"
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"type": "symfony-bridge",
"autoload": {
@@ -3216,7 +3428,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.2"
+ "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.2"
},
"funding": [
{
@@ -3232,7 +3444,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-27T08:42:13+00:00"
+ "time": "2023-12-27T00:32:33+00:00"
},
{
"name": "symfony/dotenv",
@@ -3310,22 +3522,22 @@
},
{
"name": "symfony/error-handler",
- "version": "v7.0.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "80b1258be1b84c12a345d0ec3881bbf2e5270cc2"
+ "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/80b1258be1b84c12a345d0ec3881bbf2e5270cc2",
- "reference": "80b1258be1b84c12a345d0ec3881bbf2e5270cc2",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/c873490a1c97b3a0a4838afc36ff36c112d02788",
+ "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"psr/log": "^1|^2|^3",
- "symfony/var-dumper": "^6.4|^7.0"
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"conflict": {
"symfony/deprecation-contracts": "<2.5",
@@ -3334,7 +3546,7 @@
"require-dev": {
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/http-kernel": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0"
+ "symfony/serializer": "^5.4|^6.0|^7.0"
},
"bin": [
"Resources/bin/patch-type-declarations"
@@ -3365,7 +3577,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.0"
+ "source": "https://github.com/symfony/error-handler/tree/v6.4.0"
},
"funding": [
{
@@ -3381,28 +3593,28 @@
"type": "tidelift"
}
],
- "time": "2023-10-20T16:35:23+00:00"
+ "time": "2023-10-18T09:43:34+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a"
+ "reference": "e95216850555cd55e71b857eb9d6c2674124603a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/098b62ae81fdd6cbf941f355059f617db28f4f9a",
- "reference": "098b62ae81fdd6cbf941f355059f617db28f4f9a",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a",
+ "reference": "e95216850555cd55e71b857eb9d6c2674124603a",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"symfony/event-dispatcher-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/dependency-injection": "<6.4",
+ "symfony/dependency-injection": "<5.4",
"symfony/service-contracts": "<2.5"
},
"provide": {
@@ -3411,13 +3623,13 @@
},
"require-dev": {
"psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/error-handler": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/http-foundation": "^5.4|^6.0|^7.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^6.4|^7.0"
+ "symfony/stopwatch": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3445,7 +3657,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/v7.0.2"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.2"
},
"funding": [
{
@@ -3461,7 +3673,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-27T22:24:19+00:00"
+ "time": "2023-12-27T22:16:42+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -3541,20 +3753,20 @@
},
{
"name": "symfony/filesystem",
- "version": "v7.0.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7"
+ "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/7da8ea2362a283771478c5f7729cfcb43a76b8b7",
- "reference": "7da8ea2362a283771478c5f7729cfcb43a76b8b7",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59",
+ "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
@@ -3584,7 +3796,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v7.0.0"
+ "source": "https://github.com/symfony/filesystem/tree/v6.4.0"
},
"funding": [
{
@@ -3600,27 +3812,27 @@
"type": "tidelift"
}
],
- "time": "2023-07-27T06:33:22+00:00"
+ "time": "2023-07-26T17:27:13+00:00"
},
{
"name": "symfony/finder",
- "version": "v7.0.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56"
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
- "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce",
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=8.1"
},
"require-dev": {
- "symfony/filesystem": "^6.4|^7.0"
+ "symfony/filesystem": "^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3648,7 +3860,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v7.0.0"
+ "source": "https://github.com/symfony/finder/tree/v6.4.0"
},
"funding": [
{
@@ -3664,7 +3876,7 @@
"type": "tidelift"
}
],
- "time": "2023-10-31T17:59:56+00:00"
+ "time": "2023-10-31T17:30:12+00:00"
},
{
"name": "symfony/flex",
@@ -3879,27 +4091,28 @@
},
{
"name": "symfony/http-client",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
- "reference": "db714986d3b84330bb6196fdb201c9f79b3a8853"
+ "reference": "fc0944665bd932cf32a7b8a1d009466afc16528f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client/zipball/db714986d3b84330bb6196fdb201c9f79b3a8853",
- "reference": "db714986d3b84330bb6196fdb201c9f79b3a8853",
+ "url": "https://api.github.com/repos/symfony/http-client/zipball/fc0944665bd932cf32a7b8a1d009466afc16528f",
+ "reference": "fc0944665bd932cf32a7b8a1d009466afc16528f",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"psr/log": "^1|^2|^3",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/http-client-contracts": "^3",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
"php-http/discovery": "<1.15",
- "symfony/http-foundation": "<6.4"
+ "symfony/http-foundation": "<6.3"
},
"provide": {
"php-http/async-client-implementation": "*",
@@ -3916,11 +4129,11 @@
"nyholm/psr7": "^1.0",
"php-http/httplug": "^1.0|^2.0",
"psr/http-client": "^1.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0"
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/http-kernel": "^5.4|^6.0|^7.0",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -3951,7 +4164,7 @@
"http"
],
"support": {
- "source": "https://github.com/symfony/http-client/tree/v7.0.2"
+ "source": "https://github.com/symfony/http-client/tree/v6.4.2"
},
"funding": [
{
@@ -3967,7 +4180,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-02T12:51:19+00:00"
+ "time": "2023-12-02T12:49:56+00:00"
},
{
"name": "symfony/http-client-contracts",
@@ -4126,71 +4339,72 @@
},
{
"name": "symfony/http-kernel",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "237d3008bc3f5db3e066e348dc0a6435d70a52bb"
+ "reference": "13e8387320b5942d0dc408440c888e2d526efef4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/237d3008bc3f5db3e066e348dc0a6435d70a52bb",
- "reference": "237d3008bc3f5db3e066e348dc0a6435d70a52bb",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4",
+ "reference": "13e8387320b5942d0dc408440c888e2d526efef4",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"psr/log": "^1|^2|^3",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/error-handler": "^6.4|^7.0",
- "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/http-foundation": "^6.4|^7.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
- "symfony/browser-kit": "<6.4",
- "symfony/cache": "<6.4",
- "symfony/config": "<6.4",
- "symfony/console": "<6.4",
+ "symfony/browser-kit": "<5.4",
+ "symfony/cache": "<5.4",
+ "symfony/config": "<6.1",
+ "symfony/console": "<5.4",
"symfony/dependency-injection": "<6.4",
- "symfony/doctrine-bridge": "<6.4",
- "symfony/form": "<6.4",
- "symfony/http-client": "<6.4",
+ "symfony/doctrine-bridge": "<5.4",
+ "symfony/form": "<5.4",
+ "symfony/http-client": "<5.4",
"symfony/http-client-contracts": "<2.5",
- "symfony/mailer": "<6.4",
- "symfony/messenger": "<6.4",
- "symfony/translation": "<6.4",
+ "symfony/mailer": "<5.4",
+ "symfony/messenger": "<5.4",
+ "symfony/translation": "<5.4",
"symfony/translation-contracts": "<2.5",
- "symfony/twig-bridge": "<6.4",
+ "symfony/twig-bridge": "<5.4",
"symfony/validator": "<6.4",
- "symfony/var-dumper": "<6.4",
- "twig/twig": "<3.0.4"
+ "symfony/var-dumper": "<6.3",
+ "twig/twig": "<2.13"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
"psr/cache": "^1.0|^2.0|^3.0",
- "symfony/browser-kit": "^6.4|^7.0",
- "symfony/clock": "^6.4|^7.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/css-selector": "^6.4|^7.0",
+ "symfony/browser-kit": "^5.4|^6.0|^7.0",
+ "symfony/clock": "^6.2|^7.0",
+ "symfony/config": "^6.1|^7.0",
+ "symfony/console": "^5.4|^6.0|^7.0",
+ "symfony/css-selector": "^5.4|^6.0|^7.0",
"symfony/dependency-injection": "^6.4|^7.0",
- "symfony/dom-crawler": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
+ "symfony/dom-crawler": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/finder": "^5.4|^6.0|^7.0",
"symfony/http-client-contracts": "^2.5|^3",
- "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/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
+ "symfony/property-access": "^5.4.5|^6.0.5|^7.0",
+ "symfony/routing": "^5.4|^6.0|^7.0",
+ "symfony/serializer": "^6.3|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/translation": "^5.4|^6.0|^7.0",
"symfony/translation-contracts": "^2.5|^3",
- "symfony/uid": "^6.4|^7.0",
+ "symfony/uid": "^5.4|^6.0|^7.0",
"symfony/validator": "^6.4|^7.0",
- "symfony/var-exporter": "^6.4|^7.0",
- "twig/twig": "^3.0.4"
+ "symfony/var-exporter": "^6.2|^7.0",
+ "twig/twig": "^2.13|^3.0.4"
},
"type": "library",
"autoload": {
@@ -4218,7 +4432,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.2"
+ "source": "https://github.com/symfony/http-kernel/tree/v6.4.2"
},
"funding": [
{
@@ -4234,7 +4448,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-30T15:41:17+00:00"
+ "time": "2023-12-30T15:31:44+00:00"
},
{
"name": "symfony/monolog-bridge",
@@ -4884,33 +5098,33 @@
},
{
"name": "symfony/property-info",
- "version": "v7.0.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/property-info.git",
- "reference": "ce627df05f5629ce4feec536ee827ad0a12689b6"
+ "reference": "288be71bae2ebc88676f5d3a03d23f70b278fcc1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/property-info/zipball/ce627df05f5629ce4feec536ee827ad0a12689b6",
- "reference": "ce627df05f5629ce4feec536ee827ad0a12689b6",
+ "url": "https://api.github.com/repos/symfony/property-info/zipball/288be71bae2ebc88676f5d3a03d23f70b278fcc1",
+ "reference": "288be71bae2ebc88676f5d3a03d23f70b278fcc1",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/string": "^6.4|^7.0"
+ "php": ">=8.1",
+ "symfony/string": "^5.4|^6.0|^7.0"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<5.2",
"phpdocumentor/type-resolver": "<1.5.1",
- "symfony/dependency-injection": "<6.4",
+ "symfony/dependency-injection": "<5.4",
"symfony/serializer": "<6.4"
},
"require-dev": {
"phpdocumentor/reflection-docblock": "^5.2",
"phpstan/phpdoc-parser": "^1.0",
- "symfony/cache": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/cache": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
"symfony/serializer": "^6.4|^7.0"
},
"type": "library",
@@ -4947,7 +5161,7 @@
"validator"
],
"support": {
- "source": "https://github.com/symfony/property-info/tree/v7.0.0"
+ "source": "https://github.com/symfony/property-info/tree/v6.4.0"
},
"funding": [
{
@@ -4963,7 +5177,7 @@
"type": "tidelift"
}
],
- "time": "2023-11-25T08:38:27+00:00"
+ "time": "2023-11-25T16:57:46+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
@@ -5050,34 +5264,36 @@
},
{
"name": "symfony/routing",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "78866be67255f42716271e33d1d8b64eb6e47bd9"
+ "reference": "98eab13a07fddc85766f1756129c69f207ffbc21"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/78866be67255f42716271e33d1d8b64eb6e47bd9",
- "reference": "78866be67255f42716271e33d1d8b64eb6e47bd9",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21",
+ "reference": "98eab13a07fddc85766f1756129c69f207ffbc21",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/config": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/yaml": "<6.4"
+ "doctrine/annotations": "<1.12",
+ "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": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/config": "^6.2|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/http-foundation": "^5.4|^6.0|^7.0",
+ "symfony/yaml": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -5111,7 +5327,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v7.0.2"
+ "source": "https://github.com/symfony/routing/tree/v6.4.2"
},
"funding": [
{
@@ -5127,7 +5343,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-29T15:37:40+00:00"
+ "time": "2023-12-29T15:34:34+00:00"
},
{
"name": "symfony/runtime",
@@ -5449,20 +5665,20 @@
},
{
"name": "symfony/string",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5"
+ "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/cc78f14f91f5e53b42044d0620961c48028ff9f5",
- "reference": "cc78f14f91f5e53b42044d0620961c48028ff9f5",
+ "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc",
+ "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
@@ -5472,11 +5688,11 @@
"symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
+ "symfony/error-handler": "^5.4|^6.0|^7.0",
+ "symfony/http-client": "^5.4|^6.0|^7.0",
+ "symfony/intl": "^6.2|^7.0",
"symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^6.4|^7.0"
+ "symfony/var-exporter": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -5515,7 +5731,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.0.2"
+ "source": "https://github.com/symfony/string/tree/v6.4.2"
},
"funding": [
{
@@ -5531,7 +5747,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-10T16:54:46+00:00"
+ "time": "2023-12-10T16:15:48+00:00"
},
{
"name": "symfony/uid",
@@ -5609,32 +5825,34 @@
},
{
"name": "symfony/var-dumper",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "5f6f1a527002068f6d40fda068399220eabebf71"
+ "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/5f6f1a527002068f6d40fda068399220eabebf71",
- "reference": "5f6f1a527002068f6d40fda068399220eabebf71",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f",
+ "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "symfony/console": "<6.4"
+ "symfony/console": "<5.4"
},
"require-dev": {
"ext-iconv": "*",
- "symfony/console": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/uid": "^6.4|^7.0",
- "twig/twig": "^3.0.4"
+ "symfony/console": "^5.4|^6.0|^7.0",
+ "symfony/error-handler": "^6.3|^7.0",
+ "symfony/http-kernel": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
+ "symfony/uid": "^5.4|^6.0|^7.0",
+ "twig/twig": "^2.13|^3.0.4"
},
"bin": [
"Resources/bin/var-dump-server"
@@ -5672,7 +5890,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v7.0.2"
+ "source": "https://github.com/symfony/var-dumper/tree/v6.4.2"
},
"funding": [
{
@@ -5688,27 +5906,28 @@
"type": "tidelift"
}
],
- "time": "2023-12-28T19:18:20+00:00"
+ "time": "2023-12-28T19:16:56+00:00"
},
{
"name": "symfony/var-exporter",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
- "reference": "345c62fefe92243c3a06fc0cc65f2ec1a47e0764"
+ "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-exporter/zipball/345c62fefe92243c3a06fc0cc65f2ec1a47e0764",
- "reference": "345c62fefe92243c3a06fc0cc65f2ec1a47e0764",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5fe9a0021b8d35e67d914716ec8de50716a68e7e",
+ "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"require-dev": {
- "symfony/var-dumper": "^6.4|^7.0"
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"type": "library",
"autoload": {
@@ -5746,7 +5965,7 @@
"serialize"
],
"support": {
- "source": "https://github.com/symfony/var-exporter/tree/v7.0.2"
+ "source": "https://github.com/symfony/var-exporter/tree/v6.4.2"
},
"funding": [
{
@@ -5762,7 +5981,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-27T08:42:13+00:00"
+ "time": "2023-12-27T08:18:35+00:00"
},
{
"name": "symfony/webpack-encore-bundle",
@@ -6280,16 +6499,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
- "version": "v3.47.1",
+ "version": "v3.48.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
- "reference": "173c60d1eff911c9c54322704623a45561d3241d"
+ "reference": "a92472c6fb66349de25211f31c77eceae3df024e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/173c60d1eff911c9c54322704623a45561d3241d",
- "reference": "173c60d1eff911c9c54322704623a45561d3241d",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a92472c6fb66349de25211f31c77eceae3df024e",
+ "reference": "a92472c6fb66349de25211f31c77eceae3df024e",
"shasum": ""
},
"require": {
@@ -6359,7 +6578,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
- "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.47.1"
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.48.0"
},
"funding": [
{
@@ -6367,7 +6586,7 @@
"type": "github"
}
],
- "time": "2024-01-16T18:54:21+00:00"
+ "time": "2024-01-19T21:44:39+00:00"
},
{
"name": "infection/abstract-testframework-adapter",
@@ -8904,20 +9123,20 @@
},
{
"name": "symfony/options-resolver",
- "version": "v7.0.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "700ff4096e346f54cb628ea650767c8130f1001f"
+ "reference": "22301f0e7fdeaacc14318928612dee79be99860e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f",
- "reference": "700ff4096e346f54cb628ea650767c8130f1001f",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e",
+ "reference": "22301f0e7fdeaacc14318928612dee79be99860e",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
"symfony/deprecation-contracts": "^2.5|^3"
},
"type": "library",
@@ -8951,7 +9170,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.0.0"
+ "source": "https://github.com/symfony/options-resolver/tree/v6.4.0"
},
"funding": [
{
@@ -8967,24 +9186,24 @@
"type": "tidelift"
}
],
- "time": "2023-08-08T10:20:21+00:00"
+ "time": "2023-08-08T10:16:24+00:00"
},
{
"name": "symfony/process",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "acd3eb5cb02382c1cb0287ba29b2908cc6ffa83a"
+ "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/acd3eb5cb02382c1cb0287ba29b2908cc6ffa83a",
- "reference": "acd3eb5cb02382c1cb0287ba29b2908cc6ffa83a",
+ "url": "https://api.github.com/repos/symfony/process/zipball/c4b1ef0bc80533d87a2e969806172f1c2a980241",
+ "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=8.1"
},
"type": "library",
"autoload": {
@@ -9012,7 +9231,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v7.0.2"
+ "source": "https://github.com/symfony/process/tree/v6.4.2"
},
"funding": [
{
@@ -9028,7 +9247,7 @@
"type": "tidelift"
}
],
- "time": "2023-12-24T09:15:37+00:00"
+ "time": "2023-12-22T16:42:54+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -9110,64 +9329,65 @@
},
{
"name": "symfony/twig-bridge",
- "version": "v7.0.2",
+ "version": "v6.4.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/twig-bridge.git",
- "reference": "d6236c6e75ee70317a27f0fd4c3f9bb956f22366"
+ "reference": "97af829e4733125ee70e806694d56165c60b4ee1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d6236c6e75ee70317a27f0fd4c3f9bb956f22366",
- "reference": "d6236c6e75ee70317a27f0fd4c3f9bb956f22366",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/97af829e4733125ee70e806694d56165c60b4ee1",
+ "reference": "97af829e4733125ee70e806694d56165c60b4ee1",
"shasum": ""
},
"require": {
- "php": ">=8.2",
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/translation-contracts": "^2.5|^3",
- "twig/twig": "^3.0.4"
+ "twig/twig": "^2.13|^3.0.4"
},
"conflict": {
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
- "symfony/console": "<6.4",
- "symfony/form": "<6.4",
- "symfony/http-foundation": "<6.4",
+ "symfony/console": "<5.4",
+ "symfony/form": "<6.3",
+ "symfony/http-foundation": "<5.4",
"symfony/http-kernel": "<6.4",
- "symfony/mime": "<6.4",
+ "symfony/mime": "<6.2",
"symfony/serializer": "<6.4",
- "symfony/translation": "<6.4",
- "symfony/workflow": "<6.4"
+ "symfony/translation": "<5.4",
+ "symfony/workflow": "<5.4"
},
"require-dev": {
"egulias/email-validator": "^2.1.10|^3|^4",
"league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
- "symfony/asset": "^6.4|^7.0",
- "symfony/asset-mapper": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
+ "symfony/asset": "^5.4|^6.0|^7.0",
+ "symfony/asset-mapper": "^6.3|^7.0",
+ "symfony/console": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/finder": "^5.4|^6.0|^7.0",
"symfony/form": "^6.4|^7.0",
- "symfony/html-sanitizer": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/html-sanitizer": "^6.1|^7.0",
+ "symfony/http-foundation": "^5.4|^6.0|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
+ "symfony/intl": "^5.4|^6.0|^7.0",
+ "symfony/mime": "^6.2|^7.0",
"symfony/polyfill-intl-icu": "~1.0",
- "symfony/property-info": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
+ "symfony/property-info": "^5.4|^6.0|^7.0",
+ "symfony/routing": "^5.4|^6.0|^7.0",
"symfony/security-acl": "^2.8|^3.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/security-csrf": "^6.4|^7.0",
- "symfony/security-http": "^6.4|^7.0",
+ "symfony/security-core": "^5.4|^6.0|^7.0",
+ "symfony/security-csrf": "^5.4|^6.0|^7.0",
+ "symfony/security-http": "^5.4|^6.0|^7.0",
"symfony/serializer": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/web-link": "^6.4|^7.0",
- "symfony/workflow": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/translation": "^6.1|^7.0",
+ "symfony/web-link": "^5.4|^6.0|^7.0",
+ "symfony/workflow": "^5.4|^6.0|^7.0",
+ "symfony/yaml": "^5.4|^6.0|^7.0",
"twig/cssinliner-extra": "^2.12|^3",
"twig/inky-extra": "^2.12|^3",
"twig/markdown-extra": "^2.12|^3"
@@ -9198,7 +9418,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.2"
+ "source": "https://github.com/symfony/twig-bridge/tree/v6.4.2"
},
"funding": [
{
@@ -9214,47 +9434,47 @@
"type": "tidelift"
}
],
- "time": "2023-12-15T12:36:57+00:00"
+ "time": "2023-12-15T12:36:48+00:00"
},
{
"name": "symfony/twig-bundle",
- "version": "v7.0.0",
+ "version": "v6.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/twig-bundle.git",
- "reference": "42c4a60f1b83894cd85a6b00533f8216c413ac11"
+ "reference": "35d84393e598dfb774e6a2bf49e5229a8a6dbe4c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/42c4a60f1b83894cd85a6b00533f8216c413ac11",
- "reference": "42c4a60f1b83894cd85a6b00533f8216c413ac11",
+ "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/35d84393e598dfb774e6a2bf49e5229a8a6dbe4c",
+ "reference": "35d84393e598dfb774e6a2bf49e5229a8a6dbe4c",
"shasum": ""
},
"require": {
"composer-runtime-api": ">=2.1",
- "php": ">=8.2",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/twig-bridge": "^6.4|^7.0",
- "twig/twig": "^3.0.4"
+ "php": ">=8.1",
+ "symfony/config": "^6.1|^7.0",
+ "symfony/dependency-injection": "^6.1|^7.0",
+ "symfony/http-foundation": "^5.4|^6.0|^7.0",
+ "symfony/http-kernel": "^6.2",
+ "symfony/twig-bridge": "^6.4",
+ "twig/twig": "^2.13|^3.0.4"
},
"conflict": {
- "symfony/framework-bundle": "<6.4",
- "symfony/translation": "<6.4"
+ "symfony/framework-bundle": "<5.4",
+ "symfony/translation": "<5.4"
},
"require-dev": {
- "symfony/asset": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/framework-bundle": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/web-link": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/asset": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/finder": "^5.4|^6.0|^7.0",
+ "symfony/form": "^5.4|^6.0|^7.0",
+ "symfony/framework-bundle": "^5.4|^6.0|^7.0",
+ "symfony/routing": "^5.4|^6.0|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/translation": "^5.4|^6.0|^7.0",
+ "symfony/web-link": "^5.4|^6.0|^7.0",
+ "symfony/yaml": "^5.4|^6.0|^7.0"
},
"type": "symfony-bundle",
"autoload": {
@@ -9282,7 +9502,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.0"
+ "source": "https://github.com/symfony/twig-bundle/tree/v6.4.0"
},
"funding": [
{
@@ -9298,7 +9518,7 @@
"type": "tidelift"
}
],
- "time": "2023-11-26T15:16:53+00:00"
+ "time": "2023-11-07T14:57:07+00:00"
},
{
"name": "symfony/web-profiler-bundle",
@@ -9882,5 +10102,5 @@
"ext-iconv": "*"
},
"platform-dev": [],
- "plugin-api-version": "2.6.0"
+ "plugin-api-version": "2.3.0"
}
diff --git a/config/services/braintree.xml b/config/services/braintree.xml
index 6688fe8..1294f7b 100644
--- a/config/services/braintree.xml
+++ b/config/services/braintree.xml
@@ -19,5 +19,19 @@
+
+
+
+
+ https://api.shopware.com
+
+
+
+
+
+
+ %env(default::REPORT_IDENTIFIER)%
+
+
diff --git a/infection.json5 b/infection.json5
index b75476a..e648d7a 100644
--- a/infection.json5
+++ b/infection.json5
@@ -6,6 +6,7 @@
],
excludes: [
"Command/SetupUrlCommand.php", // internal utility command, that needs no testing
+ "Command/ReportTurnoverCommand.php", // wrapper around tested ReportService.php
"Entity/",
"Tests/" // changes that doesn't break tests are fine
]
diff --git a/migrations/Version20240118141652AddTransactionReport.php b/migrations/Version20240118141652AddTransactionReport.php
new file mode 100644
index 0000000..752dd4e
--- /dev/null
+++ b/migrations/Version20240118141652AddTransactionReport.php
@@ -0,0 +1,33 @@
+addSql('CREATE TABLE transaction_report (transaction_id BINARY(16) NOT NULL COMMENT \'(DC2Type:uuid)\', currency_iso VARCHAR(3) NOT NULL, total_price NUMERIC(20, 2) NOT NULL, PRIMARY KEY(transaction_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
+ $this->addSql('ALTER TABLE transaction_report ADD CONSTRAINT FK_B25205C42FC0CB0F FOREIGN KEY (transaction_id) REFERENCES `transaction` (id)');
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql('ALTER TABLE transaction_report DROP FOREIGN KEY FK_B25205C42FC0CB0F');
+ $this->addSql('DROP TABLE transaction_report');
+ }
+}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 1a02e37..b9c4b7d 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -26,7 +26,8 @@
src/Entity
- src/Command
+ src/Command/SetupUrlCommand.php
+ src/Command/ReportTurnoverCommand.php
diff --git a/src/Braintree/Payment/BraintreePaymentService.php b/src/Braintree/Payment/BraintreePaymentService.php
index 0528e9f..ff65cb1 100644
--- a/src/Braintree/Payment/BraintreePaymentService.php
+++ b/src/Braintree/Payment/BraintreePaymentService.php
@@ -5,11 +5,13 @@
use Braintree\Exception\NotFound;
use Braintree\Gateway;
use Braintree\Transaction;
+use Doctrine\ORM\EntityManagerInterface;
use Shopware\App\SDK\Context\Payment\PaymentPayAction;
use Shopware\App\SDK\Shop\ShopInterface;
use Swag\Braintree\Braintree\Exception\BraintreePaymentException;
use Swag\Braintree\Braintree\Util\SalesChannelConfigService;
-use Swag\Braintree\Entity\ShopEntity;
+use Swag\Braintree\Entity\TransactionEntity;
+use Swag\Braintree\Entity\TransactionReportEntity;
use Swag\Braintree\Repository\TransactionRepository;
class BraintreePaymentService
@@ -24,6 +26,7 @@ public function __construct(
private readonly OrderInformationService $orderInformationService,
private readonly SalesChannelConfigService $salesChannelConfigService,
private readonly TransactionRepository $transactionRepository,
+ private readonly EntityManagerInterface $em,
) {
}
@@ -53,9 +56,7 @@ public function handleTransaction(PaymentPayAction $payment): Transaction
'discountAmount' => $this->orderInformationService->extractDiscountAmount($payment),
'lineItems' => $this->orderInformationService->extractLineItems($payment),
'shipping' => $shipping['address'],
- 'options' => [
- 'submitForSettlement' => true,
- ],
+ 'options' => ['submitForSettlement' => true],
'paymentMethodNonce' => $nonce,
'purchaseOrderNumber' => $payment->order->getOrderNumber(),
'taxAmount' => $this->orderInformationService->extractTaxAmount($payment),
@@ -134,16 +135,21 @@ public function getTransactionDetails(ShopInterface $shop, array $transactions):
return $braintreeTransaction;
}
- private function saveTransaction(PaymentPayAction $payment, Transaction $braintreeResponse): void
+ private function saveTransaction(PaymentPayAction $payment, Transaction $braintreeTransaction): void
{
- /** @var ShopEntity $shop */
- $shop = $payment->shop;
-
- $this->transactionRepository->upsert([
- [
- 'orderTransactionId' => $payment->orderTransaction->getId(),
- 'braintreeTransactionId' => $braintreeResponse->id,
- ],
- ], $shop);
+ $transaction = (new TransactionEntity())
+ ->setBraintreeTransactionId($braintreeTransaction->id)
+ ->setOrderTransactionId($payment->orderTransaction->getId())
+ ->setShop($payment->shop);
+
+ $report = (new TransactionReportEntity())
+ ->setCurrencyIso($braintreeTransaction->currencyIsoCode)
+ ->setTotalPrice((string) $braintreeTransaction->amount)
+ ->setTransaction($transaction);
+
+ $this->em->persist($transaction);
+ $this->em->persist($report);
+
+ $this->em->flush();
}
}
diff --git a/src/Braintree/Util/ReportClientFactory.php b/src/Braintree/Util/ReportClientFactory.php
new file mode 100644
index 0000000..db23023
--- /dev/null
+++ b/src/Braintree/Util/ReportClientFactory.php
@@ -0,0 +1,16 @@
+ $config
+ */
+ public static function createClient(array $config = []): Client
+ {
+ return new Client($config);
+ }
+}
diff --git a/src/Braintree/Util/ReportService.php b/src/Braintree/Util/ReportService.php
new file mode 100644
index 0000000..979f949
--- /dev/null
+++ b/src/Braintree/Util/ReportService.php
@@ -0,0 +1,81 @@
+ List of currencies that could not be reported
+ */
+ public function sendTurnoverReports(): array
+ {
+ $transactions = $this->transactionReportRepository->findAll();
+
+ $reports = [];
+ foreach ($transactions as $transaction) {
+ $reports[$transaction->getCurrencyIso()] ??= 0;
+ $reports[$transaction->getCurrencyIso()] += (float) $transaction->getTotalPrice();
+ }
+
+ $requests = [];
+ foreach ($reports as $currency => $turnover) {
+ $body = [
+ 'identifier' => $this->apiIdentifier ?? '',
+ 'reportDate' => (new \DateTime())->format(\DateTimeInterface::ATOM),
+ 'reportDataKeys' => ['turnover' => $turnover],
+ 'currency' => $currency,
+ ];
+
+ $requests[$currency] = $this->client->postAsync(
+ '/shopwarepartners/reports/technology',
+ [RequestOptions::JSON => $body],
+ );
+ }
+
+ $rejectedCurrencies = [];
+ /** @var array{state: string, reason: ClientException} $response */
+ foreach (Utils::settle($requests)->wait() as $currency => $response) {
+ if ($response['state'] !== Promise::REJECTED) {
+ continue;
+ }
+
+ // @TODO - Implement logging
+ // $this->logger->warning(\sprintf(
+ // 'Failed to report turnover for "%s": %s',
+ // $currency,
+ // $response['reason']->getMessage()
+ // ));
+
+ $rejectedCurrencies[] = $currency;
+ }
+
+ foreach ($transactions as $transaction) {
+ // transaction has a rejected currency and shouldn't be deleted
+ if (\in_array($transaction->getCurrencyIso(), $rejectedCurrencies, true)) {
+ continue;
+ }
+
+ $this->em->remove($transaction);
+ }
+
+ $this->em->flush();
+
+ return $rejectedCurrencies;
+ }
+}
diff --git a/src/Command/ReportTurnoverCommand.php b/src/Command/ReportTurnoverCommand.php
new file mode 100644
index 0000000..d463bbc
--- /dev/null
+++ b/src/Command/ReportTurnoverCommand.php
@@ -0,0 +1,43 @@
+reportService->sendTurnoverReports();
+
+ if (\count($rejectedCurrencies) > 0) {
+ $io->warning(\sprintf(
+ 'The following currencies could not be reported: %s',
+ \implode(', ', $rejectedCurrencies)
+ ));
+
+ return Command::FAILURE;
+ }
+
+ return Command::SUCCESS;
+ }
+
+ protected function configure(): void
+ {
+ $this->setDescription('Report the turnover of a given time period');
+ }
+}
diff --git a/src/Entity/TransactionEntity.php b/src/Entity/TransactionEntity.php
index f14ad43..46fe286 100644
--- a/src/Entity/TransactionEntity.php
+++ b/src/Entity/TransactionEntity.php
@@ -27,6 +27,9 @@ class TransactionEntity implements EntityInterface
#[ORM\Column(type: Types::STRING, nullable: false)]
private string $orderTransactionId;
+ #[ORM\OneToOne(targetEntity: TransactionReportEntity::class, mappedBy: 'transaction', cascade: ['persist', 'remove'])]
+ private ?TransactionReportEntity $transactionReport = null;
+
public function getBraintreeTransactionId(): string
{
return $this->braintreeTransactionId;
@@ -50,4 +53,16 @@ public function setOrderTransactionId(string $orderTransactionId): self
return $this;
}
+
+ public function getTransactionReport(): ?TransactionReportEntity
+ {
+ return $this->transactionReport;
+ }
+
+ public function setTransactionReport(?TransactionReportEntity $transactionReport): self
+ {
+ $this->transactionReport = $transactionReport;
+
+ return $this;
+ }
}
diff --git a/src/Entity/TransactionReportEntity.php b/src/Entity/TransactionReportEntity.php
new file mode 100644
index 0000000..315a75f
--- /dev/null
+++ b/src/Entity/TransactionReportEntity.php
@@ -0,0 +1,58 @@
+transaction;
+ }
+
+ public function setTransaction(TransactionEntity $transaction): self
+ {
+ $this->transaction = $transaction;
+
+ return $this;
+ }
+
+ public function getCurrencyIso(): string
+ {
+ return $this->currencyIso;
+ }
+
+ public function setCurrencyIso(string $currencyIso): self
+ {
+ $this->currencyIso = $currencyIso;
+
+ return $this;
+ }
+
+ public function getTotalPrice(): string
+ {
+ return $this->totalPrice;
+ }
+
+ public function setTotalPrice(string $totalPrice): self
+ {
+ $this->totalPrice = $totalPrice;
+
+ return $this;
+ }
+}
diff --git a/src/Repository/TransactionReportRepository.php b/src/Repository/TransactionReportRepository.php
new file mode 100644
index 0000000..afe8401
--- /dev/null
+++ b/src/Repository/TransactionReportRepository.php
@@ -0,0 +1,22 @@
+
+ */
+class TransactionReportRepository extends ServiceEntityRepository
+{
+ public function __construct(ManagerRegistry $registry)
+ {
+ parent::__construct($registry, TransactionReportEntity::class);
+ }
+}
diff --git a/tests/unit/Braintree/Payment/BraintreePaymentServiceTest.php b/tests/unit/Braintree/Payment/BraintreePaymentServiceTest.php
index c02462b..05331cd 100644
--- a/tests/unit/Braintree/Payment/BraintreePaymentServiceTest.php
+++ b/tests/unit/Braintree/Payment/BraintreePaymentServiceTest.php
@@ -9,6 +9,7 @@
use Braintree\Result;
use Braintree\Transaction;
use Braintree\TransactionGateway;
+use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@@ -20,6 +21,7 @@
use Swag\Braintree\Braintree\Util\SalesChannelConfigService;
use Swag\Braintree\Entity\ShopEntity;
use Swag\Braintree\Entity\TransactionEntity;
+use Swag\Braintree\Entity\TransactionReportEntity;
use Swag\Braintree\Repository\TransactionRepository;
use Swag\Braintree\Tests\Contract\PaymentPayActionHelperTrait;
use Swag\Braintree\Tests\IdsCollection;
@@ -45,6 +47,8 @@ class BraintreePaymentServiceTest extends TestCase
private MockObject&TransactionRepository $transactionRepository;
+ private MockObject&EntityManagerInterface $entityManager;
+
protected function setUp(): void
{
$this->paymentMethodNonceGateway = $this->createMock(PaymentMethodNonceGateway::class);
@@ -60,6 +64,8 @@ protected function setUp(): void
$this->transactionRepository = $this->createMock(TransactionRepository::class);
+ $this->entityManager = $this->createMock(EntityManagerInterface::class);
+
$this->orderIds = new IdsCollection();
$this->orderInformationService = new OrderInformationService(new TaxService());
$this->paymentService = new BraintreePaymentService(
@@ -67,6 +73,7 @@ protected function setUp(): void
$this->orderInformationService,
$salesChannelConfigService,
$this->transactionRepository,
+ $this->entityManager,
);
$this->shop = new ShopEntity('this-is-shop-id', '', 'this-is-shop-secret');
}
@@ -90,6 +97,8 @@ public function testHandleTransaction(): void
$resultSuccess = new Result\Successful([
'transaction' => Transaction::factory([
'id' => 'this-is-transaction-id',
+ 'currencyIsoCode' => 'EUR',
+ 'amount' => 200,
]),
], ['transaction']);
@@ -117,13 +126,29 @@ public function testHandleTransaction(): void
BraintreePaymentService::BRAINTREE_DEVICE_DATA => 'this-is-device-data',
]);
- $this->transactionRepository
+ $emMatcher = static::exactly(2);
+ $this->entityManager
+ ->expects($emMatcher)
+ ->method('persist')
+ ->willReturnCallback(function (object $entity) use (&$emMatcher): void {
+ switch ($emMatcher->numberOfInvocations()) {
+ case 1:
+ /** @var TransactionEntity $entity */
+ static::assertInstanceOf(TransactionEntity::class, $entity);
+ static::assertEquals('this-is-transaction-id', $entity->getBraintreeTransactionId());
+ break;
+ case 2:
+ /** @var TransactionReportEntity $entity */
+ static::assertInstanceOf(TransactionReportEntity::class, $entity);
+ static::assertEquals('EUR', $entity->getCurrencyIso());
+ static::assertEquals(200, $entity->getTotalPrice());
+ break;
+ }
+ });
+
+ $this->entityManager
->expects(static::once())
- ->method('upsert')
- ->with([[
- 'orderTransactionId' => $this->orderIds->get('order-transaction-id'),
- 'braintreeTransactionId' => 'this-is-transaction-id',
- ]], $this->shop);
+ ->method('flush');
$transaction = $this->paymentService->handleTransaction($paymentPayAction);
@@ -281,6 +306,7 @@ public function testHandleTransactionWithoutMerchantIdThrowsException(): void
$this->orderInformationService,
$salesChannelConfigService,
$this->transactionRepository,
+ $this->entityManager,
);
$this->paymentMethodNonceGateway
diff --git a/tests/unit/Braintree/Util/ReportClientFactoryTest.php b/tests/unit/Braintree/Util/ReportClientFactoryTest.php
new file mode 100644
index 0000000..ad09833
--- /dev/null
+++ b/tests/unit/Braintree/Util/ReportClientFactoryTest.php
@@ -0,0 +1,39 @@
+append(new Response());
+ $clientHandlerStack = HandlerStack::create($clientHandler);
+ $clientHandlerStack->push(Middleware::history($clientHistory));
+
+ $client = ReportClientFactory::createClient(['base_uri' => 'https://example.com', 'handler' => $clientHandlerStack]);
+ $client->get('/foo/bar');
+
+ static::assertCount(1, $clientHistory);
+
+ static::assertArrayHasKey('request', $clientHistory[0]);
+ static::assertInstanceOf(Request::class, $clientHistory[0]['request']);
+
+ $uri = $clientHistory[0]['request']->getUri();
+
+ static::assertInstanceOf(UriInterface::class, $uri);
+ static::assertSame('https://example.com/foo/bar', (string) $uri);
+ }
+}
diff --git a/tests/unit/Braintree/Util/ReportServiceTest.php b/tests/unit/Braintree/Util/ReportServiceTest.php
new file mode 100644
index 0000000..66a3a06
--- /dev/null
+++ b/tests/unit/Braintree/Util/ReportServiceTest.php
@@ -0,0 +1,312 @@
+
+ */
+ private array $clientHistory;
+
+ private MockHandler $clientHandler;
+
+ protected function setUp(): void
+ {
+ $this->transactionReportRepository = $this->createMock(TransactionReportRepository::class);
+ $this->entityManager = $this->createMock(EntityManagerInterface::class);
+
+ $this->clientHistory = [];
+ $this->clientHandler = new MockHandler();
+ $clientHandlerStack = HandlerStack::create($this->clientHandler);
+ $clientHandlerStack->push(Middleware::history($this->clientHistory));
+
+ $this->service = new ReportService(
+ $this->entityManager,
+ $this->transactionReportRepository,
+ 'test-id',
+ new Client(['handler' => $clientHandlerStack]),
+ );
+ }
+
+ public function testSendTurnoverReports(): void
+ {
+ $this->clientHandler->append(new Response(), new Response(), new Response());
+
+ $reports = [
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('10.52'),
+
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('9.48'),
+
+ (new TransactionReportEntity())
+ ->setCurrencyIso('GBP')
+ ->setTotalPrice('100.00'),
+ ];
+
+ $this->transactionReportRepository
+ ->expects(static::once())
+ ->method('findAll')
+ ->willReturn($reports);
+
+ $this->entityManager
+ ->expects(static::once())
+ ->method('flush');
+
+ $this->entityManager
+ ->expects(static::exactly(3))
+ ->method('remove');
+
+ $this->service->sendTurnoverReports();
+
+ static::assertEquals([[
+ 'reportDataKeys' => ['turnover' => 20],
+ 'currency' => 'EUR',
+ ], [
+ 'reportDataKeys' => ['turnover' => 100],
+ 'currency' => 'GBP',
+ ]], $this->extractTurnoverReports($this->clientHistory));
+ }
+
+ public function testSendTurnoverReportsWithRejectedReport(): void
+ {
+ $this->clientHandler->append(new Response(400), new Response());
+
+ $successfulReport = (new TransactionReportEntity())
+ ->setCurrencyIso('GBP')
+ ->setTotalPrice('100.00');
+
+ $reports = [
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('10.52'),
+
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('9.48'),
+
+ $successfulReport,
+ ];
+
+ $this->transactionReportRepository
+ ->expects(static::once())
+ ->method('findAll')
+ ->willReturn($reports);
+
+ $this->entityManager
+ ->expects(static::once())
+ ->method('flush');
+
+ // will only remove the successful reported transaction
+ $this->entityManager
+ ->expects(static::once())
+ ->method('remove')
+ ->with($successfulReport);
+
+ $rejectedCurrencies = $this->service->sendTurnoverReports();
+
+ static::assertEquals(['EUR'], $rejectedCurrencies);
+
+ static::assertEquals([[
+ 'reportDataKeys' => ['turnover' => 20],
+ 'currency' => 'EUR',
+ ], [
+ 'reportDataKeys' => ['turnover' => 100],
+ 'currency' => 'GBP',
+ ]], $this->extractTurnoverReports($this->clientHistory));
+ }
+
+ public function testMultipleRejectedCurrencies(): void
+ {
+ $this->clientHandler->append(new Response(400), new Response(), new Response(400));
+
+ $successfulReport = (new TransactionReportEntity())
+ ->setCurrencyIso('CHF')
+ ->setTotalPrice('9.48');
+
+ $reports = [
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('10.52'),
+
+ $successfulReport,
+
+ (new TransactionReportEntity())
+ ->setCurrencyIso('GBP')
+ ->setTotalPrice('100.00'),
+ ];
+
+ $this->transactionReportRepository
+ ->expects(static::once())
+ ->method('findAll')
+ ->willReturn($reports);
+
+ $this->entityManager
+ ->expects(static::once())
+ ->method('flush');
+
+ // will only remove the successful reported transaction
+ $this->entityManager
+ ->expects(static::once())
+ ->method('remove')
+ ->with($successfulReport);
+
+ $rejectedCurrencies = $this->service->sendTurnoverReports();
+
+ static::assertEquals(['EUR', 'GBP'], $rejectedCurrencies);
+
+ static::assertEquals([[
+ 'reportDataKeys' => ['turnover' => 10.52],
+ 'currency' => 'EUR',
+ ], [
+ 'reportDataKeys' => ['turnover' => 9.48],
+ 'currency' => 'CHF',
+ ], [
+ 'reportDataKeys' => ['turnover' => 100],
+ 'currency' => 'GBP',
+ ]], $this->extractTurnoverReports($this->clientHistory));
+ }
+
+ public function testTransactionFloatCasting(): void
+ {
+ $this->clientHandler->append(new Response());
+
+ $reports = [
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('10.52s'),
+ ];
+
+ $this->transactionReportRepository
+ ->expects(static::once())
+ ->method('findAll')
+ ->willReturn($reports);
+
+ $this->service->sendTurnoverReports();
+
+ static::assertNotNull($this->clientHandler->getLastRequest());
+
+ $requestBody = $this->clientHandler->getLastRequest()->getBody()->getContents();
+
+ static::assertJson($requestBody);
+
+ $requestBodyArray = \json_decode($requestBody, true);
+
+ static::assertIsArray($requestBodyArray);
+
+ static::assertArrayHasKey('reportDataKeys', $requestBodyArray);
+ static::assertIsArray($requestBodyArray['reportDataKeys']);
+
+ static::assertArrayHasKey('turnover', $requestBodyArray['reportDataKeys']);
+ static::assertIsFloat($requestBodyArray['reportDataKeys']['turnover']);
+ }
+
+ public function testReportDateIsSent(): void
+ {
+ $this->clientHandler->append(new Response());
+
+ $reports = [
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('10.52s'),
+ ];
+
+ $this->transactionReportRepository
+ ->expects(static::once())
+ ->method('findAll')
+ ->willReturn($reports);
+
+ $this->service->sendTurnoverReports();
+
+ static::assertNotNull($this->clientHandler->getLastRequest());
+
+ $requestBody = $this->clientHandler->getLastRequest()->getBody()->getContents();
+
+ static::assertJson($requestBody);
+
+ $requestBodyArray = \json_decode($requestBody, true);
+
+ static::assertArrayHasKey('reportDate', $requestBodyArray);
+ static::assertIsString($requestBodyArray['reportDate']);
+
+ $reportDate = \DateTime::createFromFormat(\DateTimeInterface::ATOM, $requestBodyArray['reportDate']);
+
+ static::assertInstanceOf(\DateTimeInterface::class, $reportDate);
+ }
+
+ public function testApiIdentifierIsSent(): void
+ {
+ $this->clientHandler->append(new Response());
+
+ $reports = [
+ (new TransactionReportEntity())
+ ->setCurrencyIso('EUR')
+ ->setTotalPrice('10.52s'),
+ ];
+
+ $this->transactionReportRepository
+ ->expects(static::once())
+ ->method('findAll')
+ ->willReturn($reports);
+
+ $this->service->sendTurnoverReports();
+
+ static::assertNotNull($this->clientHandler->getLastRequest());
+
+ $requestBody = $this->clientHandler->getLastRequest()->getBody()->getContents();
+
+ static::assertJson($requestBody);
+
+ $requestBodyArray = \json_decode($requestBody, true);
+
+ static::assertArrayHasKey('identifier', $requestBodyArray);
+ static::assertSame('test-id', $requestBodyArray['identifier']);
+ }
+
+ /**
+ * Extracts all turnover reports, successful and failed ones
+ *
+ * @param array $history
+ *
+ * @return array>
+ */
+ private function extractTurnoverReports(array $history): array
+ {
+ return \array_map(
+ function (array $entry) {
+ $body = \json_decode($entry['request']->getBody()->getContents(), true);
+ static::assertIsArray($body);
+
+ unset($body['identifier']);
+ unset($body['reportDate']);
+
+ return $body;
+ },
+ $history,
+ );
+ }
+}
diff --git a/tests/unit/Repository/TransactionReportRepositoryTest.php b/tests/unit/Repository/TransactionReportRepositoryTest.php
new file mode 100644
index 0000000..a6dcbfb
--- /dev/null
+++ b/tests/unit/Repository/TransactionReportRepositoryTest.php
@@ -0,0 +1,47 @@
+entityManager = $this->createMock(EntityManagerInterface::class);
+ $this->entityManager
+ ->method('getClassMetadata')
+ ->with(TransactionReportEntity::class)
+ ->willReturn(new ClassMetadata(TransactionReportEntity::class));
+
+ $this->registry = $this->createMock(ManagerRegistry::class);
+ $this->registry
+ ->method('getManagerForClass')
+ ->with(TransactionReportEntity::class)
+ ->willReturn($this->entityManager);
+
+ $this->repository = new TransactionReportRepository($this->registry);
+ }
+
+ public function testConstruct(): void
+ {
+ $this->entityManager->expects(static::once())->method('getClassMetadata');
+ $this->registry->expects(static::once())->method('getManagerForClass');
+
+ static::assertSame(TransactionReportEntity::class, $this->repository->getClassName());
+ }
+}