From b6492e28698c2783d1f4584f87c1ec9f00b4ec62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20L=C3=B8vgaard?= Date: Mon, 15 Jun 2026 11:40:44 +0200 Subject: [PATCH 1/4] Upgrade plugin to support Sylius 2 Follows the Setono Sylius v1 -> v2 plugin upgrade playbook, using the SyliusPluginSkeleton as reference. - Require PHP >=8.2, Symfony ^6.4 || ^7.4 and Sylius ^2.0 - Move configuration to repo-root config/ and translations/; convert service definitions from XML to the PHP DSL (config/services.php) - Register the admin grid via the bundle extension prepend() instead of a grid YAML file; override getPath()/getConfigFilesPath() so Doctrine mapping, validation and translations resolve from the new layout - Default the command bus to sylius.command_bus - Replace Psalm/PHPSpec/code-quality-pack with setono/sylius-plugin (PHPStan max + PHPUnit); add ecs.php, rector.php, infection.json5 and composer-dependency-analyser.php - Convert the PHPSpec specs to PHPUnit under tests/Unit and add a functional admin-routing test - Rebuild the test application for Sylius 2.2 - Switch CI to the setono/sylius-plugin composite actions See UPGRADE.md for consumer-facing changes. --- .gitattributes | 27 +- .github/workflows/build.yaml | 281 +++--------------- .gitignore | 14 +- README.md | 60 ++-- UPGRADE.md | 48 +++ composer-dependency-analyser.php | 28 ++ composer-require-checker.json | 29 -- composer.json | 69 ++--- .../doctrine/model/Program.orm.xml | 0 config/routes.yaml | 3 + .../routing => config/routes}/admin.yaml | 9 +- config/services.php | 103 +++++++ .../config => config}/validation/Program.xml | 0 ecs.php | 17 +- infection.json5 | 15 + phpspec.yml.dist | 4 - phpstan.neon | 40 +++ psalm.xml | 31 -- rector.php | 25 ++ spec/Calculator/OrderTotalCalculatorSpec.php | 45 --- spec/Client/ClientSpec.php | 51 ---- spec/EventListener/NotifySubscriberSpec.php | 168 ----------- .../EventListener/SetCookieSubscriberSpec.php | 91 ------ spec/UrlProvider/NotifyUrlProviderSpec.php | 48 --- src/Client/Client.php | 18 +- src/Context/ProgramContext.php | 10 +- src/CookieHandler/CookieHandler.php | 10 +- src/DependencyInjection/Configuration.php | 5 +- .../SetonoSyliusPartnerAdsExtension.php | 70 ++++- src/EventListener/NotifySubscriber.php | 30 +- src/EventListener/SetCookieSubscriber.php | 10 +- src/Exception/InterfaceNotFoundException.php | 6 +- .../MissingVariableInUrlException.php | 9 +- src/Exception/RequestFailedException.php | 12 +- src/Message/Command/Notify.php | 19 +- src/Message/Handler/NotifyHandler.php | 7 +- src/Resources/config/app/config.yaml | 2 - ...tono_sylius_partner_ads_admin_program.yaml | 23 -- src/Resources/config/routing.yaml | 3 - src/Resources/config/services.xml | 16 - src/Resources/config/services/calculator.xml | 7 - src/Resources/config/services/client.xml | 11 - src/Resources/config/services/context.xml | 10 - .../config/services/cookie_handler.xml | 10 - .../config/services/event_listener.xml | 20 -- src/Resources/config/services/form.xml | 16 - src/Resources/config/services/http_client.xml | 8 - src/Resources/config/services/menu.xml | 9 - src/Resources/config/services/message.xml | 7 - .../config/services/message/handler.xml | 10 - .../config/services/url_provider.xml | 9 - src/SetonoSyliusPartnerAdsPlugin.php | 19 ++ src/UrlProvider/NotifyUrlProvider.php | 11 +- tests/Application/.env | 30 +- tests/Application/.env.test | 2 +- tests/Application/.gitignore | 2 + tests/Application/Client/Client.php | 19 +- tests/Application/Kernel.php | 114 +------ tests/Application/bin/console | 2 +- .../config/api_platform/.gitignore | 0 tests/Application/config/bundles.php | 24 +- tests/Application/config/jwt/private.pem | 54 ---- tests/Application/config/jwt/public.pem | 14 - .../Application/config/packages/_sylius.yaml | 6 +- .../config/packages/api_platform.yaml | 9 - .../config/packages/dev/framework.yaml | 2 - .../config/packages/dev/jms_serializer.yaml | 12 - .../config/packages/dev/monolog.yaml | 9 - .../config/packages/dev/routing.yaml | 3 - .../config/packages/dev/swiftmailer.yaml | 2 - .../config/packages/dev/web_profiler.yaml | 3 - .../Application/config/packages/doctrine.yaml | 33 ++ .../config/packages/doctrine_migrations.yaml | 2 + .../Application/config/packages/fos_rest.yaml | 11 - .../config/packages/framework.yaml | 26 +- .../config/packages/http_discovery.yaml | 10 + .../config/packages/jms_serializer.yaml | 4 - .../packages/lexik_jwt_authentication.yaml | 4 - tests/Application/config/packages/mailer.yaml | 3 + .../config/packages/messenger.yaml | 4 - .../Application/config/packages/monolog.yaml | 30 ++ .../config/packages/prod/doctrine.yaml | 31 -- .../config/packages/prod/jms_serializer.yaml | 10 - .../config/packages/prod/monolog.yaml | 10 - .../Application/config/packages/routing.yaml | 7 +- .../Application/config/packages/security.yaml | 93 ++---- .../packages/setono_sylius_partner_ads.yaml | 5 +- .../config/packages/staging/monolog.yaml | 10 - .../config/packages/staging/swiftmailer.yaml | 2 - .../config/packages/swiftmailer.yaml | 2 - .../sylius_state_machine_abstraction.yaml | 6 + .../config/packages/sylius_theme.yaml | 4 + .../config/packages/test/framework.yaml | 4 - .../config/packages/test/monolog.yaml | 6 - .../config/packages/test/security.yaml | 3 - .../config/packages/test/swiftmailer.yaml | 6 - .../config/packages/test/sylius_theme.yaml | 3 - .../config/packages/test/sylius_uploader.yaml | 3 - .../config/packages/test/web_profiler.yaml | 6 - .../config/packages/test_cached/doctrine.yaml | 16 - .../config/packages/test_cached/fos_rest.yaml | 3 - .../packages/test_cached/framework.yaml | 4 - .../config/packages/test_cached/monolog.yaml | 6 - .../config/packages/test_cached/security.yaml | 3 - .../packages/test_cached/swiftmailer.yaml | 6 - .../packages/test_cached/sylius_channel.yaml | 2 - .../packages/test_cached/sylius_theme.yaml | 3 - .../packages/test_cached/sylius_uploader.yaml | 3 - .../config/packages/test_cached/twig.yaml | 2 - .../config/packages/validator.yaml | 2 +- .../config/packages/web_profiler.yaml | 12 + .../Application/config/packages/workflow.yaml | 2 + tests/Application/config/routes.yaml | 2 - tests/Application/config/routes/dev/twig.yaml | 3 - .../config/routes/dev/web_profiler.yaml | 7 - .../routes/setono_sylius_partner_ads.yaml | 2 + .../config/routes/sylius_admin.yaml | 2 +- .../config/routes/sylius_admin_api.yaml | 3 - .../Application/config/routes/sylius_api.yaml | 3 - .../config/routes/sylius_shop.yaml | 16 +- .../config/routes/web_profiler.yaml | 8 + tests/Application/config/services.yaml | 10 +- tests/Application/package.json | 38 +-- tests/Application/public/callback.php | 1 + tests/Application/public/index.php | 4 +- .../Application/public/media/image/.gitignore | 0 tests/Application/webpack.config.js | 47 +-- tests/Functional/AdminRoutingTest.php | 46 +++ tests/PHPStan/console_application.php | 13 + tests/PHPStan/object_manager.php | 13 + .../Calculator/OrderTotalCalculatorTest.php | 36 +++ tests/Unit/Client/ClientTest.php | 52 ++++ .../CookieHandler/CookieHandlerTest.php | 51 ++-- .../Compiler/RegisterCommandBusPassTest.php | 9 +- .../Compiler/RegisterHttpClientPassTest.php | 15 +- .../DependencyInjection/ConfigurationTest.php | 9 +- .../SetonoSyliusPartnerAdsExtensionTest.php | 9 +- .../EventListener/NotifySubscriberTest.php | 108 +++++++ .../EventListener/SetCookieSubscriberTest.php | 92 ++++++ .../UrlProvider/NotifyUrlProviderTest.php | 41 +++ .../messages.da.yaml | 0 .../messages.en.yaml | 0 .../validators.da.yaml | 0 .../validators.en.yaml | 0 144 files changed, 1209 insertions(+), 1743 deletions(-) create mode 100644 UPGRADE.md create mode 100644 composer-dependency-analyser.php delete mode 100644 composer-require-checker.json rename {src/Resources/config => config}/doctrine/model/Program.orm.xml (100%) create mode 100644 config/routes.yaml rename {src/Resources/config/routing => config/routes}/admin.yaml (55%) create mode 100644 config/services.php rename {src/Resources/config => config}/validation/Program.xml (100%) create mode 100644 infection.json5 delete mode 100644 phpspec.yml.dist create mode 100644 phpstan.neon delete mode 100644 psalm.xml create mode 100644 rector.php delete mode 100644 spec/Calculator/OrderTotalCalculatorSpec.php delete mode 100644 spec/Client/ClientSpec.php delete mode 100644 spec/EventListener/NotifySubscriberSpec.php delete mode 100644 spec/EventListener/SetCookieSubscriberSpec.php delete mode 100644 spec/UrlProvider/NotifyUrlProviderSpec.php delete mode 100644 src/Resources/config/app/config.yaml delete mode 100644 src/Resources/config/grids/setono_sylius_partner_ads_admin_program.yaml delete mode 100644 src/Resources/config/routing.yaml delete mode 100644 src/Resources/config/services.xml delete mode 100644 src/Resources/config/services/calculator.xml delete mode 100644 src/Resources/config/services/client.xml delete mode 100644 src/Resources/config/services/context.xml delete mode 100644 src/Resources/config/services/cookie_handler.xml delete mode 100644 src/Resources/config/services/event_listener.xml delete mode 100644 src/Resources/config/services/form.xml delete mode 100644 src/Resources/config/services/http_client.xml delete mode 100644 src/Resources/config/services/menu.xml delete mode 100644 src/Resources/config/services/message.xml delete mode 100644 src/Resources/config/services/message/handler.xml delete mode 100644 src/Resources/config/services/url_provider.xml delete mode 100644 tests/Application/config/api_platform/.gitignore delete mode 100644 tests/Application/config/jwt/private.pem delete mode 100644 tests/Application/config/jwt/public.pem delete mode 100644 tests/Application/config/packages/api_platform.yaml delete mode 100644 tests/Application/config/packages/dev/framework.yaml delete mode 100644 tests/Application/config/packages/dev/jms_serializer.yaml delete mode 100644 tests/Application/config/packages/dev/monolog.yaml delete mode 100644 tests/Application/config/packages/dev/routing.yaml delete mode 100644 tests/Application/config/packages/dev/swiftmailer.yaml delete mode 100644 tests/Application/config/packages/dev/web_profiler.yaml delete mode 100644 tests/Application/config/packages/fos_rest.yaml create mode 100644 tests/Application/config/packages/http_discovery.yaml delete mode 100644 tests/Application/config/packages/jms_serializer.yaml delete mode 100644 tests/Application/config/packages/lexik_jwt_authentication.yaml create mode 100644 tests/Application/config/packages/mailer.yaml delete mode 100644 tests/Application/config/packages/messenger.yaml create mode 100644 tests/Application/config/packages/monolog.yaml delete mode 100644 tests/Application/config/packages/prod/doctrine.yaml delete mode 100644 tests/Application/config/packages/prod/jms_serializer.yaml delete mode 100644 tests/Application/config/packages/prod/monolog.yaml delete mode 100644 tests/Application/config/packages/staging/monolog.yaml delete mode 100644 tests/Application/config/packages/staging/swiftmailer.yaml delete mode 100644 tests/Application/config/packages/swiftmailer.yaml create mode 100644 tests/Application/config/packages/sylius_state_machine_abstraction.yaml create mode 100644 tests/Application/config/packages/sylius_theme.yaml delete mode 100644 tests/Application/config/packages/test/framework.yaml delete mode 100644 tests/Application/config/packages/test/monolog.yaml delete mode 100644 tests/Application/config/packages/test/security.yaml delete mode 100644 tests/Application/config/packages/test/swiftmailer.yaml delete mode 100644 tests/Application/config/packages/test/sylius_theme.yaml delete mode 100644 tests/Application/config/packages/test/sylius_uploader.yaml delete mode 100644 tests/Application/config/packages/test/web_profiler.yaml delete mode 100644 tests/Application/config/packages/test_cached/doctrine.yaml delete mode 100644 tests/Application/config/packages/test_cached/fos_rest.yaml delete mode 100644 tests/Application/config/packages/test_cached/framework.yaml delete mode 100644 tests/Application/config/packages/test_cached/monolog.yaml delete mode 100644 tests/Application/config/packages/test_cached/security.yaml delete mode 100644 tests/Application/config/packages/test_cached/swiftmailer.yaml delete mode 100644 tests/Application/config/packages/test_cached/sylius_channel.yaml delete mode 100644 tests/Application/config/packages/test_cached/sylius_theme.yaml delete mode 100644 tests/Application/config/packages/test_cached/sylius_uploader.yaml delete mode 100644 tests/Application/config/packages/test_cached/twig.yaml create mode 100644 tests/Application/config/packages/web_profiler.yaml create mode 100644 tests/Application/config/packages/workflow.yaml delete mode 100644 tests/Application/config/routes.yaml delete mode 100644 tests/Application/config/routes/dev/twig.yaml delete mode 100644 tests/Application/config/routes/dev/web_profiler.yaml create mode 100644 tests/Application/config/routes/setono_sylius_partner_ads.yaml delete mode 100644 tests/Application/config/routes/sylius_admin_api.yaml delete mode 100644 tests/Application/config/routes/sylius_api.yaml create mode 100644 tests/Application/config/routes/web_profiler.yaml delete mode 100644 tests/Application/public/media/image/.gitignore create mode 100644 tests/Functional/AdminRoutingTest.php create mode 100644 tests/PHPStan/console_application.php create mode 100644 tests/PHPStan/object_manager.php create mode 100644 tests/Unit/Calculator/OrderTotalCalculatorTest.php create mode 100644 tests/Unit/Client/ClientTest.php rename tests/{ => Unit}/CookieHandler/CookieHandlerTest.php (67%) rename tests/{ => Unit}/DependencyInjection/Compiler/RegisterCommandBusPassTest.php (82%) rename tests/{ => Unit}/DependencyInjection/Compiler/RegisterHttpClientPassTest.php (90%) rename tests/{ => Unit}/DependencyInjection/ConfigurationTest.php (79%) rename tests/{ => Unit}/DependencyInjection/SetonoSyliusPartnerAdsExtensionTest.php (81%) create mode 100644 tests/Unit/EventListener/NotifySubscriberTest.php create mode 100644 tests/Unit/EventListener/SetCookieSubscriberTest.php create mode 100644 tests/Unit/UrlProvider/NotifyUrlProviderTest.php rename {src/Resources/translations => translations}/messages.da.yaml (100%) rename {src/Resources/translations => translations}/messages.en.yaml (100%) rename {src/Resources/translations => translations}/validators.da.yaml (100%) rename {src/Resources/translations => translations}/validators.en.yaml (100%) diff --git a/.gitattributes b/.gitattributes index d82c43d..3884ed6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,13 +1,14 @@ -/spec export-ignore -/tests export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore -/composer-require-checker.json export-ignore -/ecs.php export-ignore -/phpspec.yml.dist export-ignore -/phpunit.xml.dist export-ignore -/psalm.xml export-ignore -/README.md export-ignore -/.editorconfig export-ignore -/node_modules export-ignore -/.github export-ignore +/.editorconfig export-ignore +/.gitattributes export-ignore +/.github export-ignore +/.gitignore export-ignore +/composer-dependency-analyser.php export-ignore +/ecs.php export-ignore +/infection.json5 export-ignore +/node_modules export-ignore +/phpstan.neon export-ignore +/phpunit.xml.dist export-ignore +/README.md export-ignore +/rector.php export-ignore +/tests export-ignore +/UPGRADE.md export-ignore diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8a40d70..747e983 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,279 +1,94 @@ name: "build" + on: - push: - branches: - - "*.x" - paths-ignore: - - "**/*.md" - pull_request: - paths-ignore: - - "**/*.md" + push: ~ + pull_request: ~ workflow_dispatch: ~ -env: - APP_ENV: "test" - DATABASE_URL: "mysql://root:root@127.0.0.1/sylius?serverVersion=8.0" - PHP_EXTENSIONS: "intl, mbstring" - jobs: - coding-standards: - name: "Coding Standards (PHP${{ matrix.php-version }} | Deps: ${{ matrix.dependencies }})" - + backwards-compatibility: runs-on: "ubuntu-latest" - - strategy: - matrix: - php-version: - - "7.4" # Always use the lowest version of PHP since a higher version would create actual syntax errors in lower versions - - dependencies: - - "highest" - + if: "github.event_name == 'pull_request'" steps: - - name: "Checkout" - uses: "actions/checkout@v3" + - uses: "setono/sylius-plugin/backwards-compatibility@v2" - - name: "Setup PHP, with composer and extensions" - uses: "shivammathur/setup-php@v2" - with: - php-version: "${{ matrix.php-version }}" - extensions: "${{ env.PHP_EXTENSIONS }}" - coverage: "none" - - - name: "Install composer dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Validate composer" - run: "composer validate --strict" - - - name: "Check composer normalized" - run: "composer normalize --dry-run" - - - name: "Check style" - run: "composer check-style" - - - name: "Lint yaml files" - run: "(cd tests/Application && bin/console lint:yaml ../../src/Resources)" - - - name: "Lint twig files" - run: "(cd tests/Application && bin/console lint:twig ../../src/Resources)" + coding-standards: + runs-on: "ubuntu-latest" + steps: + - uses: "setono/sylius-plugin/coding-standards@v2" dependency-analysis: - name: "Dependency Analysis (PHP${{ matrix.php-version }} | Deps: ${{ matrix.dependencies }} | SF${{ matrix.symfony }})" - runs-on: "ubuntu-latest" - strategy: + fail-fast: false matrix: - php-version: - - "7.4" - - "8.0" - - "8.1" - - dependencies: - - "highest" - - symfony: - - "^5.4" - + php-version: ["8.2", "8.3", "8.4"] + dependencies: ["lowest", "highest"] + symfony: ["~6.4.0", "~7.4.0"] steps: - - name: "Checkout" - uses: "actions/checkout@v3" - - - name: "Setup PHP, with composer and extensions" - uses: "shivammathur/setup-php@v2" + - uses: "setono/sylius-plugin/dependency-analysis@v2" with: - coverage: "none" - extensions: "${{ env.PHP_EXTENSIONS }}" php-version: "${{ matrix.php-version }}" - tools: "composer-require-checker, composer-unused, flex" - - - name: "Install composer dependencies" - uses: "ramsey/composer-install@v2" - env: - SYMFONY_REQUIRE: "${{ matrix.symfony }}" - with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Run maglnet/composer-require-checker" - run: "composer-require-checker check --config-file=$(pwd)/composer-require-checker.json" - - - name: "Run composer-unused/composer-unused" - run: "composer-unused" + dependencies: "${{ matrix.dependencies }}" + symfony: "${{ matrix.symfony }}" static-code-analysis: - name: "Static Code Analysis (PHP${{ matrix.php-version }} | Deps: ${{ matrix.dependencies }} | SF${{ matrix.symfony }})" - runs-on: "ubuntu-latest" - strategy: + fail-fast: false matrix: - php-version: - - "7.4" - - "8.0" - - "8.1" - - dependencies: - - "highest" - - symfony: - - "^5.4" - + php-version: ["8.2", "8.3", "8.4"] + dependencies: ["lowest", "highest"] + symfony: ["~6.4.0", "~7.4.0"] steps: - - name: "Checkout" - uses: "actions/checkout@v3" - - - name: "Setup PHP, with composer and extensions" - uses: "shivammathur/setup-php@v2" + - uses: "setono/sylius-plugin/static-code-analysis@v2" with: - coverage: "none" - extensions: "${{ env.PHP_EXTENSIONS }}" php-version: "${{ matrix.php-version }}" - tools: "flex" - - - name: "Install composer dependencies" - uses: "ramsey/composer-install@v2" - env: - SYMFONY_REQUIRE: "${{ matrix.symfony }}" - with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Cache warmup" - run: "(cd tests/Application && bin/console cache:warmup)" - - - name: "Static analysis" - run: "vendor/bin/psalm --php-version=${{ matrix.php-version }}" + dependencies: "${{ matrix.dependencies }}" + symfony: "${{ matrix.symfony }}" unit-tests: - name: "Unit tests (PHP${{ matrix.php-version }} | Deps: ${{ matrix.dependencies }} | SF${{ matrix.symfony }})" - runs-on: "ubuntu-latest" - strategy: + fail-fast: false matrix: - php-version: - - "7.4" - - "8.0" - - "8.1" - - dependencies: - - "highest" - - symfony: - - "^5.4" - + php-version: ["8.2", "8.3", "8.4"] + dependencies: ["lowest", "highest"] + symfony: ["~6.4.0", "~7.4.0"] steps: - - name: "Checkout" - uses: "actions/checkout@v3" - - - name: "Setup PHP, with composer and extensions" - uses: "shivammathur/setup-php@v2" + - uses: "setono/sylius-plugin/unit-tests@v2" with: - coverage: "none" - extensions: "${{ env.PHP_EXTENSIONS }}" php-version: "${{ matrix.php-version }}" - tools: "flex" - - - name: "Install composer dependencies" - uses: "ramsey/composer-install@v2" - env: - SYMFONY_REQUIRE: "${{ matrix.symfony }}" - with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Run phpunit" - run: "composer phpunit" - - integration-tests: - name: "Integration tests (PHP${{ matrix.php-version }} | Deps: ${{ matrix.dependencies }} | SF${{ matrix.symfony }})" + dependencies: "${{ matrix.dependencies }}" + symfony: "${{ matrix.symfony }}" + testsuite: "unit" + functional-tests: runs-on: "ubuntu-latest" - strategy: + fail-fast: false matrix: - php-version: - - "7.4" - - "8.0" - - "8.1" - - dependencies: - - "highest" - - symfony: - - "^5.4" - + php-version: ["8.2", "8.3", "8.4"] + dependencies: ["highest"] + symfony: ["~6.4.0", "~7.4.0"] steps: - - name: "Start MySQL" - run: "sudo /etc/init.d/mysql start" - - - name: "Checkout" - uses: "actions/checkout@v3" - - - name: "Setup PHP, with composer and extensions" - uses: "shivammathur/setup-php@v2" + - uses: "setono/sylius-plugin/functional-tests@v2" with: - coverage: "none" - extensions: "${{ env.PHP_EXTENSIONS }}" php-version: "${{ matrix.php-version }}" - tools: "flex" + dependencies: "${{ matrix.dependencies }}" + symfony: "${{ matrix.symfony }}" + testsuite: "functional" - - name: "Install composer dependencies" - uses: "ramsey/composer-install@v2" - env: - SYMFONY_REQUIRE: "${{ matrix.symfony }}" + mutation-tests: + runs-on: "ubuntu-latest" + steps: + - uses: "setono/sylius-plugin/mutation-tests@v2" with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Lint container" - run: "(cd tests/Application && bin/console lint:container)" - - - name: "Create database" - run: "(cd tests/Application && bin/console doctrine:database:create -vvv)" - - - name: "Create database schema" - run: "(cd tests/Application && bin/console doctrine:schema:create -vvv)" - - - name: "Validate Doctrine mapping" - run: "(cd tests/Application && bin/console doctrine:schema:validate -vvv)" + stryker-dashboard-api-key: "${{ secrets.STRYKER_DASHBOARD_API_KEY }}" code-coverage: - name: "Code Coverage (PHP${{ matrix.php-version }} | Deps: ${{ matrix.dependencies }})" - runs-on: "ubuntu-latest" - - strategy: - matrix: - php-version: - - "8.1" - - dependencies: - - "highest" - steps: - - name: "Checkout" - uses: "actions/checkout@v3" - - - name: "Setup PHP, with composer and extensions" - uses: "shivammathur/setup-php@v2" + - uses: "setono/sylius-plugin/code-coverage@v2" with: - coverage: "pcov" - extensions: "${{ env.PHP_EXTENSIONS }}" - php-version: "${{ matrix.php-version }}" - - - name: "Set up problem matchers for phpunit/phpunit" - run: "echo \"::add-matcher::${{ runner.tool_cache }}/phpunit.json\"" - - - name: "Install composer dependencies" - uses: "ramsey/composer-install@v2" - with: - dependency-versions: "${{ matrix.dependencies }}" - - - name: "Collect code coverage with pcov and phpunit/phpunit" - run: "vendor/bin/phpunit --coverage-clover=.build/logs/clover.xml" - - - name: "Send code coverage report to Codecov.io" - env: - CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}" - run: "bash <(curl -s https://codecov.io/bash)" + codecov-token: "${{ secrets.CODECOV_TOKEN }}" diff --git a/.gitignore b/.gitignore index d96511f..2d97e86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,16 @@ +/.build/ /vendor/ /node_modules/ /composer.lock -/etc/build/* -!/etc/build/.gitignore - /tests/Application/yarn.lock +/tests/Application/config/reference.php + +/.phpunit.cache + +# Symfony CLI https://symfony.com/doc/current/setup/symfony_server.html#different-php-settings-per-project +/.php-version +/php.ini -/behat.yml -/phpspec.yml +/.claude/ /.phpunit.result.cache diff --git a/README.md b/README.md index 9d8ab5a..0d4c795 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,16 @@ This plugin will track sales made by Partner Ads affiliates. It works by saving the affiliate partner id when the visitor visits any page on your shop. Then when the user successfully completes an order it will send a HTTP request to Partner Ads telling them to credit the affiliate partner. +## Requirements + +| Package | Version | +|--------------|------------| +| PHP | >=8.2 | +| sylius/sylius| ^2.0 | +| Symfony | ^6.4 \|\| ^7.4 | + +> For Sylius 1.x use the [`1.x`](https://github.com/Setono/SyliusPartnerAdsPlugin/tree/1.x) version of this plugin. + ## Installation ### Step 1: Download the plugin @@ -18,70 +28,56 @@ composer require setono/sylius-partner-ads-plugin ### Step 2: Enable the plugin -Then, enable the plugin by adding it to the list of registered plugins/bundles -in the `config/bundles.php` file of your project before (!) `SyliusGridBundle`: +If it wasn't done automatically by Symfony Flex, enable the plugin by adding it to the list of registered plugins/bundles +in the `config/bundles.php` file of your project: ```php ['all' => true], - Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true], + // ... ]; ``` -### Step 3: Configure plugin - -```yaml -# config/packages/_sylius.yaml -imports: - # ... - - { resource: "@SetonoSyliusPartnerAdsPlugin/Resources/config/app/config.yaml" } - # ... -``` - -### Step 4: Import routing +### Step 3: Import routing ```yaml # config/routes/setono_sylius_partner_ads.yaml -setono_partner_ads_plugin: - resource: "@SetonoSyliusPartnerAdsPlugin/Resources/config/routing.yaml" +setono_sylius_partner_ads: + resource: "@SetonoSyliusPartnerAdsPlugin/config/routes.yaml" ``` -### Step 5: HTTP client -If you already use a PSR18 HTTP client you need to inject that service: +### Step 4: HTTP client +If you already use a PSR-18 HTTP client you need to inject that service: ```yaml setono_sylius_partner_ads: http_client: '@http_client_service_id' ``` -If not, you can just do composer the Buzz library and it will automatically register the Buzz client as the HTTP client: +If not, you can just install the Buzz library and it will automatically register the Buzz client as the HTTP client: ```bash -$ composer require kriswallsmith/buzz +composer require kriswallsmith/buzz ``` -### Step 6: Update your database schema +### Step 5: Update your database schema ```bash -$ php bin/console doctrine:migrations:diff -$ php bin/console doctrine:migrations:migrate +php bin/console doctrine:migrations:diff +php bin/console doctrine:migrations:migrate ``` -### Step 7: Setup program +### Step 6: Setup program Login to your Sylius app admin and go to the Partner Ads page and click "Create" to create a new program. Fill in the program id of your Partner Ads program, make sure "enable" is toggled on, and choose which channel the program should be applied to. Please notice you should only make one program for each channel, or else you will end up with undefined behaviour. -### Step 8 (optional, but recommended): Configure Async HTTP requests -This plugin will make a HTTP request to Partner Ads when a customer completes an order. This will make the 'Thank you' page load slower. To circumvent that you can use RabbitMQ with Symfony Messenger to send this HTTP request asynchronously. +### Step 7 (optional, but recommended): Configure Async HTTP requests +This plugin will make a HTTP request to Partner Ads when a customer completes an order. This will make the 'Thank you' page load slower. To circumvent that you can use a transport (e.g. RabbitMQ) with Symfony Messenger to send this HTTP request asynchronously. Follow the installation instructions here: [How to Use the Messenger](https://symfony.com/doc/current/messenger.html) and then [configure a transport](https://symfony.com/doc/current/messenger.html#transports). -Basically you should do: -```bash -$ composer req messenger symfony/serializer-pack -``` - Then configure the Messenger component: ```yaml # config/packages/messenger.yaml @@ -108,8 +104,6 @@ setono_sylius_partner_ads: After this the Messenger will be automatically enabled in this plugin and subsequently it will send an asynchronous request to Partner Ads instead of a synchronous. -For testing purposes you can sign up for a free RabbitMQ cloud service here: [CloudAMQP](https://www.cloudamqp.com/plans.html). - [ico-version]: https://poser.pugx.org/setono/sylius-partner-ads-plugin/v/stable [ico-license]: https://poser.pugx.org/setono/sylius-partner-ads-plugin/license [ico-github-actions]: https://github.com/Setono/SyliusPartnerAdsPlugin/workflows/build/badge.svg diff --git a/UPGRADE.md b/UPGRADE.md new file mode 100644 index 0000000..13ffa79 --- /dev/null +++ b/UPGRADE.md @@ -0,0 +1,48 @@ +# Upgrade + +## From 1.x to 2.x + +This release upgrades the plugin to Sylius 2. + +### Requirements + +| Package | Old | New | +|---------------|------------|----------------| +| PHP | >=7.4 | >=8.2 | +| sylius/sylius | ~1.10 | ^2.0 | +| Symfony | ^5.4/^6.0 | ^6.4 \|\| ^7.4 | + +### File layout + +Following the current Setono plugin convention, configuration moved out of `src/Resources/` to the +repository root: + +| Old | New | +|-----------------------------------------------------------|--------------------------------------| +| `src/Resources/config/services.xml` (+ `services/*.xml`) | `config/services.php` (PHP DSL) | +| `src/Resources/config/routing.yaml` | `config/routes.yaml` | +| `src/Resources/config/routing/admin.yaml` | `config/routes/admin.yaml` | +| `src/Resources/config/doctrine/model/Program.orm.xml` | `config/doctrine/model/Program.orm.xml` | +| `src/Resources/config/validation/Program.xml` | `config/validation/Program.xml` | +| `src/Resources/translations/*` | `translations/*` | +| `src/Resources/config/grids/*.yaml` | registered automatically by the plugin | +| `src/Resources/config/app/config.yaml` | removed | + +### Things you need to change in your project + +1. **Routing import** now points to the new location: + ```yaml + # config/routes/setono_sylius_partner_ads.yaml + setono_sylius_partner_ads: + resource: "@SetonoSyliusPartnerAdsPlugin/config/routes.yaml" + ``` +2. **Grid registration is automatic.** Remove any import of + `@SetonoSyliusPartnerAdsPlugin/Resources/config/app/config.yaml` — the admin grid is now registered + by the plugin via its bundle extension `prepend()`. + +### Removed + +| Removed | Replacement | +|---------------------------------------------------------------|------------------------------------------| +| `@SetonoSyliusPartnerAdsPlugin/Resources/config/routing.yaml` | `@SetonoSyliusPartnerAdsPlugin/config/routes.yaml` | +| `@SetonoSyliusPartnerAdsPlugin/Resources/config/app/config.yaml` | (no longer needed — grid auto-registered) | diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php new file mode 100644 index 0000000..0d11009 --- /dev/null +++ b/composer-dependency-analyser.php @@ -0,0 +1,28 @@ +addPathToScan(__DIR__ . '/config', false) + ->addPathToExclude(__DIR__ . '/tests') + // Buzz is an optional PSR-18 client fallback referenced behind interface_exists()/class_exists() + // guards in the compiler pass and configuration, so it is intentionally a dev dependency. + ->ignoreErrorsOnPackage('kriswallsmith/buzz', [ErrorType::DEV_DEPENDENCY_IN_PROD]) + // The sylius/sylius metapackage (dev only) "replace"s the split sylius/* packages this plugin requires. + // In this dev environment their classes therefore resolve to sylius/sylius, so the analyser reports + // sylius/sylius as a shadow dependency and the split packages as unused. The split packages are the + // correct production dependencies for consumers that do not install the sylius/sylius metapackage. + ->ignoreErrorsOnPackage('sylius/sylius', [ErrorType::DEV_DEPENDENCY_IN_PROD]) + ->ignoreErrorsOnPackages([ + 'sylius/channel', + 'sylius/channel-bundle', + 'sylius/core', + 'sylius/core-bundle', + 'sylius/order', + 'sylius/ui-bundle', + ], [ErrorType::UNUSED_DEPENDENCY]) +; diff --git a/composer-require-checker.json b/composer-require-checker.json deleted file mode 100644 index 2a0c655..0000000 --- a/composer-require-checker.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "symbol-whitelist": [ - "array", - "bool", - "callable", - "false", - "float", - "int", - "iterable", - "null", - "object", - "parent", - "self", - "static", - "string", - "true", - "void", - "Buzz\\Client\\BuzzClientInterface", - "Buzz\\Client\\Curl", - "Sylius\\Bundle\\ChannelBundle\\Form\\Type\\ChannelChoiceType", - "Sylius\\Bundle\\CoreBundle\\Application\\SyliusPluginTrait", - "Sylius\\Bundle\\UiBundle\\Menu\\Event\\MenuBuilderEvent", - "Sylius\\Component\\Channel\\Context\\ChannelContextInterface", - "Sylius\\Component\\Channel\\Model\\ChannelAwareInterface", - "Sylius\\Component\\Channel\\Model\\ChannelInterface", - "Sylius\\Component\\Core\\Model\\OrderInterface", - "Sylius\\Component\\Order\\Repository\\OrderRepositoryInterface" - ] -} diff --git a/composer.json b/composer.json index 3020ab8..6265cc5 100644 --- a/composer.json +++ b/composer.json @@ -10,41 +10,44 @@ "setono" ], "require": { - "php": ">=7.4", + "php": ">=8.2", "ext-mbstring": "*", "knplabs/knp-menu": "^3.1", + "nyholm/psr7": "^1.8", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", - "sylius/resource-bundle": "^1.6", - "symfony/config": "^5.4 || ^6.0", - "symfony/dependency-injection": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/form": "^5.4 || ^6.0", - "symfony/http-foundation": "^5.4 || ^6.0", - "symfony/http-kernel": "^5.4 || ^6.0", - "symfony/messenger": "^5.4 || ^6.0", + "psr/http-message": "^1.0 || ^2.0", + "sylius/channel": "^2.0", + "sylius/channel-bundle": "^2.0", + "sylius/core": "^2.0", + "sylius/core-bundle": "^2.0", + "sylius/order": "^2.0", + "sylius/resource-bundle": "^1.12", + "sylius/ui-bundle": "^2.0", + "symfony/config": "^6.4 || ^7.4", + "symfony/dependency-injection": "^6.4 || ^7.4", + "symfony/event-dispatcher": "^6.4 || ^7.4", + "symfony/form": "^6.4 || ^7.4", + "symfony/http-foundation": "^6.4 || ^7.4", + "symfony/http-kernel": "^6.4 || ^7.4", + "symfony/messenger": "^6.4 || ^7.4", "webmozart/assert": "^1.11" }, "require-dev": { - "api-platform/core": "^2.7", - "friendsofsymfony/oauth-server-bundle": ">2.0.0-alpha.0 ^2.0@dev", + "api-platform/symfony": "^4.3.3", "kriswallsmith/buzz": "^1.2", - "lexik/jwt-authentication-bundle": "^2.16", - "matthiasnoback/symfony-config-test": "^4.3", - "matthiasnoback/symfony-dependency-injection-test": "^4.3", - "phpspec/phpspec": "^7.2", - "phpunit/phpunit": "^9.5", - "psalm/plugin-symfony": "^5.0", - "setono/code-quality-pack": "^2.2", - "sylius/admin-api-bundle": "^1.11", - "sylius/sylius": "~1.10.14", - "symfony/debug-bundle": "^5.4 || ^6.0", - "symfony/dotenv": "^5.4 || ^6.0", - "symfony/intl": "^5.4 || ^6.0", - "symfony/serializer-pack": "^1.0", - "symfony/web-profiler-bundle": "^5.4 || ^6.0", - "symfony/webpack-encore-bundle": "^1.15" + "matthiasnoback/symfony-config-test": "^5.1 || ^6.0", + "payum/core": "^1.7.5", + "setono/sylius-plugin": "^2.0", + "sylius/grid-bundle": "^1.15", + "sylius/sylius": "~2.2.5", + "symfony/debug-bundle": "^6.4 || ^7.4", + "symfony/dotenv": "^6.4 || ^7.4", + "symfony/intl": "^6.4 || ^7.4", + "symfony/property-info": "^6.4 || ^7.4", + "symfony/serializer": "^6.4 || ^7.4", + "symfony/web-profiler-bundle": "^6.4 || ^7.4", + "symfony/webpack-encore-bundle": "^2.2" }, "prefer-stable": true, "autoload": { @@ -54,7 +57,7 @@ }, "autoload-dev": { "psr-4": { - "Tests\\Setono\\SyliusPartnerAdsPlugin\\": "tests/" + "Setono\\SyliusPartnerAdsPlugin\\Tests\\": "tests/" }, "classmap": [ "tests/Application/Kernel.php" @@ -64,19 +67,17 @@ "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": false, "ergebnis/composer-normalize": true, + "infection/extension-installer": true, + "php-http/discovery": false, + "phpstan/extension-installer": true, "symfony/thanks": false }, "sort-packages": true }, "scripts": { - "analyse": [ - "@ensure-test-container-exists", - "psalm" - ], + "analyse": "phpstan analyse", "check-style": "ecs check", - "ensure-test-container-exists": "[[ -f tests/Application/var/cache/test/ApplicationTests_Setono_SyliusPartnerAdsPlugin_Application_KernelTestDebugContainer.xml ]] || tests/Application/bin/console cache:warmup --env=test", "fix-style": "ecs check --fix", - "phpspec": "phpspec", "phpunit": "phpunit" } } diff --git a/src/Resources/config/doctrine/model/Program.orm.xml b/config/doctrine/model/Program.orm.xml similarity index 100% rename from src/Resources/config/doctrine/model/Program.orm.xml rename to config/doctrine/model/Program.orm.xml diff --git a/config/routes.yaml b/config/routes.yaml new file mode 100644 index 0000000..17ba6b9 --- /dev/null +++ b/config/routes.yaml @@ -0,0 +1,3 @@ +setono_sylius_partner_ads_admin: + resource: "@SetonoSyliusPartnerAdsPlugin/config/routes/admin.yaml" + prefix: /%sylius_admin.path_name%/partner-ads diff --git a/src/Resources/config/routing/admin.yaml b/config/routes/admin.yaml similarity index 55% rename from src/Resources/config/routing/admin.yaml rename to config/routes/admin.yaml index d99769a..6ca96b6 100644 --- a/src/Resources/config/routing/admin.yaml +++ b/config/routes/admin.yaml @@ -1,14 +1,9 @@ setono_sylius_partner_ads_admin_program: resource: | - section: admin alias: setono_sylius_partner_ads.program + section: admin permission: true - templates: "@SyliusAdmin\\Crud" + templates: "@SyliusAdmin\\shared\\crud" redirect: update grid: setono_sylius_partner_ads_admin_program - vars: - all: - subheader: setono_sylius_partner_ads.ui.manage_programs - index: - icon: 'handshake outline' type: sylius.resource diff --git a/config/services.php b/config/services.php new file mode 100644 index 0000000..abd8a79 --- /dev/null +++ b/config/services.php @@ -0,0 +1,103 @@ +parameters() + ->set('setono_sylius_partner_ads.form.program.validation_groups', ['setono_sylius_partner_ads']); + + $services = $container->services(); + + $services->set(OrderTotalCalculator::class); + $services->alias(OrderTotalCalculatorInterface::class, OrderTotalCalculator::class); + + $services->set(NotifyUrlProvider::class) + ->args([ + '%setono_sylius_partner_ads.urls.notify%', + ]); + $services->alias(NotifyUrlProviderInterface::class, NotifyUrlProvider::class); + + // PSR-17 factories. These ids are referenced by the Client and by RegisterHttpClientPass + $services->set('setono_sylius_partner_ads.http_client.request_factory', Psr17Factory::class); + $services->set('setono_sylius_partner_ads.http_client.response_factory', Psr17Factory::class); + + $services->set(Client::class) + ->args([ + // alias created by RegisterHttpClientPass (a configured PSR-18 client or a Buzz fallback) + service('setono_sylius_partner_ads.http_client'), + service('setono_sylius_partner_ads.http_client.request_factory'), + service(NotifyUrlProviderInterface::class), + ]); + $services->alias(ClientInterface::class, Client::class); + + $services->set(CookieHandler::class) + ->args([ + '%setono_sylius_partner_ads.cookie.name%', + '%setono_sylius_partner_ads.cookie.expire%', + ]); + $services->alias(CookieHandlerInterface::class, CookieHandler::class); + + $services->set(ProgramContext::class) + ->args([ + service('sylius.context.channel.composite'), + // repository service created by AbstractResourceExtension::registerResources() + service('setono_sylius_partner_ads.repository.program'), + ]); + $services->alias(ProgramContextInterface::class, ProgramContext::class); + + $services->set(NotifySubscriber::class) + ->args([ + // alias created by RegisterCommandBusPass + service('setono_sylius_partner_ads.command_bus'), + service(CookieHandlerInterface::class), + service(OrderTotalCalculatorInterface::class), + service(ProgramContextInterface::class), + service('sylius.repository.order'), + ]) + ->tag('kernel.event_subscriber'); + + $services->set(SetCookieSubscriber::class) + ->args([ + service(CookieHandlerInterface::class), + '%setono_sylius_partner_ads.query_parameter%', + ]) + ->tag('kernel.event_subscriber'); + + $services->set(ProgramType::class) + ->args([ + '%setono_sylius_partner_ads.model.program.class%', + '%setono_sylius_partner_ads.form.program.validation_groups%', + ]) + ->tag('form.type'); + + $services->set(NotifyHandler::class) + ->args([ + service(ClientInterface::class), + ]) + ->tag('messenger.message_handler'); + + $services->set(AdminMenuListener::class) + ->tag('kernel.event_listener', [ + 'event' => 'sylius.menu.admin.main', + 'method' => 'addAdminMenuItems', + ]); +}; diff --git a/src/Resources/config/validation/Program.xml b/config/validation/Program.xml similarity index 100% rename from src/Resources/config/validation/Program.xml rename to config/validation/Program.xml diff --git a/ecs.php b/ecs.php index bdc2526..4b0a2e4 100644 --- a/ecs.php +++ b/ecs.php @@ -2,16 +2,19 @@ declare(strict_types=1); -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; -use Symplify\EasyCodingStandard\ValueObject\Option; +use Symplify\EasyCodingStandard\Config\ECSConfig; -return static function (ContainerConfigurator $containerConfigurator): void { - $containerConfigurator->import('vendor/sylius-labs/coding-standard/ecs.php'); - $containerConfigurator->parameters()->set(Option::PATHS, [ - 'src', 'tests', 'spec' +return static function (ECSConfig $config): void { + $config->import('vendor/sylius-labs/coding-standard/ecs.php'); + $config->paths([ + 'src', + 'tests', + 'composer-dependency-analyser.php', + 'rector.php', ]); - $containerConfigurator->parameters()->set(Option::SKIP, [ + $config->skip([ 'tests/Application/node_modules/**', 'tests/Application/var/**', + 'tests/Application/config/reference.php', ]); }; diff --git a/infection.json5 b/infection.json5 new file mode 100644 index 0000000..8fd8b84 --- /dev/null +++ b/infection.json5 @@ -0,0 +1,15 @@ +{ + "$schema": "vendor/infection/infection/resources/schema.json", + "source": { + "directories": ["src"] + }, + "logs": { + "text": "php://stderr", + "github": true, + "stryker": { + "badge": "2.x" + } + }, + "minMsi": 100.00, + "minCoveredMsi": 100.00 +} diff --git a/phpspec.yml.dist b/phpspec.yml.dist deleted file mode 100644 index bc36a21..0000000 --- a/phpspec.yml.dist +++ /dev/null @@ -1,4 +0,0 @@ -suites: - main: - namespace: Setono\SyliusPartnerAdsPlugin - psr4_prefix: Setono\SyliusPartnerAdsPlugin diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..f124191 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,40 @@ +parameters: + level: max + + paths: + - src + - tests + + excludePaths: + - tests/Application/* + + bootstrapFiles: + - tests/Application/config/bootstrap.php + + # Symfony Configuration + symfony: + consoleApplicationLoader: tests/PHPStan/console_application.php + + # Doctrine Configuration + doctrine: + repositoryClass: Doctrine\ORM\EntityRepository + objectManagerLoader: tests/PHPStan/object_manager.php + + reportUnmatchedIgnoredErrors: false + treatPhpDocTypesAsCertain: false + + ignoreErrors: + - + identifier: doctrine.associationType + - + identifier: doctrine.columnType + - + identifier: missingType.generics + - + identifier: missingType.iterableValue + - + identifier: trait.unused + path: src/Model + - + identifier: trait.unused + path: src/Repository diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index e953691..0000000 --- a/psalm.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - tests/Application/var/cache/test/ApplicationTests_Setono_SyliusPartnerAdsPlugin_Application_KernelTestDebugContainer.xml - - - tests/Application/var/cache/test/Tests_Setono_SyliusPartnerAdsPlugin_Application_KernelTestDebugContainer.xml - - - - - - diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..489a662 --- /dev/null +++ b/rector.php @@ -0,0 +1,25 @@ +cacheClass(FileCacheStorage::class); + $rectorConfig->cacheDirectory('./.build/rector'); + + $rectorConfig->paths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]); + + $rectorConfig->skip([ + __DIR__ . '/tests/Application', + ]); + + $rectorConfig->sets([ + LevelSetList::UP_TO_PHP_82, + ]); +}; diff --git a/spec/Calculator/OrderTotalCalculatorSpec.php b/spec/Calculator/OrderTotalCalculatorSpec.php deleted file mode 100644 index 3ecc60f..0000000 --- a/spec/Calculator/OrderTotalCalculatorSpec.php +++ /dev/null @@ -1,45 +0,0 @@ -shouldHaveType(OrderTotalCalculator::class); - } - - public function it_returns_correct_total(OrderInterface $order): void - { - $tests = [ - [ - 'total' => 0, - 'shipping' => 0, - 'expected' => 0.0, - ], - [ - 'total' => 10, - 'shipping' => 9, - 'expected' => 0.01, - ], - [ - 'total' => 123456, - 'shipping' => 1245, - 'expected' => 1222.11, - ], - ]; - - foreach ($tests as $test) { - $order->getTotal()->willReturn($test['total']); - $order->getShippingTotal()->willReturn($test['shipping']); - - $this->get($order)->shouldReturn($test['expected']); - } - } -} diff --git a/spec/Client/ClientSpec.php b/spec/Client/ClientSpec.php deleted file mode 100644 index f59979f..0000000 --- a/spec/Client/ClientSpec.php +++ /dev/null @@ -1,51 +0,0 @@ -provide(Argument::cetera())->willReturn($this->url); - - $this->beConstructedWith($httpClient, $requestFactory, $notifyUrlProvider); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(Client::class); - } - - public function it_implements_client_interface(): void - { - $this->shouldHaveType(ClientInterface::class); - } - - public function it_notifies( - HttpClientInterface $httpClient, - RequestFactoryInterface $requestFactory, - RequestInterface $request, - ResponseInterface $response - ): void { - $requestFactory->createRequest('GET', $this->url)->willReturn($request); - - $response->getStatusCode()->willReturn(200); - $response->getBody()->shouldBeCalled(); - $httpClient->sendRequest($request)->willReturn($response); - $this->notify(123, 'order-123', 123.123, 123, '123.456.789.000'); - } -} diff --git a/spec/EventListener/NotifySubscriberSpec.php b/spec/EventListener/NotifySubscriberSpec.php deleted file mode 100644 index 87670b3..0000000 --- a/spec/EventListener/NotifySubscriberSpec.php +++ /dev/null @@ -1,168 +0,0 @@ -beConstructedWith($messageBus, $cookieHandler, $orderTotalCalculator, $programContext, $orderRepository); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(NotifySubscriber::class); - } - - public function it_implements_event_subscriber_interface(): void - { - $this->shouldImplement(EventSubscriberInterface::class); - } - - public function it_notifies( - RequestEvent $event, - OrderInterface $order, - CookieHandlerInterface $cookieHandler, - OrderTotalCalculatorInterface $orderTotalCalculator, - ProgramContextInterface $programContext, - ProgramInterface $program, - MessageBusInterface $messageBus, - StampInterface $stamp, - OrderRepositoryInterface $orderRepository - ): void { - $request = self::getRequest(); - $event->getRequest()->willReturn($request); - $event->isMainRequest()->willReturn(true); - - $orderRepository->find(123)->willReturn($order); - - $cookieHandler->has($request)->willReturn(true); - $cookieHandler->get($request)->willReturn(123); - $programContext->getProgram()->willReturn($program); - $program->getProgramId()->willReturn(1234); - $orderTotalCalculator->get($order)->willReturn(199.0); - $envelope = new Envelope(new stdClass(), [$stamp->getWrappedObject()]); - - $messageBus->dispatch(Argument::any())->willReturn($envelope)->shouldBeCalled(); - - $this->notify($event); - } - - private static function getRequest(): Request - { - $session = new class() implements SessionInterface { - public function start() - { - } - - public function getId() - { - } - - public function setId($id) - { - } - - public function getName() - { - } - - public function setName($name) - { - } - - public function invalidate($lifetime = null) - { - } - - public function migrate($destroy = false, $lifetime = null) - { - } - - public function save() - { - } - - public function has($name) - { - } - - public function get($name, $default = null) - { - return 123; - } - - public function set($name, $value) - { - } - - public function all() - { - } - - public function replace(array $attributes) - { - } - - public function remove($name) - { - } - - public function clear() - { - } - - public function isStarted() - { - } - - public function registerBag(SessionBagInterface $bag) - { - } - - public function getBag($name) - { - } - - public function getMetadataBag() - { - } - }; - - return new class($session) extends Request { - public function __construct(SessionInterface $session) - { - parent::__construct(); - - $this->attributes->set('_route', 'sylius_shop_order_thank_you'); - $this->setSession($session); - } - }; - } -} diff --git a/spec/EventListener/SetCookieSubscriberSpec.php b/spec/EventListener/SetCookieSubscriberSpec.php deleted file mode 100644 index 723233b..0000000 --- a/spec/EventListener/SetCookieSubscriberSpec.php +++ /dev/null @@ -1,91 +0,0 @@ -beConstructedWith($cookieHandler, $this->param); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(SetCookieSubscriber::class); - } - - public function it_does_not_do_anything_when_not_master_request( - HttpKernelInterface $kernel, - Request $request, - Response $response - ): void { - $event = new ResponseEvent($kernel->getWrappedObject(), $request->getWrappedObject(), HttpKernelInterface::SUB_REQUEST, $response->getWrappedObject()); - - $request->isXmlHttpRequest()->shouldNotBeCalled(); - - $this->setCookie($event); - } - - public function it_does_not_do_anything_when_xml_request( - HttpKernelInterface $kernel, - Request $request, - Response $response, - CookieHandlerInterface $cookieHandler - ): void { - $event = new ResponseEvent($kernel->getWrappedObject(), $request->getWrappedObject(), HttpKernelInterface::MAIN_REQUEST, $response->getWrappedObject()); - $request->isXmlHttpRequest()->willReturn(true); - - $cookieHandler->set(Argument::any(), Argument::any())->shouldNotBeCalled(); - - $this->setCookie($event); - } - - public function it_does_not_do_anything_when_query_param_is_not_set( - HttpKernelInterface $kernel, - Request $request, - Response $response, - CookieHandlerInterface $cookieHandler, - ParameterBag $query - ): void { - $event = new ResponseEvent($kernel->getWrappedObject(), $request->getWrappedObject(), HttpKernelInterface::MAIN_REQUEST, $response->getWrappedObject()); - $request->isXmlHttpRequest()->willReturn(false); - $query->has($this->param)->willReturn(false); - $request->query = $query; - - $cookieHandler->set(Argument::any(), Argument::any())->shouldNotBeCalled(); - - $this->setCookie($event); - } - - public function it_sets( - HttpKernelInterface $kernel, - Request $request, - Response $response, - CookieHandlerInterface $cookieHandler, - ParameterBag $query - ): void { - $event = new ResponseEvent($kernel->getWrappedObject(), $request->getWrappedObject(), HttpKernelInterface::MAIN_REQUEST, $response->getWrappedObject()); - $request->isXmlHttpRequest()->willReturn(false); - $query->has($this->param)->willReturn(true); - $query->get($this->param)->willReturn('123'); - $request->query = $query; - - $cookieHandler->set(Argument::any(), '123')->shouldBeCalled(); - - $this->setCookie($event); - } -} diff --git a/spec/UrlProvider/NotifyUrlProviderSpec.php b/spec/UrlProvider/NotifyUrlProviderSpec.php deleted file mode 100644 index b2c83e2..0000000 --- a/spec/UrlProvider/NotifyUrlProviderSpec.php +++ /dev/null @@ -1,48 +0,0 @@ -beConstructedWith('https://example.com/?programid={program_id}&type=salg&partnerid={partner_id}&userip={ip}&ordreid={order_id}&varenummer=x&antal=1&omprsalg={value}'); - } - - public function it_is_initializable(): void - { - $this->shouldHaveType(NotifyUrlProvider::class); - } - - public function it_implements_notify_url_provider_interface(): void - { - $this->shouldImplement(NotifyUrlProviderInterface::class); - } - - public function it_throws_exception(): void - { - $this->beConstructedWith(''); - - $this->shouldThrow(MissingVariableInUrlException::class)->during('provide', [123, '123', 123.123, 123, '123']); - } - - public function it_provides_correct_url(): void - { - $programId = 123; - $partnerId = 456; - $ip = '123.123.123.123'; - $orderId = 'order-123'; - $value = 123.123; - - $expectedUrl = "https://example.com/?programid=$programId&type=salg&partnerid=$partnerId&userip=$ip&ordreid=$orderId&varenummer=x&antal=1&omprsalg=$value"; - - $this->provide($programId, $orderId, $value, $partnerId, $ip)->shouldReturn($expectedUrl); - } -} diff --git a/src/Client/Client.php b/src/Client/Client.php index 29c4f78..61991d1 100644 --- a/src/Client/Client.php +++ b/src/Client/Client.php @@ -9,22 +9,10 @@ use Setono\SyliusPartnerAdsPlugin\Exception\RequestFailedException; use Setono\SyliusPartnerAdsPlugin\UrlProvider\NotifyUrlProviderInterface; -final class Client implements ClientInterface +final readonly class Client implements ClientInterface { - private HttpClientInterface $httpClient; - - private RequestFactoryInterface $requestFactory; - - private NotifyUrlProviderInterface $notifyUrlProvider; - - public function __construct( - HttpClientInterface $httpClient, - RequestFactoryInterface $requestFactory, - NotifyUrlProviderInterface $notifyUrlProvider - ) { - $this->httpClient = $httpClient; - $this->requestFactory = $requestFactory; - $this->notifyUrlProvider = $notifyUrlProvider; + public function __construct(private HttpClientInterface $httpClient, private RequestFactoryInterface $requestFactory, private NotifyUrlProviderInterface $notifyUrlProvider) + { } public function notify(int $programId, string $orderId, float $total, int $partnerId, string $ip): void diff --git a/src/Context/ProgramContext.php b/src/Context/ProgramContext.php index e22103e..2b76cfd 100644 --- a/src/Context/ProgramContext.php +++ b/src/Context/ProgramContext.php @@ -8,16 +8,10 @@ use Setono\SyliusPartnerAdsPlugin\Repository\ProgramRepositoryInterface; use Sylius\Component\Channel\Context\ChannelContextInterface; -final class ProgramContext implements ProgramContextInterface +final readonly class ProgramContext implements ProgramContextInterface { - private ChannelContextInterface $channelContext; - - private ProgramRepositoryInterface $programRepository; - - public function __construct(ChannelContextInterface $channelContext, ProgramRepositoryInterface $programRepository) + public function __construct(private ChannelContextInterface $channelContext, private ProgramRepositoryInterface $programRepository) { - $this->channelContext = $channelContext; - $this->programRepository = $programRepository; } public function getProgram(): ?ProgramInterface diff --git a/src/CookieHandler/CookieHandler.php b/src/CookieHandler/CookieHandler.php index 75e1505..5f2eb31 100644 --- a/src/CookieHandler/CookieHandler.php +++ b/src/CookieHandler/CookieHandler.php @@ -8,16 +8,10 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -final class CookieHandler implements CookieHandlerInterface +final readonly class CookieHandler implements CookieHandlerInterface { - private string $cookieName; - - private int $expire; - - public function __construct(string $cookieName, int $expire) + public function __construct(private string $cookieName, private int $expire) { - $this->cookieName = $cookieName; - $this->expire = $expire; } public function set(Response $response, int $partnerId): void diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index ab6744f..2ef9fce 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -23,7 +23,6 @@ public function getConfigTreeBuilder(): TreeBuilder $rootNode = $treeBuilder->getRootNode(); - /** @psalm-suppress MixedMethodCall,PossiblyNullReference,PossiblyUndefinedMethod,UndefinedInterfaceMethod */ $rootNode ->addDefaultsIfNotSet() ->children() @@ -87,8 +86,8 @@ public function getConfigTreeBuilder(): TreeBuilder ->children() ->scalarNode('command_bus') ->cannotBeEmpty() - ->defaultValue('message_bus') - ->example('message_bus') + ->defaultValue('sylius.command_bus') + ->example('sylius.command_bus') ->info('The service id for the message bus you use for commands') ->end() ->scalarNode('transport') diff --git a/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php b/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php index 38023e8..7047500 100644 --- a/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php +++ b/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php @@ -9,14 +9,25 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; final class SetonoSyliusPartnerAdsExtension extends AbstractResourceExtension implements PrependExtensionInterface { public function load(array $configs, ContainerBuilder $container): void { + /** + * @var array{ + * driver: string, + * resources: array, + * http_client: string|null, + * urls: array{notify: string}, + * query_parameter: string, + * cookie: array{name: string, expire: int}, + * messenger: array{command_bus: string, transport: string|null} + * } $config + */ $config = $this->processConfiguration($this->getConfiguration([], $container), $configs); - $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../../config')); $container->setParameter('setono_sylius_partner_ads.http_client', $config['http_client']); $container->setParameter('setono_sylius_partner_ads.urls.notify', $config['urls']['notify']); @@ -28,15 +39,64 @@ public function load(array $configs, ContainerBuilder $container): void $this->registerResources('setono_sylius_partner_ads', $config['driver'], $config['resources'], $container); - $loader->load('services.xml'); + $loader->load('services.php'); } public function prepend(ContainerBuilder $container): void { - $config = $this->processConfiguration($this->getConfiguration([], $container), $container->getExtensionConfig($this->getAlias())); + /** @var array{resources: array{program: array{classes: array{model: string}}}, messenger: array{transport: string|null}} $config */ + $config = $this->processConfiguration( + $this->getConfiguration([], $container), + $container->getExtensionConfig($this->getAlias()), + ); - $transport = $config['messenger']['transport']; + // The model class parameter is normally set by registerResources() during load(), but the + // sylius_grid extension resolves it while loading its own configuration. Depending on bundle + // registration order that can happen before this plugin's load() runs, so we set it here in + // prepend() (which always runs before any load()) to make the grid registration order-independent. + $container->setParameter('setono_sylius_partner_ads.model.program.class', $config['resources']['program']['classes']['model']); + $this->prependGrid($container); + $this->prependMessenger($container, $config['messenger']['transport']); + } + + private function prependGrid(ContainerBuilder $container): void + { + $container->prependExtensionConfig('sylius_grid', [ + 'grids' => [ + 'setono_sylius_partner_ads_admin_program' => [ + 'driver' => [ + 'name' => 'doctrine/orm', + 'options' => [ + 'class' => '%setono_sylius_partner_ads.model.program.class%', + ], + ], + 'fields' => [ + 'programId' => [ + 'type' => 'string', + 'label' => 'setono_sylius_partner_ads.ui.program_id', + ], + 'channel' => [ + 'type' => 'string', + 'label' => 'setono_sylius_partner_ads.ui.channel', + ], + ], + 'actions' => [ + 'main' => [ + 'create' => ['type' => 'create'], + ], + 'item' => [ + 'update' => ['type' => 'update'], + 'delete' => ['type' => 'delete'], + ], + ], + ], + ], + ]); + } + + private function prependMessenger(ContainerBuilder $container, ?string $transport): void + { if (null === $transport) { return; } diff --git a/src/EventListener/NotifySubscriber.php b/src/EventListener/NotifySubscriber.php index ad394fd..28deb8f 100644 --- a/src/EventListener/NotifySubscriber.php +++ b/src/EventListener/NotifySubscriber.php @@ -15,30 +15,10 @@ use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Messenger\MessageBusInterface; -final class NotifySubscriber implements EventSubscriberInterface +final readonly class NotifySubscriber implements EventSubscriberInterface { - private MessageBusInterface $messageBus; - - private CookieHandlerInterface $cookieHandler; - - private OrderTotalCalculatorInterface $orderTotalCalculator; - - private ProgramContextInterface $programContext; - - private OrderRepositoryInterface $orderRepository; - - public function __construct( - MessageBusInterface $messageBus, - CookieHandlerInterface $cookieHandler, - OrderTotalCalculatorInterface $orderTotalCalculator, - ProgramContextInterface $programContext, - OrderRepositoryInterface $orderRepository - ) { - $this->messageBus = $messageBus; - $this->cookieHandler = $cookieHandler; - $this->orderTotalCalculator = $orderTotalCalculator; - $this->programContext = $programContext; - $this->orderRepository = $orderRepository; + public function __construct(private MessageBusInterface $messageBus, private CookieHandlerInterface $cookieHandler, private OrderTotalCalculatorInterface $orderTotalCalculator, private ProgramContextInterface $programContext, private OrderRepositoryInterface $orderRepository) + { } public static function getSubscribedEvents(): array @@ -89,11 +69,11 @@ public function notify(RequestEvent $event): void } $this->messageBus->dispatch(new Notify( - (int) $program->getProgramId(), + $program->getProgramId(), (string) $order->getNumber(), $this->orderTotalCalculator->get($order), $this->cookieHandler->get($request), - (string) $request->getClientIp() + (string) $request->getClientIp(), )); } } diff --git a/src/EventListener/SetCookieSubscriber.php b/src/EventListener/SetCookieSubscriber.php index 059219e..43a07d1 100644 --- a/src/EventListener/SetCookieSubscriber.php +++ b/src/EventListener/SetCookieSubscriber.php @@ -9,16 +9,10 @@ use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; -final class SetCookieSubscriber implements EventSubscriberInterface +final readonly class SetCookieSubscriber implements EventSubscriberInterface { - private CookieHandlerInterface $cookieHandler; - - private string $queryParameter; - - public function __construct(CookieHandlerInterface $cookieHandler, string $queryParameter) + public function __construct(private CookieHandlerInterface $cookieHandler, private string $queryParameter) { - $this->cookieHandler = $cookieHandler; - $this->queryParameter = $queryParameter; } public static function getSubscribedEvents(): array diff --git a/src/Exception/InterfaceNotFoundException.php b/src/Exception/InterfaceNotFoundException.php index 5d6ba64..8c619e3 100644 --- a/src/Exception/InterfaceNotFoundException.php +++ b/src/Exception/InterfaceNotFoundException.php @@ -8,12 +8,8 @@ final class InterfaceNotFoundException extends RuntimeException { - private string $interface; - - public function __construct(string $interface) + public function __construct(private readonly string $interface) { - $this->interface = $interface; - parent::__construct(sprintf('The interface "%s" was not found', $this->interface)); } diff --git a/src/Exception/MissingVariableInUrlException.php b/src/Exception/MissingVariableInUrlException.php index 5934b4e..cc2eb81 100644 --- a/src/Exception/MissingVariableInUrlException.php +++ b/src/Exception/MissingVariableInUrlException.php @@ -8,15 +8,8 @@ final class MissingVariableInUrlException extends InvalidArgumentException { - private string $url; - - private string $missingVariable; - - public function __construct(string $url, string $missingVariable) + public function __construct(private readonly string $url, private readonly string $missingVariable) { - $this->url = $url; - $this->missingVariable = $missingVariable; - parent::__construct(sprintf('The URL %s is missing variable %s', $this->url, $this->missingVariable)); } diff --git a/src/Exception/RequestFailedException.php b/src/Exception/RequestFailedException.php index d22bbb4..03da4e8 100644 --- a/src/Exception/RequestFailedException.php +++ b/src/Exception/RequestFailedException.php @@ -10,18 +10,8 @@ final class RequestFailedException extends RuntimeException { - private RequestInterface $request; - - private ResponseInterface $response; - - private int $statusCode; - - public function __construct(RequestInterface $request, ResponseInterface $response, int $statusCode) + public function __construct(private readonly RequestInterface $request, private readonly ResponseInterface $response, private readonly int $statusCode) { - $this->request = $request; - $this->response = $response; - $this->statusCode = $statusCode; - parent::__construct(sprintf('Request failed with status code %d', $this->statusCode)); } diff --git a/src/Message/Command/Notify.php b/src/Message/Command/Notify.php index 9308f91..9786905 100644 --- a/src/Message/Command/Notify.php +++ b/src/Message/Command/Notify.php @@ -4,25 +4,10 @@ namespace Setono\SyliusPartnerAdsPlugin\Message\Command; -final class Notify +final readonly class Notify { - private int $programId; - - private string $orderId; - - private float $orderTotal; - - private int $partnerId; - - private string $ip; - - public function __construct(int $programId, string $orderId, float $orderTotal, int $partnerId, string $ip) + public function __construct(private int $programId, private string $orderId, private float $orderTotal, private int $partnerId, private string $ip) { - $this->programId = $programId; - $this->orderId = $orderId; - $this->orderTotal = $orderTotal; - $this->partnerId = $partnerId; - $this->ip = $ip; } public function getProgramId(): int diff --git a/src/Message/Handler/NotifyHandler.php b/src/Message/Handler/NotifyHandler.php index b872ada..404b750 100644 --- a/src/Message/Handler/NotifyHandler.php +++ b/src/Message/Handler/NotifyHandler.php @@ -7,13 +7,10 @@ use Setono\SyliusPartnerAdsPlugin\Client\ClientInterface; use Setono\SyliusPartnerAdsPlugin\Message\Command\Notify; -final class NotifyHandler +final readonly class NotifyHandler { - private ClientInterface $client; - - public function __construct(ClientInterface $client) + public function __construct(private ClientInterface $client) { - $this->client = $client; } public function __invoke(Notify $message): void diff --git a/src/Resources/config/app/config.yaml b/src/Resources/config/app/config.yaml deleted file mode 100644 index 748ac95..0000000 --- a/src/Resources/config/app/config.yaml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - "@SetonoSyliusPartnerAdsPlugin/Resources/config/grids/setono_sylius_partner_ads_admin_program.yaml" diff --git a/src/Resources/config/grids/setono_sylius_partner_ads_admin_program.yaml b/src/Resources/config/grids/setono_sylius_partner_ads_admin_program.yaml deleted file mode 100644 index 3e7f165..0000000 --- a/src/Resources/config/grids/setono_sylius_partner_ads_admin_program.yaml +++ /dev/null @@ -1,23 +0,0 @@ -sylius_grid: - grids: - setono_sylius_partner_ads_admin_program: - driver: - name: doctrine/orm - options: - class: "%setono_sylius_partner_ads.model.program.class%" - fields: - programId: - type: string - label: setono_sylius_partner_ads.ui.program_id - channel: - type: string - label: setono_sylius_partner_ads.ui.channel - actions: - main: - create: - type: create - item: - update: - type: update - delete: - type: delete diff --git a/src/Resources/config/routing.yaml b/src/Resources/config/routing.yaml deleted file mode 100644 index cfeb411..0000000 --- a/src/Resources/config/routing.yaml +++ /dev/null @@ -1,3 +0,0 @@ -setono_sylius_partner_ads_admin: - resource: routing/admin.yaml - prefix: /admin/partner-ads diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml deleted file mode 100644 index 34524bb..0000000 --- a/src/Resources/config/services.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/src/Resources/config/services/calculator.xml b/src/Resources/config/services/calculator.xml deleted file mode 100644 index 18c0c69..0000000 --- a/src/Resources/config/services/calculator.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Resources/config/services/client.xml b/src/Resources/config/services/client.xml deleted file mode 100644 index 65a3349..0000000 --- a/src/Resources/config/services/client.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/Resources/config/services/context.xml b/src/Resources/config/services/context.xml deleted file mode 100644 index fdb9c43..0000000 --- a/src/Resources/config/services/context.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/Resources/config/services/cookie_handler.xml b/src/Resources/config/services/cookie_handler.xml deleted file mode 100644 index bf7209c..0000000 --- a/src/Resources/config/services/cookie_handler.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - %setono_sylius_partner_ads.cookie.name% - %setono_sylius_partner_ads.cookie.expire% - - - diff --git a/src/Resources/config/services/event_listener.xml b/src/Resources/config/services/event_listener.xml deleted file mode 100644 index 31bd771..0000000 --- a/src/Resources/config/services/event_listener.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - %setono_sylius_partner_ads.query_parameter% - - - - diff --git a/src/Resources/config/services/form.xml b/src/Resources/config/services/form.xml deleted file mode 100644 index 08ad6a7..0000000 --- a/src/Resources/config/services/form.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - setono_sylius_partner_ads - - - - - %setono_sylius_partner_ads.model.program.class% - %setono_sylius_partner_ads.form.program.validation_groups% - - - - diff --git a/src/Resources/config/services/http_client.xml b/src/Resources/config/services/http_client.xml deleted file mode 100644 index 99c8a9b..0000000 --- a/src/Resources/config/services/http_client.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/Resources/config/services/menu.xml b/src/Resources/config/services/menu.xml deleted file mode 100644 index 3d3fdbc..0000000 --- a/src/Resources/config/services/menu.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/Resources/config/services/message.xml b/src/Resources/config/services/message.xml deleted file mode 100644 index 5e13e97..0000000 --- a/src/Resources/config/services/message.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Resources/config/services/message/handler.xml b/src/Resources/config/services/message/handler.xml deleted file mode 100644 index 279740f..0000000 --- a/src/Resources/config/services/message/handler.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/Resources/config/services/url_provider.xml b/src/Resources/config/services/url_provider.xml deleted file mode 100644 index 3a5f492..0000000 --- a/src/Resources/config/services/url_provider.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - %setono_sylius_partner_ads.urls.notify% - - - diff --git a/src/SetonoSyliusPartnerAdsPlugin.php b/src/SetonoSyliusPartnerAdsPlugin.php index 0ac2c7f..cf2decd 100644 --- a/src/SetonoSyliusPartnerAdsPlugin.php +++ b/src/SetonoSyliusPartnerAdsPlugin.php @@ -23,10 +23,29 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new RegisterHttpClientPass()); } + public function getPath(): string + { + return \dirname(__DIR__); + } + public function getSupportedDrivers(): array { return [ SyliusResourceBundle::DRIVER_DOCTRINE_ORM, ]; } + + protected function getModelNamespace(): string + { + return 'Setono\SyliusPartnerAdsPlugin\Model'; + } + + protected function getConfigFilesPath(): string + { + return sprintf( + '%s/config/doctrine/%s', + $this->getPath(), + strtolower($this->getDoctrineMappingDirectory()), + ); + } } diff --git a/src/UrlProvider/NotifyUrlProvider.php b/src/UrlProvider/NotifyUrlProvider.php index a9ac7cf..ad422ce 100644 --- a/src/UrlProvider/NotifyUrlProvider.php +++ b/src/UrlProvider/NotifyUrlProvider.php @@ -6,13 +6,10 @@ use Setono\SyliusPartnerAdsPlugin\Exception\MissingVariableInUrlException; -final class NotifyUrlProvider implements NotifyUrlProviderInterface +final readonly class NotifyUrlProvider implements NotifyUrlProviderInterface { - private string $url; - - public function __construct(string $url) + public function __construct(private string $url) { - $this->url = $url; } public function provide(int $programId, string $orderId, float $value, int $partnerId, string $ip): string @@ -27,8 +24,8 @@ public function provide(int $programId, string $orderId, float $value, int $part return str_replace( ['{program_id}', '{partner_id}', '{ip}', '{order_id}', '{value}'], - [$programId, $partnerId, $ip, $orderId, $value], - $this->url + [(string) $programId, (string) $partnerId, $ip, $orderId, (string) $value], + $this->url, ); } } diff --git a/tests/Application/.env b/tests/Application/.env index 2afcb77..fe58793 100644 --- a/tests/Application/.env +++ b/tests/Application/.env @@ -1,5 +1,16 @@ -# This file is a "template" of which env vars needs to be defined in your configuration or in an .env file -# Set variables here that may be different on each deployment target of the app, e.g. development, staging, production. +# In all environments, the following files are loaded if they exist, +# the later taking precedence over the former: +# +# * .env contains default values for the environment variables needed by the app +# * .env.local uncommitted file with local overrides +# * .env.$APP_ENV committed environment-specific defaults +# * .env.$APP_ENV.local uncommitted environment-specific overrides +# +# Real environment variables win over .env files. +# +# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. +# +# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration ###> symfony/framework-bundle ### @@ -9,21 +20,28 @@ APP_SECRET=EDITME ###< symfony/framework-bundle ### ###> doctrine/doctrine-bundle ### -# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url +# Format described at https://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url # For a sqlite database, use: "sqlite:///%kernel.project_dir%/var/data.db" # Set "serverVersion" to your server version to avoid edge-case exceptions and extra database calls -DATABASE_URL=mysql://root@127.0.0.1/setono_sylius_partner_ads_%kernel.environment%?serverVersion=5.7 +DATABASE_URL=mysql://root@127.0.0.1/setono_sylius_partner_ads_%kernel.environment%?serverVersion=11.6.2-MariaDB ###< doctrine/doctrine-bundle ### ###> lexik/jwt-authentication-bundle ### JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem -JWT_PASSPHRASE=acme_plugin_development +JWT_PASSPHRASE=acme_sylius_example_development ###< lexik/jwt-authentication-bundle ### +###> symfony/messenger ### +# Choose one of the transports below +# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages +MESSENGER_TRANSPORT_DSN=doctrine://default +# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages +###< symfony/messenger ### + ###> symfony/swiftmailer-bundle ### # For Gmail as a transport, use: "gmail://username:password@localhost" # For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode=" # Delivery is disabled by default via "null://localhost" -MAILER_URL=null://localhost +MAILER_DSN=null://localhost ###< symfony/swiftmailer-bundle ### diff --git a/tests/Application/.env.test b/tests/Application/.env.test index 02281a0..a251ad8 100644 --- a/tests/Application/.env.test +++ b/tests/Application/.env.test @@ -1,3 +1,3 @@ APP_SECRET='ch4mb3r0f5ecr3ts' -KERNEL_CLASS='Tests\Setono\SyliusPartnerAdsPlugin\Application\Kernel' +KERNEL_CLASS='Setono\SyliusPartnerAdsPlugin\Tests\Application\Kernel' diff --git a/tests/Application/.gitignore b/tests/Application/.gitignore index bc600a8..57ff3f1 100644 --- a/tests/Application/.gitignore +++ b/tests/Application/.gitignore @@ -21,3 +21,5 @@ ###> symfony/web-server-bundle ### /.web-server-pid ###< symfony/web-server-bundle ### + +/config/reference.php diff --git a/tests/Application/Client/Client.php b/tests/Application/Client/Client.php index 57256f4..68e7702 100644 --- a/tests/Application/Client/Client.php +++ b/tests/Application/Client/Client.php @@ -2,24 +2,21 @@ declare(strict_types=1); -namespace Tests\Setono\SyliusPartnerAdsPlugin\Application\Client; +namespace Setono\SyliusPartnerAdsPlugin\Tests\Application\Client; use Psr\Log\LoggerInterface; use Setono\SyliusPartnerAdsPlugin\Client\ClientInterface; use Setono\SyliusPartnerAdsPlugin\UrlProvider\NotifyUrlProviderInterface; +/** + * Test double used by the test application so functional tests don't make real HTTP requests to Partner Ads. + */ final class Client implements ClientInterface { - /** @var NotifyUrlProviderInterface */ - private $notifyUrlProvider; - - /** @var LoggerInterface */ - private $logger; - - public function __construct(NotifyUrlProviderInterface $notifyUrlProvider, LoggerInterface $logger) - { - $this->notifyUrlProvider = $notifyUrlProvider; - $this->logger = $logger; + public function __construct( + private readonly NotifyUrlProviderInterface $notifyUrlProvider, + private readonly LoggerInterface $logger, + ) { } public function notify(int $programId, string $orderId, float $total, int $partnerId, string $ip): void diff --git a/tests/Application/Kernel.php b/tests/Application/Kernel.php index 790f0ac..db86064 100644 --- a/tests/Application/Kernel.php +++ b/tests/Application/Kernel.php @@ -2,124 +2,12 @@ declare(strict_types=1); -namespace Tests\Setono\SyliusPartnerAdsPlugin\Application; +namespace Setono\SyliusPartnerAdsPlugin\Tests\Application; -use PSS\SymfonyMockerContainer\DependencyInjection\MockerContainer; -use Sylius\Bundle\CoreBundle\Application\Kernel as SyliusKernel; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Kernel as BaseKernel; -use Symfony\Component\Routing\RouteCollectionBuilder; final class Kernel extends BaseKernel { use MicroKernelTrait; - - private const CONFIG_EXTS = '.{php,xml,yaml,yml}'; - - public function getCacheDir(): string - { - return $this->getProjectDir() . '/var/cache/' . $this->environment; - } - - public function getLogDir(): string - { - return $this->getProjectDir() . '/var/log'; - } - - public function registerBundles(): iterable - { - foreach ($this->getConfigurationDirectories() as $confDir) { - $bundlesFile = $confDir . '/bundles.php'; - if (false === is_file($bundlesFile)) { - continue; - } - yield from $this->registerBundlesFromFile($bundlesFile); - } - } - - protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void - { - foreach ($this->getConfigurationDirectories() as $confDir) { - $bundlesFile = $confDir . '/bundles.php'; - if (false === is_file($bundlesFile)) { - continue; - } - $container->addResource(new FileResource($bundlesFile)); - } - - $container->setParameter('container.dumper.inline_class_loader', true); - - foreach ($this->getConfigurationDirectories() as $confDir) { - $this->loadContainerConfiguration($loader, $confDir); - } - } - - protected function configureRoutes(RouteCollectionBuilder $routes): void - { - foreach ($this->getConfigurationDirectories() as $confDir) { - $this->loadRoutesConfiguration($routes, $confDir); - } - } - - protected function getContainerBaseClass(): string - { - if ($this->isTestEnvironment() && class_exists(MockerContainer::class)) { - return MockerContainer::class; - } - - return parent::getContainerBaseClass(); - } - - private function isTestEnvironment(): bool - { - return 0 === strpos($this->getEnvironment(), 'test'); - } - - private function loadContainerConfiguration(LoaderInterface $loader, string $confDir): void - { - $loader->load($confDir . '/{packages}/*' . self::CONFIG_EXTS, 'glob'); - $loader->load($confDir . '/{packages}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, 'glob'); - $loader->load($confDir . '/{services}' . self::CONFIG_EXTS, 'glob'); - $loader->load($confDir . '/{services}_' . $this->environment . self::CONFIG_EXTS, 'glob'); - } - - private function loadRoutesConfiguration(RouteCollectionBuilder $routes, string $confDir): void - { - $routes->import($confDir . '/{routes}/*' . self::CONFIG_EXTS, '/', 'glob'); - $routes->import($confDir . '/{routes}/' . $this->environment . '/**/*' . self::CONFIG_EXTS, '/', 'glob'); - $routes->import($confDir . '/{routes}' . self::CONFIG_EXTS, '/', 'glob'); - } - - /** - * @return BundleInterface[] - */ - private function registerBundlesFromFile(string $bundlesFile): iterable - { - $contents = require $bundlesFile; - foreach ($contents as $class => $envs) { - if (isset($envs['all']) || isset($envs[$this->environment])) { - yield new $class(); - } - } - } - - /** - * @return string[] - */ - private function getConfigurationDirectories(): iterable - { - yield $this->getProjectDir() . '/config'; - $syliusConfigDir = $this->getProjectDir() . '/config/sylius/' . SyliusKernel::MAJOR_VERSION . '.' . SyliusKernel::MINOR_VERSION; - if (is_dir($syliusConfigDir)) { - yield $syliusConfigDir; - } - $symfonyConfigDir = $this->getProjectDir() . '/config/symfony/' . BaseKernel::MAJOR_VERSION . '.' . BaseKernel::MINOR_VERSION; - if (is_dir($symfonyConfigDir)) { - yield $symfonyConfigDir; - } - } } diff --git a/tests/Application/bin/console b/tests/Application/bin/console index cbea617..8f70ac0 100755 --- a/tests/Application/bin/console +++ b/tests/Application/bin/console @@ -1,7 +1,7 @@ #!/usr/bin/env php ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], - Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true], Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Sylius\Bundle\OrderBundle\SyliusOrderBundle::class => ['all' => true], @@ -30,13 +29,7 @@ Sylius\Bundle\ReviewBundle\SyliusReviewBundle::class => ['all' => true], Sylius\Bundle\CoreBundle\SyliusCoreBundle::class => ['all' => true], Sylius\Bundle\ResourceBundle\SyliusResourceBundle::class => ['all' => true], - Setono\SyliusPartnerAdsPlugin\SetonoSyliusPartnerAdsPlugin::class => ['all' => true], Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true], - winzou\Bundle\StateMachineBundle\winzouStateMachineBundle::class => ['all' => true], - Sonata\BlockBundle\SonataBlockBundle::class => ['all' => true], - Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle::class => ['all' => true], - JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true], - FOS\RestBundle\FOSRestBundle::class => ['all' => true], Knp\Bundle\GaufretteBundle\KnpGaufretteBundle::class => ['all' => true], Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true], Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true], @@ -48,16 +41,19 @@ Sylius\Bundle\ThemeBundle\SyliusThemeBundle::class => ['all' => true], Sylius\Bundle\AdminBundle\SyliusAdminBundle::class => ['all' => true], Sylius\Bundle\ShopBundle\SyliusShopBundle::class => ['all' => true], - FOS\OAuthServerBundle\FOSOAuthServerBundle::class => ['all' => true], - Sylius\Bundle\AdminApiBundle\SyliusAdminApiBundle::class => ['all' => true], Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true, 'test_cached' => true], - Sylius\Behat\Application\SyliusTestPlugin\SyliusTestPlugin::class => ['test' => true, 'test_cached' => true], - ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], - Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle::class => ['all' => true], - Sylius\Bundle\ApiBundle\SyliusApiBundle::class => ['all' => true], SyliusLabs\DoctrineMigrationsExtraBundle\SyliusLabsDoctrineMigrationsExtraBundle::class => ['all' => true], BabDev\PagerfantaBundle\BabDevPagerfantaBundle::class => ['all' => true], - SyliusLabs\Polyfill\Symfony\Security\Bundle\SyliusLabsPolyfillSymfonySecurityBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], + League\FlysystemBundle\FlysystemBundle::class => ['all' => true], + Sylius\TwigExtra\Symfony\SyliusTwigExtraBundle::class => ['all' => true], + Sylius\TwigHooks\SyliusTwigHooksBundle::class => ['all' => true], + Symfony\UX\Icons\UXIconsBundle::class => ['all' => true], + Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true], + Symfony\UX\LiveComponent\LiveComponentBundle::class => ['all' => true], + Symfony\UX\Autocomplete\AutocompleteBundle::class => ['all' => true], + Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true], + Sylius\Abstraction\StateMachine\SyliusStateMachineAbstractionBundle::class => ['all' => true], + Setono\SyliusPartnerAdsPlugin\SetonoSyliusPartnerAdsPlugin::class => ['all' => true], ]; diff --git a/tests/Application/config/jwt/private.pem b/tests/Application/config/jwt/private.pem deleted file mode 100644 index 2bcf023..0000000 --- a/tests/Application/config/jwt/private.pem +++ /dev/null @@ -1,54 +0,0 @@ ------BEGIN ENCRYPTED PRIVATE KEY----- -MIIJrTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIDbthk+aF5EACAggA -MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBA3DYfh2mXByUxFNke/Wf5SBIIJ -UBckIgXeXBWPLQAAq07pN8uNFMUcUirFuEvbmxVe1PupCCAqriNxi1DqeSu/M7c1 -h66y0BqKZu/0G9SVTg63iCKDEiRAM3hLyD2CsjYg8h2LAaqQ9dFYGV0cHRhCXagZ -Sdt9YTfn2rarRbxauMSt0z9zwCaiUrBU4JwSM3g+tD7W0lxAm9TeaqBZek5DIX+j -3Gom5tPYQe8jvfGMGdMPuanoEwH4WbWzGcqypWriy4JwaggwKCQ4ituWfa9kqMMC -8HRmBBDg0gtafmQP910RZh18JL2ewF5Pl7GDsLtOj5gNLNuAiQxDCcYRnD4/Cdsl -bH91btmGX1nUVIFViUTW93eBsjBgdgqOMRVxUKkSSX6CmIZWlE3AazgwSbvOvNrN -JGa8X21UwfuS/JHLmfRmgdti0YxRjJkBYLPpcd3ILsi+MMhSHy0uycAM/dB80Q1B -vkW1UXGbCw/PzA5yHrzULzAl69E3Tt5nTVMIIcBGxw2rf+ej+AVjsuOl7etwecdC -gnA90ViNlGOACLVnhsjd4WVF9Oircosf0UYoblwcT6gw1GSVF9pWuu7k5hy/7Pt/ -o1BvonUgz/4VHG+K58qvtnlto+JE0XWzPvukNUyggtekTLyoQCI3ZKge6ui3qLax -N6whHpzFnFVF3GJAisTk5naHFawHNvH7t85pmc+UnjNUUmyl9RStl9LMYDSBKNlR -LzPlJK27E5SLhhyJCni4+UYjH6PdlJuKXJ0365fufJ+5ajHRatwt039xLnK0W+oa -L35NxCuXrn8YxOgJIomt7IrkV3AuxoWxcx4lRFoM0WCdn9SWZVtfFFiyX/Xr1qDg -dUysw3/bePEkOKr5JWx09hT0OKDpkwLFo2Ljtvjln4EMXYEvvVqFciKw0kqF73Dw -NyoSubwR4qs6FQclKW1TAP6UW4B6ffq1iagKOCTZ5bBtsPBZk8UGCJb57q4fUj4P -nJy0hnSdlOH4Am+US4HF4ayOGuaV1Be1taurdJnt5cNnUYRah0wg4nG+wVdG5HJk -f4dJ4nih9d6WA/8LfxdpB7NCwdR+KK6lky+GgLSdhmIT9lzjj2GDsU4lBf29TkBn -lyt98/LWGrgCQgZAQ/obxLT8CZtY+tNejGoMppY+ub8DIaLBFID+fcz13kgA9x7a -TeVB8RPok+S3yHXP9a4WSFe9DGjjN+m7EnRtte7MEjyMoekXVnT04gNbTMoGAjNb -lrR4g3ICygZtsoGSB2VEu7o3azAspXNBMOuJfRCuC0LDXcjH3TbvjX0da5wHBoK9 -clRxu+CDo9A849HMkmSje8wED7ysZnkvSX0OdPjXahVd4t1tDRI6jSlzFo9fGcjp -S8Ikm9iMrHXaWcDdtcq4C63CjSynIBr4mNIxe/f2e9nynm3AIv+aOan891RWHqrd -DdpSSPShtzATI9PbB+b+S0Gw58Y8fpO7yoZ87VW1BMpadmFZ87YY78jdB7BwInNI -JqtnivinM6qCsvbdMoGinUyL6PUcfQGiEAibouKr3zNRDC4aesBZZmj7w0dnf+HK -YC905aR0cddlc6DBo/ed3o9krMcZ6oY/vruemPTc5G7Cg3t4H3mInRgURw22X1wo -FsioU1yOdkK+MYxvmGsQvQuSJhp7h1Uz37t/olkPRafZgy2nEtw6DQO0Dm4UfSsD -nysq6dn1WeZPkOipGBRgQmY1FTRzwPoCxi7+/EuHhD8hr962rHOglSuNqPG89J8r -wdbTDr8kgXj2A9p+jI3TVKEX+h6FEhrCHW9SHUqATOZ7RiNL6hKld9j0U4D9gQwZ -dflA0TxpVsHXm7pd1idkr46jIFgw7HA89Erm0Ty7RolfHkqlRca805AVmsKkviIz -sbF5uv4WzIE3ViO8P1KMUhCyElm72mpyNTXBhkxkup9hJ4fQieaN6pET6dQ2xyjs -SBIvQoXI0JQKpespcyAdoh88ULQjRUXEOaNFfN7q+itTcocwmPZfzW2nXORJT2p8 -SXLqSE73nYZdqzSYFq1hLcnlubJ7yPBYYG1fI0IydjSGKfnjtB0DReR32OToRZ7m -laduZ8O+IaBUY4Sp6QdYcVbGGpG/wsPmTQyScc/O2bfSI7AiPnL9EnwebI9sPSWQ -R0t0QMXZOSSqNY6jkYjsOCxeekRIdY6havo2Y52Ywti0QNrkT4BQ+175VVTmRMdy -LNaMFeEq6ehSEdaHaozvjHvP50HQT43tCK+RJiL+Gf9FqawoQRt693yO5LFbQsuw -QsUSMi41txpINMa+HEc2K5FvGoPr7FmajLK7X2fr+3c/yZ4fahoMKEAVFWl5kRYx -Fe1smlw1Vxl/qNQ32LFWsBIK+XnYBteYmlpVyYrTgXyjnp1rK2zz0118DPFuYiAP -O0r6nnBz0NbwnSKb7S4CjxBKDvDbWTzP35Q5L/vySnO2zRbM64Gw7sjeLiJittWS -gQfbFpEk9k8KVndKM4H50Jp0WznmYpm1Tman8hUOiCvmq0qdI3bJ5Bnj0K+q2zFV -+noGpMFdq1+8WaUFLQFGCPM+yJgCqDgT1RAgfsGcomckGcmenDtHaTbcSFabEdpM -Tsa2qLdg/Kju+7JyGrkmobXl/azuyjYTHfRvSZrvO5WUDFzhChrJpIL4nA3ZGRlS -gvy+OzyyBh4sRyHwLItwUwE81aya3W4llAkhQ7OycmqniJgjtJzLwnxv2RQsB8bF -pyoqQdKVxkqHdbUFeh9igI4ffRAK+8xDER5J+RUoZ4mO8qJebxar54XTb6I/Lepc -g8ITX8bJ/GH+M6JdP7tLCikDTSGS+i1ReMQXE5XuEajYOVbzQdyWU5jleZIx0f6X -mTa4WvMEGNyNxKZZXsy9FAaBkZqrNzEv8k0uFgFMNWQcMMtiqbei86yACdqe+jiW -HqHv8wfoBHR+eIARub2itOJ/cI+oKv96d4it4FqQ9Lml8RUFFZj7Hrd6EjDb6Nq4 -P9ti7eku/xZvS0saBNChvv44GhP6FZJS0i/gidVffLna7Wua98tPZEAXp57k+XUL -PzsRJ4a+hFuQjkyXFoz/v8YuUdyCFUSVVr9ArVu0v4+4euFWpQLav5sXv0Gh9X58 -Ek1KIf7Z/tZAJnSjTjFuSbDX/AoTMTxpRBKKnFW6zY0Nw2pjTVMtTVDkv9xkBpBK -wod7FPD5f0T7y9YOARVZnBxVRSkkcYpEJFy5pLNeadg9 ------END ENCRYPTED PRIVATE KEY----- diff --git a/tests/Application/config/jwt/public.pem b/tests/Application/config/jwt/public.pem deleted file mode 100644 index cb4e13d..0000000 --- a/tests/Application/config/jwt/public.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6QkmF/Xi5nAYb8Kzr7qC -d63V2K+d/nCXbpDUKKDPJAqOtTlMoQSuJRLNnhhp7z1i/Cp4Bhifr20Pu2dq8JYg -6pRT4ctqvYb/MXxAaPZc3EcBC0S6AhgKO/fDvR3LcqYqGJmQQOXZvxTsgqongdvV -4XbqFBMMgngyayoBk0VKTaI/s+LQhIce+1QaxbAI0+/zbR0hZ1hWT73orJi3do+1 -TBzQol+V7WGa8LlJfmgM56qO3BmVkeTDMBc27pGp6g3+Oufk/l29jEGJlUT9yu7Q -BRhaQTWNVASa2aD+AKjVBzJh53O2zD8slAbjF1M9U7bbWN28Sv+xC/dUz0q9HnPu -RsY2tnwryqTyYn/Hf2xyP3/KvjJ6oslAwemu5JirdJkO7KVQAthWG42gLuhZg3ks -cSZhCLZH7nO2UDsf+2ZZgdbhpYZwR4gDRfNt7GKWXnWZOz9Uw1yVCPgylyZRZwg8 -l0y9aABdj3379I22icrwpMZbAgkyxNSV6UNJuxZksLUoP3i9OvXYgPYU9E4tU/Ul -Dm/T1rGSReGoPkU1YQnI50bq7p1byIoUu2scTflvpTVI5a7zULkS1tg60xk7vBRC -aBc7nr4UEtA235N6uLtcGxH11WBMwsKX69sSU0sQdC4Sk25zXM2gc8R1XV9K3qz2 -wQorQRlCwrkG44VRDgbFH+8CAwEAAQ== ------END PUBLIC KEY----- diff --git a/tests/Application/config/packages/_sylius.yaml b/tests/Application/config/packages/_sylius.yaml index 490bc2d..a3e30bb 100644 --- a/tests/Application/config/packages/_sylius.yaml +++ b/tests/Application/config/packages/_sylius.yaml @@ -1,9 +1,8 @@ imports: - { resource: "@SyliusCoreBundle/Resources/config/app/config.yml" } + - { resource: "@SyliusPayumBundle/Resources/config/app/config.yaml" } - { resource: "@SyliusAdminBundle/Resources/config/app/config.yml" } - - { resource: "@SyliusAdminApiBundle/Resources/config/app/config.yml" } - { resource: "@SyliusShopBundle/Resources/config/app/config.yml" } - - { resource: "@SyliusApiBundle/Resources/config/app/config.yaml" } parameters: sylius_core.public_dir: '%kernel.project_dir%/public' @@ -11,6 +10,3 @@ parameters: sylius_shop: product_grid: include_all_descendants: true - -sylius_api: - enabled: true diff --git a/tests/Application/config/packages/api_platform.yaml b/tests/Application/config/packages/api_platform.yaml deleted file mode 100644 index 26def49..0000000 --- a/tests/Application/config/packages/api_platform.yaml +++ /dev/null @@ -1,9 +0,0 @@ -api_platform: - mapping: - paths: - - '%kernel.project_dir%/../../vendor/sylius/sylius/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources' - - '%kernel.project_dir%/config/api_platform' - patch_formats: - json: ['application/merge-patch+json'] - swagger: - versions: [3] diff --git a/tests/Application/config/packages/dev/framework.yaml b/tests/Application/config/packages/dev/framework.yaml deleted file mode 100644 index 4b116de..0000000 --- a/tests/Application/config/packages/dev/framework.yaml +++ /dev/null @@ -1,2 +0,0 @@ -framework: - profiler: { only_exceptions: false } diff --git a/tests/Application/config/packages/dev/jms_serializer.yaml b/tests/Application/config/packages/dev/jms_serializer.yaml deleted file mode 100644 index 2f32a9b..0000000 --- a/tests/Application/config/packages/dev/jms_serializer.yaml +++ /dev/null @@ -1,12 +0,0 @@ -jms_serializer: - visitors: - json_serialization: - options: - - JSON_PRETTY_PRINT - - JSON_UNESCAPED_SLASHES - - JSON_PRESERVE_ZERO_FRACTION - json_deserialization: - options: - - JSON_PRETTY_PRINT - - JSON_UNESCAPED_SLASHES - - JSON_PRESERVE_ZERO_FRACTION diff --git a/tests/Application/config/packages/dev/monolog.yaml b/tests/Application/config/packages/dev/monolog.yaml deleted file mode 100644 index da2b092..0000000 --- a/tests/Application/config/packages/dev/monolog.yaml +++ /dev/null @@ -1,9 +0,0 @@ -monolog: - handlers: - main: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug - firephp: - type: firephp - level: info diff --git a/tests/Application/config/packages/dev/routing.yaml b/tests/Application/config/packages/dev/routing.yaml deleted file mode 100644 index 4116679..0000000 --- a/tests/Application/config/packages/dev/routing.yaml +++ /dev/null @@ -1,3 +0,0 @@ -framework: - router: - strict_requirements: true diff --git a/tests/Application/config/packages/dev/swiftmailer.yaml b/tests/Application/config/packages/dev/swiftmailer.yaml deleted file mode 100644 index f438078..0000000 --- a/tests/Application/config/packages/dev/swiftmailer.yaml +++ /dev/null @@ -1,2 +0,0 @@ -swiftmailer: - disable_delivery: true diff --git a/tests/Application/config/packages/dev/web_profiler.yaml b/tests/Application/config/packages/dev/web_profiler.yaml deleted file mode 100644 index 1f1cb2b..0000000 --- a/tests/Application/config/packages/dev/web_profiler.yaml +++ /dev/null @@ -1,3 +0,0 @@ -web_profiler: - toolbar: true - intercept_redirects: false diff --git a/tests/Application/config/packages/doctrine.yaml b/tests/Application/config/packages/doctrine.yaml index f51ba5a..e479e54 100644 --- a/tests/Application/config/packages/doctrine.yaml +++ b/tests/Application/config/packages/doctrine.yaml @@ -12,3 +12,36 @@ doctrine: charset: UTF8 url: '%env(resolve:DATABASE_URL)%' + +when@prod: + doctrine: + orm: + metadata_cache_driver: + type: service + id: doctrine.system_cache_provider + query_cache_driver: + type: service + id: doctrine.system_cache_provider + result_cache_driver: + type: service + id: doctrine.result_cache_provider + + services: + doctrine.result_cache_provider: + class: Symfony\Component\Cache\DoctrineProvider + public: false + arguments: + - '@doctrine.result_cache_pool' + doctrine.system_cache_provider: + class: Symfony\Component\Cache\DoctrineProvider + public: false + arguments: + - '@doctrine.system_cache_pool' + + framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/tests/Application/config/packages/doctrine_migrations.yaml b/tests/Application/config/packages/doctrine_migrations.yaml index cdbc01a..ec35649 100644 --- a/tests/Application/config/packages/doctrine_migrations.yaml +++ b/tests/Application/config/packages/doctrine_migrations.yaml @@ -2,3 +2,5 @@ doctrine_migrations: storage: table_storage: table_name: sylius_migrations + migrations_paths: + 'App\Migrations': '%kernel.project_dir%/../../src/Migrations/' diff --git a/tests/Application/config/packages/fos_rest.yaml b/tests/Application/config/packages/fos_rest.yaml deleted file mode 100644 index eaebb27..0000000 --- a/tests/Application/config/packages/fos_rest.yaml +++ /dev/null @@ -1,11 +0,0 @@ -fos_rest: - exception: true - view: - formats: - json: true - xml: true - empty_content: 204 - format_listener: - rules: - - { path: '^/api/v1/.*', priorities: ['json', 'xml'], fallback_format: json, prefer_extension: true } - - { path: '^/', stop: true } diff --git a/tests/Application/config/packages/framework.yaml b/tests/Application/config/packages/framework.yaml index bd82dd9..0ef6331 100644 --- a/tests/Application/config/packages/framework.yaml +++ b/tests/Application/config/packages/framework.yaml @@ -1,10 +1,24 @@ framework: - csrf_protection: true - form: true - ide: phpstorm secret: '%env(APP_SECRET)%' + ide: 'phpstorm' + form: true + csrf_protection: true session: handler_id: ~ - serializer: - mapping: - paths: [ '%kernel.project_dir%/config/serialization' ] + +when@dev: + framework: + profiler: { only_exceptions: false } + +when@test: + framework: + test: ~ + session: + storage_factory_id: session.storage.factory.mock_file + + mailer: + dsn: '%env(MAILER_DSN)%' + cache: + pools: + test.mailer_pool: + adapter: cache.adapter.filesystem diff --git a/tests/Application/config/packages/http_discovery.yaml b/tests/Application/config/packages/http_discovery.yaml new file mode 100644 index 0000000..2a789e7 --- /dev/null +++ b/tests/Application/config/packages/http_discovery.yaml @@ -0,0 +1,10 @@ +services: + Psr\Http\Message\RequestFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\ResponseFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\ServerRequestFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\StreamFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\UploadedFileFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\UriFactoryInterface: '@http_discovery.psr17_factory' + + http_discovery.psr17_factory: + class: Http\Discovery\Psr17Factory diff --git a/tests/Application/config/packages/jms_serializer.yaml b/tests/Application/config/packages/jms_serializer.yaml deleted file mode 100644 index ed7bc61..0000000 --- a/tests/Application/config/packages/jms_serializer.yaml +++ /dev/null @@ -1,4 +0,0 @@ -jms_serializer: - visitors: - xml_serialization: - format_output: '%kernel.debug%' diff --git a/tests/Application/config/packages/lexik_jwt_authentication.yaml b/tests/Application/config/packages/lexik_jwt_authentication.yaml deleted file mode 100644 index edfb69d..0000000 --- a/tests/Application/config/packages/lexik_jwt_authentication.yaml +++ /dev/null @@ -1,4 +0,0 @@ -lexik_jwt_authentication: - secret_key: '%env(resolve:JWT_SECRET_KEY)%' - public_key: '%env(resolve:JWT_PUBLIC_KEY)%' - pass_phrase: '%env(JWT_PASSPHRASE)%' diff --git a/tests/Application/config/packages/mailer.yaml b/tests/Application/config/packages/mailer.yaml new file mode 100644 index 0000000..56a650d --- /dev/null +++ b/tests/Application/config/packages/mailer.yaml @@ -0,0 +1,3 @@ +framework: + mailer: + dsn: '%env(MAILER_DSN)%' diff --git a/tests/Application/config/packages/messenger.yaml b/tests/Application/config/packages/messenger.yaml deleted file mode 100644 index b3a792f..0000000 --- a/tests/Application/config/packages/messenger.yaml +++ /dev/null @@ -1,4 +0,0 @@ -framework: - messenger: - buses: - message_bus: ~ diff --git a/tests/Application/config/packages/monolog.yaml b/tests/Application/config/packages/monolog.yaml new file mode 100644 index 0000000..73e391a --- /dev/null +++ b/tests/Application/config/packages/monolog.yaml @@ -0,0 +1,30 @@ +when@dev: + monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + firephp: + type: firephp + level: info + +when@test: + monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: error + +when@prod: + monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + nested: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug diff --git a/tests/Application/config/packages/prod/doctrine.yaml b/tests/Application/config/packages/prod/doctrine.yaml deleted file mode 100644 index 2f16f0f..0000000 --- a/tests/Application/config/packages/prod/doctrine.yaml +++ /dev/null @@ -1,31 +0,0 @@ -doctrine: - orm: - metadata_cache_driver: - type: service - id: doctrine.system_cache_provider - query_cache_driver: - type: service - id: doctrine.system_cache_provider - result_cache_driver: - type: service - id: doctrine.result_cache_provider - -services: - doctrine.result_cache_provider: - class: Symfony\Component\Cache\DoctrineProvider - public: false - arguments: - - '@doctrine.result_cache_pool' - doctrine.system_cache_provider: - class: Symfony\Component\Cache\DoctrineProvider - public: false - arguments: - - '@doctrine.system_cache_pool' - -framework: - cache: - pools: - doctrine.result_cache_pool: - adapter: cache.app - doctrine.system_cache_pool: - adapter: cache.system diff --git a/tests/Application/config/packages/prod/jms_serializer.yaml b/tests/Application/config/packages/prod/jms_serializer.yaml deleted file mode 100644 index c288182..0000000 --- a/tests/Application/config/packages/prod/jms_serializer.yaml +++ /dev/null @@ -1,10 +0,0 @@ -jms_serializer: - visitors: - json_serialization: - options: - - JSON_UNESCAPED_SLASHES - - JSON_PRESERVE_ZERO_FRACTION - json_deserialization: - options: - - JSON_UNESCAPED_SLASHES - - JSON_PRESERVE_ZERO_FRACTION diff --git a/tests/Application/config/packages/prod/monolog.yaml b/tests/Application/config/packages/prod/monolog.yaml deleted file mode 100644 index 6461211..0000000 --- a/tests/Application/config/packages/prod/monolog.yaml +++ /dev/null @@ -1,10 +0,0 @@ -monolog: - handlers: - main: - type: fingers_crossed - action_level: error - handler: nested - nested: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug diff --git a/tests/Application/config/packages/routing.yaml b/tests/Application/config/packages/routing.yaml index 368bc7f..d0c2c76 100644 --- a/tests/Application/config/packages/routing.yaml +++ b/tests/Application/config/packages/routing.yaml @@ -1,3 +1,8 @@ framework: router: - strict_requirements: ~ + strict_requirements: false + +when@dev: + framework: + router: + strict_requirements: true diff --git a/tests/Application/config/packages/security.yaml b/tests/Application/config/packages/security.yaml index 51a6ec9..c89110e 100644 --- a/tests/Application/config/packages/security.yaml +++ b/tests/Application/config/packages/security.yaml @@ -1,28 +1,11 @@ -parameters: - sylius.security.admin_regex: "^/%sylius_admin.path_name%" - sylius.security.shop_regex: "^/(?!%sylius_admin.path_name%|api/.*|api$|media/.*)[^/]++" - sylius.security.new_api_route: "/api/v2" - sylius.security.new_api_regex: "^%sylius.security.new_api_route%" - sylius.security.new_api_admin_route: "%sylius.security.new_api_route%/admin" - sylius.security.new_api_admin_regex: "^%sylius.security.new_api_admin_route%" - sylius.security.new_api_shop_route: "%sylius.security.new_api_route%/shop" - sylius.security.new_api_shop_regex: "^%sylius.security.new_api_shop_route%" - sylius.security.new_api_user_account_route: "%sylius.security.new_api_shop_route%/account" - sylius.security.new_api_user_account_regex: "^%sylius.security.new_api_user_account_route%" - security: - always_authenticate_before_granting: true providers: sylius_admin_user_provider: id: sylius.admin_user_provider.email_or_name_based - sylius_api_admin_user_provider: - id: sylius.admin_user_provider.email_or_name_based sylius_shop_user_provider: id: sylius.shop_user_provider.email_or_name_based - sylius_api_shop_user_provider: - id: sylius.shop_user_provider.email_or_name_based - encoders: + password_hashers: Sylius\Component\User\Model\UserInterface: argon2i firewalls: admin: @@ -30,6 +13,7 @@ security: context: admin pattern: "%sylius.security.admin_regex%" provider: sylius_admin_user_provider + user_checker: security.user_checker.chain.admin form_login: provider: sylius_admin_user_provider login_path: sylius_admin_login @@ -38,7 +22,7 @@ security: default_target_path: sylius_admin_dashboard use_forward: false use_referer: true - csrf_token_generator: security.csrf.token_manager + enable_csrf: true csrf_parameter: _csrf_admin_security_token csrf_token_id: admin_authenticate remember_me: @@ -50,43 +34,13 @@ security: logout: path: sylius_admin_logout target: sylius_admin_login - anonymous: true - - new_api_admin_user: - pattern: "%sylius.security.new_api_admin_regex%/.*" - provider: sylius_api_admin_user_provider - stateless: true - anonymous: true - json_login: - check_path: "%sylius.security.new_api_admin_route%/authentication-token" - username_path: email - password_path: password - success_handler: lexik_jwt_authentication.handler.authentication_success - failure_handler: lexik_jwt_authentication.handler.authentication_failure - guard: - authenticators: - - lexik_jwt_authentication.jwt_token_authenticator - - new_api_shop_user: - pattern: "%sylius.security.new_api_shop_regex%/.*" - provider: sylius_api_shop_user_provider - stateless: true - anonymous: true - json_login: - check_path: "%sylius.security.new_api_shop_route%/authentication-token" - username_path: email - password_path: password - success_handler: lexik_jwt_authentication.handler.authentication_success - failure_handler: lexik_jwt_authentication.handler.authentication_failure - guard: - authenticators: - - lexik_jwt_authentication.jwt_token_authenticator shop: switch_user: { role: ROLE_ALLOWED_TO_SWITCH } context: shop pattern: "%sylius.security.shop_regex%" provider: sylius_shop_user_provider + user_checker: security.user_checker.chain.shop form_login: success_handler: sylius.authentication.success_handler failure_handler: sylius.authentication.failure_handler @@ -97,9 +51,15 @@ security: default_target_path: sylius_shop_homepage use_forward: false use_referer: true - csrf_token_generator: security.csrf.token_manager + enable_csrf: true csrf_parameter: _csrf_shop_security_token csrf_token_id: shop_authenticate + json_login: + check_path: sylius_shop_json_login_check + username_path: _username + password_path: _password + success_handler: sylius.authentication.success_handler + failure_handler: sylius.authentication.failure_handler remember_me: secret: "%env(APP_SECRET)%" name: APP_SHOP_REMEMBER_ME @@ -107,36 +67,25 @@ security: remember_me_parameter: _remember_me logout: path: sylius_shop_logout - target: sylius_shop_login + target: sylius_shop_homepage invalidate_session: false - success_handler: sylius.handler.shop_user_logout - anonymous: true - - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ - security: false image_resolver: pattern: ^/media/cache/resolve security: false + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + access_control: - - { path: "%sylius.security.admin_regex%/_partial", role: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1] } - - { path: "%sylius.security.admin_regex%/_partial", role: ROLE_NO_ACCESS } - - { path: "%sylius.security.shop_regex%/_partial", role: IS_AUTHENTICATED_ANONYMOUSLY, ips: [127.0.0.1, ::1] } - - { path: "%sylius.security.shop_regex%/_partial", role: ROLE_NO_ACCESS } + - { path: "%sylius.security.admin_regex%/forgotten-password", role: PUBLIC_ACCESS } - - { path: "%sylius.security.admin_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: "%sylius.security.shop_regex%/login", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.admin_regex%/login", role: PUBLIC_ACCESS } + - { path: "%sylius.security.shop_regex%/login", role: PUBLIC_ACCESS } - - { path: "%sylius.security.shop_regex%/register", role: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: "%sylius.security.shop_regex%/verify", role: IS_AUTHENTICATED_ANONYMOUSLY } + - { path: "%sylius.security.shop_regex%/register", role: PUBLIC_ACCESS } + - { path: "%sylius.security.shop_regex%/verify", role: PUBLIC_ACCESS } - { path: "%sylius.security.admin_regex%", role: ROLE_ADMINISTRATION_ACCESS } - { path: "%sylius.security.shop_regex%/account", role: ROLE_USER } - - - { path: "%sylius.security.new_api_admin_regex%/.*", role: ROLE_API_ACCESS } - - { path: "%sylius.security.new_api_admin_route%/authentication-token", role: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: "%sylius.security.new_api_user_account_regex%/.*", role: ROLE_USER } - - { path: "%sylius.security.new_api_shop_route%/authentication-token", role: IS_AUTHENTICATED_ANONYMOUSLY } - - { path: "%sylius.security.new_api_shop_regex%/.*", role: IS_AUTHENTICATED_ANONYMOUSLY } diff --git a/tests/Application/config/packages/setono_sylius_partner_ads.yaml b/tests/Application/config/packages/setono_sylius_partner_ads.yaml index 1593f48..a7b6a63 100644 --- a/tests/Application/config/packages/setono_sylius_partner_ads.yaml +++ b/tests/Application/config/packages/setono_sylius_partner_ads.yaml @@ -1,6 +1,3 @@ -imports: - - { resource: "@SetonoSyliusPartnerAdsPlugin/Resources/config/app/config.yaml" } - setono_sylius_partner_ads: urls: - notify: http://127.0.0.1:8000/callback.php?programid={program_id}&type=salg&partnerid={partner_id}&userip={ip}&ordreid={order_id}&varenummer=x&antal=1&omprsalg={value} + notify: 'http://127.0.0.1:8000/callback.php?programid={program_id}&type=salg&partnerid={partner_id}&userip={ip}&ordreid={order_id}&varenummer=x&antal=1&omprsalg={value}' diff --git a/tests/Application/config/packages/staging/monolog.yaml b/tests/Application/config/packages/staging/monolog.yaml deleted file mode 100644 index 6461211..0000000 --- a/tests/Application/config/packages/staging/monolog.yaml +++ /dev/null @@ -1,10 +0,0 @@ -monolog: - handlers: - main: - type: fingers_crossed - action_level: error - handler: nested - nested: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: debug diff --git a/tests/Application/config/packages/staging/swiftmailer.yaml b/tests/Application/config/packages/staging/swiftmailer.yaml deleted file mode 100644 index f438078..0000000 --- a/tests/Application/config/packages/staging/swiftmailer.yaml +++ /dev/null @@ -1,2 +0,0 @@ -swiftmailer: - disable_delivery: true diff --git a/tests/Application/config/packages/swiftmailer.yaml b/tests/Application/config/packages/swiftmailer.yaml deleted file mode 100644 index 3bab0d3..0000000 --- a/tests/Application/config/packages/swiftmailer.yaml +++ /dev/null @@ -1,2 +0,0 @@ -swiftmailer: - url: '%env(MAILER_URL)%' diff --git a/tests/Application/config/packages/sylius_state_machine_abstraction.yaml b/tests/Application/config/packages/sylius_state_machine_abstraction.yaml new file mode 100644 index 0000000..7f43c0b --- /dev/null +++ b/tests/Application/config/packages/sylius_state_machine_abstraction.yaml @@ -0,0 +1,6 @@ +parameters: + test_default_state_machine_adapter: 'symfony_workflow' + test_sylius_state_machine_adapter: '%env(string:default:test_default_state_machine_adapter:TEST_SYLIUS_STATE_MACHINE_ADAPTER)%' + +sylius_state_machine_abstraction: + default_adapter: '%test_sylius_state_machine_adapter%' diff --git a/tests/Application/config/packages/sylius_theme.yaml b/tests/Application/config/packages/sylius_theme.yaml new file mode 100644 index 0000000..cbc95ba --- /dev/null +++ b/tests/Application/config/packages/sylius_theme.yaml @@ -0,0 +1,4 @@ +when@test: + sylius_theme: + sources: + test: ~ diff --git a/tests/Application/config/packages/test/framework.yaml b/tests/Application/config/packages/test/framework.yaml deleted file mode 100644 index 76d7e5e..0000000 --- a/tests/Application/config/packages/test/framework.yaml +++ /dev/null @@ -1,4 +0,0 @@ -framework: - test: ~ - session: - storage_id: session.storage.mock_file diff --git a/tests/Application/config/packages/test/monolog.yaml b/tests/Application/config/packages/test/monolog.yaml deleted file mode 100644 index 7e2b9e3..0000000 --- a/tests/Application/config/packages/test/monolog.yaml +++ /dev/null @@ -1,6 +0,0 @@ -monolog: - handlers: - main: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: error diff --git a/tests/Application/config/packages/test/security.yaml b/tests/Application/config/packages/test/security.yaml deleted file mode 100644 index 21cc377..0000000 --- a/tests/Application/config/packages/test/security.yaml +++ /dev/null @@ -1,3 +0,0 @@ -security: - encoders: - sha512: sha512 diff --git a/tests/Application/config/packages/test/swiftmailer.yaml b/tests/Application/config/packages/test/swiftmailer.yaml deleted file mode 100644 index c438f4b..0000000 --- a/tests/Application/config/packages/test/swiftmailer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -swiftmailer: - disable_delivery: true - logging: true - spool: - type: file - path: "%kernel.cache_dir%/spool" diff --git a/tests/Application/config/packages/test/sylius_theme.yaml b/tests/Application/config/packages/test/sylius_theme.yaml deleted file mode 100644 index 4d34199..0000000 --- a/tests/Application/config/packages/test/sylius_theme.yaml +++ /dev/null @@ -1,3 +0,0 @@ -sylius_theme: - sources: - test: ~ diff --git a/tests/Application/config/packages/test/sylius_uploader.yaml b/tests/Application/config/packages/test/sylius_uploader.yaml deleted file mode 100644 index ab9d6ca..0000000 --- a/tests/Application/config/packages/test/sylius_uploader.yaml +++ /dev/null @@ -1,3 +0,0 @@ -services: - Sylius\Component\Core\Generator\ImagePathGeneratorInterface: - class: Sylius\Behat\Service\Generator\UploadedImagePathGenerator diff --git a/tests/Application/config/packages/test/web_profiler.yaml b/tests/Application/config/packages/test/web_profiler.yaml deleted file mode 100644 index 03752de..0000000 --- a/tests/Application/config/packages/test/web_profiler.yaml +++ /dev/null @@ -1,6 +0,0 @@ -web_profiler: - toolbar: false - intercept_redirects: false - -framework: - profiler: { collect: false } diff --git a/tests/Application/config/packages/test_cached/doctrine.yaml b/tests/Application/config/packages/test_cached/doctrine.yaml deleted file mode 100644 index 4952860..0000000 --- a/tests/Application/config/packages/test_cached/doctrine.yaml +++ /dev/null @@ -1,16 +0,0 @@ -doctrine: - orm: - entity_managers: - default: - result_cache_driver: - type: memcached - host: localhost - port: 11211 - query_cache_driver: - type: memcached - host: localhost - port: 11211 - metadata_cache_driver: - type: memcached - host: localhost - port: 11211 diff --git a/tests/Application/config/packages/test_cached/fos_rest.yaml b/tests/Application/config/packages/test_cached/fos_rest.yaml deleted file mode 100644 index 2b4189d..0000000 --- a/tests/Application/config/packages/test_cached/fos_rest.yaml +++ /dev/null @@ -1,3 +0,0 @@ -fos_rest: - exception: - debug: true diff --git a/tests/Application/config/packages/test_cached/framework.yaml b/tests/Application/config/packages/test_cached/framework.yaml deleted file mode 100644 index 76d7e5e..0000000 --- a/tests/Application/config/packages/test_cached/framework.yaml +++ /dev/null @@ -1,4 +0,0 @@ -framework: - test: ~ - session: - storage_id: session.storage.mock_file diff --git a/tests/Application/config/packages/test_cached/monolog.yaml b/tests/Application/config/packages/test_cached/monolog.yaml deleted file mode 100644 index 7e2b9e3..0000000 --- a/tests/Application/config/packages/test_cached/monolog.yaml +++ /dev/null @@ -1,6 +0,0 @@ -monolog: - handlers: - main: - type: stream - path: "%kernel.logs_dir%/%kernel.environment%.log" - level: error diff --git a/tests/Application/config/packages/test_cached/security.yaml b/tests/Application/config/packages/test_cached/security.yaml deleted file mode 100644 index 21cc377..0000000 --- a/tests/Application/config/packages/test_cached/security.yaml +++ /dev/null @@ -1,3 +0,0 @@ -security: - encoders: - sha512: sha512 diff --git a/tests/Application/config/packages/test_cached/swiftmailer.yaml b/tests/Application/config/packages/test_cached/swiftmailer.yaml deleted file mode 100644 index c438f4b..0000000 --- a/tests/Application/config/packages/test_cached/swiftmailer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -swiftmailer: - disable_delivery: true - logging: true - spool: - type: file - path: "%kernel.cache_dir%/spool" diff --git a/tests/Application/config/packages/test_cached/sylius_channel.yaml b/tests/Application/config/packages/test_cached/sylius_channel.yaml deleted file mode 100644 index bab83ef..0000000 --- a/tests/Application/config/packages/test_cached/sylius_channel.yaml +++ /dev/null @@ -1,2 +0,0 @@ -sylius_channel: - debug: true diff --git a/tests/Application/config/packages/test_cached/sylius_theme.yaml b/tests/Application/config/packages/test_cached/sylius_theme.yaml deleted file mode 100644 index 4d34199..0000000 --- a/tests/Application/config/packages/test_cached/sylius_theme.yaml +++ /dev/null @@ -1,3 +0,0 @@ -sylius_theme: - sources: - test: ~ diff --git a/tests/Application/config/packages/test_cached/sylius_uploader.yaml b/tests/Application/config/packages/test_cached/sylius_uploader.yaml deleted file mode 100644 index 21cc377..0000000 --- a/tests/Application/config/packages/test_cached/sylius_uploader.yaml +++ /dev/null @@ -1,3 +0,0 @@ -security: - encoders: - sha512: sha512 diff --git a/tests/Application/config/packages/test_cached/twig.yaml b/tests/Application/config/packages/test_cached/twig.yaml deleted file mode 100644 index 8c6e0b4..0000000 --- a/tests/Application/config/packages/test_cached/twig.yaml +++ /dev/null @@ -1,2 +0,0 @@ -twig: - strict_variables: true diff --git a/tests/Application/config/packages/validator.yaml b/tests/Application/config/packages/validator.yaml index 61807db..a695e1a 100644 --- a/tests/Application/config/packages/validator.yaml +++ b/tests/Application/config/packages/validator.yaml @@ -1,3 +1,3 @@ framework: validation: - enable_annotations: true + email_validation_mode: html5 diff --git a/tests/Application/config/packages/web_profiler.yaml b/tests/Application/config/packages/web_profiler.yaml new file mode 100644 index 0000000..da7b532 --- /dev/null +++ b/tests/Application/config/packages/web_profiler.yaml @@ -0,0 +1,12 @@ +when@dev: + web_profiler: + toolbar: true + intercept_redirects: false + +when@test: + web_profiler: + toolbar: false + intercept_redirects: false + + framework: + profiler: { collect: false } diff --git a/tests/Application/config/packages/workflow.yaml b/tests/Application/config/packages/workflow.yaml new file mode 100644 index 0000000..2a716ff --- /dev/null +++ b/tests/Application/config/packages/workflow.yaml @@ -0,0 +1,2 @@ +framework: + workflows: ~ diff --git a/tests/Application/config/routes.yaml b/tests/Application/config/routes.yaml deleted file mode 100644 index e808adc..0000000 --- a/tests/Application/config/routes.yaml +++ /dev/null @@ -1,2 +0,0 @@ -setono_partner_ads_plugin: - resource: "@SetonoSyliusPartnerAdsPlugin/Resources/config/routing.yaml" diff --git a/tests/Application/config/routes/dev/twig.yaml b/tests/Application/config/routes/dev/twig.yaml deleted file mode 100644 index f4ee839..0000000 --- a/tests/Application/config/routes/dev/twig.yaml +++ /dev/null @@ -1,3 +0,0 @@ -_errors: - resource: '@TwigBundle/Resources/config/routing/errors.xml' - prefix: /_error diff --git a/tests/Application/config/routes/dev/web_profiler.yaml b/tests/Application/config/routes/dev/web_profiler.yaml deleted file mode 100644 index 3e79dc2..0000000 --- a/tests/Application/config/routes/dev/web_profiler.yaml +++ /dev/null @@ -1,7 +0,0 @@ -_wdt: - resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" - prefix: /_wdt - -_profiler: - resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" - prefix: /_profiler diff --git a/tests/Application/config/routes/setono_sylius_partner_ads.yaml b/tests/Application/config/routes/setono_sylius_partner_ads.yaml new file mode 100644 index 0000000..485b317 --- /dev/null +++ b/tests/Application/config/routes/setono_sylius_partner_ads.yaml @@ -0,0 +1,2 @@ +setono_sylius_partner_ads: + resource: "@SetonoSyliusPartnerAdsPlugin/config/routes.yaml" diff --git a/tests/Application/config/routes/sylius_admin.yaml b/tests/Application/config/routes/sylius_admin.yaml index 1ba48d6..b9c12c2 100644 --- a/tests/Application/config/routes/sylius_admin.yaml +++ b/tests/Application/config/routes/sylius_admin.yaml @@ -1,3 +1,3 @@ sylius_admin: resource: "@SyliusAdminBundle/Resources/config/routing.yml" - prefix: /admin + prefix: '/%sylius_admin.path_name%' diff --git a/tests/Application/config/routes/sylius_admin_api.yaml b/tests/Application/config/routes/sylius_admin_api.yaml deleted file mode 100644 index 80aed45..0000000 --- a/tests/Application/config/routes/sylius_admin_api.yaml +++ /dev/null @@ -1,3 +0,0 @@ -sylius_admin_api: - resource: "@SyliusAdminApiBundle/Resources/config/routing.yml" - prefix: /api diff --git a/tests/Application/config/routes/sylius_api.yaml b/tests/Application/config/routes/sylius_api.yaml deleted file mode 100644 index ae01ffc..0000000 --- a/tests/Application/config/routes/sylius_api.yaml +++ /dev/null @@ -1,3 +0,0 @@ -sylius_api: - resource: "@SyliusApiBundle/Resources/config/routing.yml" - prefix: "%sylius.security.new_api_route%" diff --git a/tests/Application/config/routes/sylius_shop.yaml b/tests/Application/config/routes/sylius_shop.yaml index 92eeae0..8e3dd42 100644 --- a/tests/Application/config/routes/sylius_shop.yaml +++ b/tests/Application/config/routes/sylius_shop.yaml @@ -5,10 +5,22 @@ sylius_shop: _locale: ^[A-Za-z]{2,4}(_([A-Za-z]{4}|[0-9]{3}))?(_([A-Za-z]{2}|[0-9]{3}))?$ sylius_shop_payum: - resource: "@SyliusShopBundle/Resources/config/routing/payum.yml" + resource: "@SyliusPayumBundle/Resources/config/routing/integrations/sylius_shop.yaml" + +sylius_payment_notify: + resource: "@SyliusPaymentBundle/Resources/config/routing/integrations/sylius.yaml" sylius_shop_default_locale: path: / methods: [GET] defaults: - _controller: sylius.controller.shop.locale_switch:switchAction + _controller: sylius_shop.controller.locale_switch::switchAction + +# see https://web.dev/change-password-url/ +sylius_shop_request_password_reset_token_redirect: + path: /.well-known/change-password + methods: [GET] + controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::redirectAction + defaults: + route: sylius_shop_request_password_reset_token + permanent: false diff --git a/tests/Application/config/routes/web_profiler.yaml b/tests/Application/config/routes/web_profiler.yaml new file mode 100644 index 0000000..e15ab24 --- /dev/null +++ b/tests/Application/config/routes/web_profiler.yaml @@ -0,0 +1,8 @@ +when@dev: + _wdt: + resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" + prefix: /_wdt + + _profiler: + resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" + prefix: /_profiler diff --git a/tests/Application/config/services.yaml b/tests/Application/config/services.yaml index a4a0d81..4e4ed8c 100644 --- a/tests/Application/config/services.yaml +++ b/tests/Application/config/services.yaml @@ -4,8 +4,12 @@ parameters: locale: en_US services: - Tests\Setono\SyliusPartnerAdsPlugin\Application\Client\Client: - decorates: setono_sylius_partner_ads.client.default + # Replace the real Partner Ads HTTP client with a logging test double so the test + # application never makes real outbound requests. + Setono\SyliusPartnerAdsPlugin\Tests\Application\Client\Client: arguments: - - '@setono_sylius_partner_ads.url_provider.notify' + - '@Setono\SyliusPartnerAdsPlugin\UrlProvider\NotifyUrlProviderInterface' - '@logger' + + Setono\SyliusPartnerAdsPlugin\Client\ClientInterface: + alias: Setono\SyliusPartnerAdsPlugin\Tests\Application\Client\Client diff --git a/tests/Application/package.json b/tests/Application/package.json index e990ba4..bdebb61 100644 --- a/tests/Application/package.json +++ b/tests/Application/package.json @@ -1,30 +1,20 @@ { - "dependencies": { - "chart.js": "^2.9", - "jquery": "^3.6", - "jquery.dirtyforms": "^2.0", - "lightbox2": "^2.9", - "semantic-ui-css": "^2.2", - "slick-carousel": "^1.8" - }, - "devDependencies": { - "@symfony/webpack-encore": "^1.8", - "eslint": "^8.18", - "eslint-config-airbnb-base": "^15.0", - "eslint-import-resolver-babel-module": "^5.3", - "eslint-plugin-import": "^2.26", - "node-sass": "^7.0", - "sass-loader": "^12.0" - }, + "license": "UNLICENSED", "scripts": { - "dev": "encore dev", - "build": "encore production", + "build": "encore dev", + "build:prod": "encore production", "watch": "encore dev --watch" }, - "repository": { - "type": "git", - "url": "git+https://github.com/Sylius/Sylius.git" + "dependencies": { + "@sylius-ui/admin": "file:../../vendor/sylius/sylius/src/Sylius/Bundle/AdminBundle", + "@sylius-ui/shop": "file:../../vendor/sylius/sylius/src/Sylius/Bundle/ShopBundle", + "@symfony/ux-autocomplete": "file:../../vendor/symfony/ux-autocomplete/assets", + "@symfony/ux-live-component": "file:../../vendor/symfony/ux-live-component/assets" }, - "author": "Paweł Jędrzejewski", - "license": "MIT" + "devDependencies": { + "@hotwired/stimulus": "^3.0.0", + "@symfony/stimulus-bridge": "^3.2.0", + "@symfony/webpack-encore": "^5.0.1", + "tom-select": "^2.2.2" + } } diff --git a/tests/Application/public/callback.php b/tests/Application/public/callback.php index b121500..f100e1f 100644 --- a/tests/Application/public/callback.php +++ b/tests/Application/public/callback.php @@ -1,4 +1,5 @@ get('router'); + $routes = $router->getRouteCollection(); + + // The presence of these routes proves the `type: sylius.resource` routing resolves, + // which in turn requires the resource and its referenced grid to be registered. + self::assertNotNull( + $routes->get('setono_sylius_partner_ads_admin_program_index'), + 'The admin program index route should be registered through the sylius.resource routing.', + ); + self::assertNotNull($routes->get('setono_sylius_partner_ads_admin_program_create')); + self::assertNotNull($routes->get('setono_sylius_partner_ads_admin_program_update')); + } +} diff --git a/tests/PHPStan/console_application.php b/tests/PHPStan/console_application.php new file mode 100644 index 0000000..627de93 --- /dev/null +++ b/tests/PHPStan/console_application.php @@ -0,0 +1,13 @@ +boot(); + +return new Application($kernel); diff --git a/tests/PHPStan/object_manager.php b/tests/PHPStan/object_manager.php new file mode 100644 index 0000000..c85b681 --- /dev/null +++ b/tests/PHPStan/object_manager.php @@ -0,0 +1,13 @@ +boot(); + +/** @phpstan-ignore method.notFound,method.nonObject */ +return $kernel->getContainer()->get('doctrine')->getManager(); diff --git a/tests/Unit/Calculator/OrderTotalCalculatorTest.php b/tests/Unit/Calculator/OrderTotalCalculatorTest.php new file mode 100644 index 0000000..ecdcb09 --- /dev/null +++ b/tests/Unit/Calculator/OrderTotalCalculatorTest.php @@ -0,0 +1,36 @@ + 0, 'shipping' => 0, 'expected' => 0.0], + ['total' => 10, 'shipping' => 9, 'expected' => 0.01], + ['total' => 123456, 'shipping' => 1245, 'expected' => 1222.11], + ]; + + foreach ($tests as $test) { + $order = $this->prophesize(OrderInterface::class); + $order->getTotal()->willReturn($test['total']); + $order->getShippingTotal()->willReturn($test['shipping']); + + self::assertSame($test['expected'], $calculator->get($order->reveal())); + } + } +} diff --git a/tests/Unit/Client/ClientTest.php b/tests/Unit/Client/ClientTest.php new file mode 100644 index 0000000..01b402f --- /dev/null +++ b/tests/Unit/Client/ClientTest.php @@ -0,0 +1,52 @@ +prophesize(HttpClientInterface::class); + $requestFactory = $this->prophesize(RequestFactoryInterface::class); + $notifyUrlProvider = $this->prophesize(NotifyUrlProviderInterface::class); + $request = $this->prophesize(RequestInterface::class); + $response = $this->prophesize(ResponseInterface::class); + $stream = $this->prophesize(StreamInterface::class); + + $notifyUrlProvider->provide(Argument::cetera())->willReturn($url); + $requestFactory->createRequest('GET', $url)->willReturn($request->reveal()); + + $stream->__toString()->willReturn('OK'); + $response->getStatusCode()->willReturn(200); + $response->getBody()->willReturn($stream->reveal()); + + $httpClient->sendRequest($request->reveal())->willReturn($response->reveal())->shouldBeCalled(); + + $client = new Client( + $httpClient->reveal(), + $requestFactory->reveal(), + $notifyUrlProvider->reveal(), + ); + + $client->notify(123, 'order-123', 123.123, 123, '123.456.789.000'); + } +} diff --git a/tests/CookieHandler/CookieHandlerTest.php b/tests/Unit/CookieHandler/CookieHandlerTest.php similarity index 67% rename from tests/CookieHandler/CookieHandlerTest.php rename to tests/Unit/CookieHandler/CookieHandlerTest.php index e4b2557..34446a7 100644 --- a/tests/CookieHandler/CookieHandlerTest.php +++ b/tests/Unit/CookieHandler/CookieHandlerTest.php @@ -2,8 +2,9 @@ declare(strict_types=1); -namespace Tests\Setono\SyliusPartnerAdsPlugin\CookieHandler; +namespace Setono\SyliusPartnerAdsPlugin\Tests\Unit\CookieHandler; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Setono\SyliusPartnerAdsPlugin\CookieHandler\CookieHandler; use Symfony\Component\HttpFoundation\Request; @@ -11,15 +12,13 @@ final class CookieHandlerTest extends TestCase { - private $name = 'name'; + private string $name = 'name'; - private $expire = 40; + private int $expire = 40; - private $partnerId = 1234; + private int $partnerId = 1234; - /** - * @test - */ + #[Test] public function it_sets(): void { $response = new Response(); @@ -27,21 +26,19 @@ public function it_sets(): void $cookies = $response->headers->getCookies(); - $this->assertCount(1, $cookies); + self::assertCount(1, $cookies); $cookie = $cookies[0]; - $this->assertSame($this->name, $cookie->getName()); - $this->assertSame($this->partnerId, (int) $cookie->getValue()); + self::assertSame($this->name, $cookie->getName()); + self::assertSame($this->partnerId, (int) $cookie->getValue()); $expireInDays = (int) ceil(($cookie->getExpiresTime() - time()) / 60 / 60 / 24); - $this->assertSame($this->expire, $expireInDays); + self::assertSame($this->expire, $expireInDays); } - /** - * @test - */ + #[Test] public function it_removes(): void { $response = new Response(); @@ -51,17 +48,15 @@ public function it_removes(): void $cookies = $response->headers->getCookies(); - $this->assertCount(1, $cookies); + self::assertCount(1, $cookies); $cookie = $cookies[0]; - $this->assertSame($this->name, $cookie->getName()); - $this->assertNull($cookie->getValue()); + self::assertSame($this->name, $cookie->getName()); + self::assertNull($cookie->getValue()); } - /** - * @test - */ + #[Test] public function it_gets_the_value(): void { $cookieHandler = $this->createCookieHandler(new Response()); @@ -69,29 +64,25 @@ public function it_gets_the_value(): void $value = $cookieHandler->get($request); - $this->assertSame($this->partnerId, $value); + self::assertSame($this->partnerId, $value); } - /** - * @test - */ + #[Test] public function it_returns_true_if_cookie_is_set(): void { $cookieHandler = $this->createCookieHandler(new Response()); $request = $this->createRequest(); - $this->assertTrue($cookieHandler->has($request)); + self::assertTrue($cookieHandler->has($request)); } - /** - * @test - */ + #[Test] public function it_returns_false_if_cookie_is_not_set(): void { $cookieHandler = $this->createCookieHandler(new Response()); $request = $this->createRequest('doesnotexist'); - $this->assertFalse($cookieHandler->has($request)); + self::assertFalse($cookieHandler->has($request)); } private function createCookieHandler(Response $response): CookieHandler @@ -102,7 +93,7 @@ private function createCookieHandler(Response $response): CookieHandler return $cookieHandler; } - private function createRequest(string $name = null): Request + private function createRequest(?string $name = null): Request { return new Request([], [], [], [ $name ?? $this->name => $this->partnerId, diff --git a/tests/DependencyInjection/Compiler/RegisterCommandBusPassTest.php b/tests/Unit/DependencyInjection/Compiler/RegisterCommandBusPassTest.php similarity index 82% rename from tests/DependencyInjection/Compiler/RegisterCommandBusPassTest.php rename to tests/Unit/DependencyInjection/Compiler/RegisterCommandBusPassTest.php index f25d19e..90fffbd 100644 --- a/tests/DependencyInjection/Compiler/RegisterCommandBusPassTest.php +++ b/tests/Unit/DependencyInjection/Compiler/RegisterCommandBusPassTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace Tests\Setono\SyliusPartnerAdsPlugin\DependencyInjection; +namespace Setono\SyliusPartnerAdsPlugin\Tests\Unit\DependencyInjection\Compiler; use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractCompilerPassTestCase; +use PHPUnit\Framework\Attributes\Test; use Setono\SyliusPartnerAdsPlugin\DependencyInjection\Compiler\RegisterCommandBusPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Messenger\MessageBus; @@ -16,10 +17,8 @@ protected function registerCompilerPass(ContainerBuilder $container): void $container->addCompilerPass(new RegisterCommandBusPass()); } - /** - * @test - */ - public function command_bus_service_exists() + #[Test] + public function command_bus_service_exists(): void { $this->setParameter('setono_sylius_partner_ads.messenger.command_bus', 'message_bus'); $this->registerService('message_bus', MessageBus::class); diff --git a/tests/DependencyInjection/Compiler/RegisterHttpClientPassTest.php b/tests/Unit/DependencyInjection/Compiler/RegisterHttpClientPassTest.php similarity index 90% rename from tests/DependencyInjection/Compiler/RegisterHttpClientPassTest.php rename to tests/Unit/DependencyInjection/Compiler/RegisterHttpClientPassTest.php index f3ea7c3..8418d1c 100644 --- a/tests/DependencyInjection/Compiler/RegisterHttpClientPassTest.php +++ b/tests/Unit/DependencyInjection/Compiler/RegisterHttpClientPassTest.php @@ -2,10 +2,11 @@ declare(strict_types=1); -namespace Tests\Setono\SyliusPartnerAdsPlugin\DependencyInjection; +namespace Setono\SyliusPartnerAdsPlugin\Tests\Unit\DependencyInjection\Compiler; use Buzz\Client\Curl; use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractCompilerPassTestCase; +use PHPUnit\Framework\Attributes\Test; use Setono\SyliusPartnerAdsPlugin\DependencyInjection\Compiler\RegisterHttpClientPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; @@ -17,9 +18,7 @@ protected function registerCompilerPass(ContainerBuilder $container): void $container->addCompilerPass(new RegisterHttpClientPass()); } - /** - * @test - */ + #[Test] public function http_client_service_is_registered(): void { $this->setParameter('setono_sylius_partner_ads.http_client', 'http_client'); @@ -30,9 +29,7 @@ public function http_client_service_is_registered(): void $this->assertContainerBuilderHasService('setono_sylius_partner_ads.http_client', Curl::class); } - /** - * @test - */ + #[Test] public function throws_exception_if_http_client_service_does_not_exist(): void { $this->setParameter('setono_sylius_partner_ads.http_client', 'http_client'); @@ -42,9 +39,7 @@ public function throws_exception_if_http_client_service_does_not_exist(): void $this->compile(); } - /** - * @test - */ + #[Test] public function autoregister_http_client_if_buzz_is_present(): void { $this->setParameter('setono_sylius_partner_ads.http_client', null); diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php similarity index 79% rename from tests/DependencyInjection/ConfigurationTest.php rename to tests/Unit/DependencyInjection/ConfigurationTest.php index cfb8dc0..6d499fd 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace Tests\Setono\SyliusPartnerAdsPlugin\DependencyInjection; +namespace Setono\SyliusPartnerAdsPlugin\Tests\Unit\DependencyInjection; use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\TestCase; use Setono\SyliusPartnerAdsPlugin\DependencyInjection\Configuration; @@ -17,10 +18,8 @@ protected function getConfiguration(): Configuration return new Configuration(); } - /** - * @test - */ - public function processes_configuration(): void + #[Test] + public function it_processes_configuration(): void { $this->assertConfigurationIsValid([ [ diff --git a/tests/DependencyInjection/SetonoSyliusPartnerAdsExtensionTest.php b/tests/Unit/DependencyInjection/SetonoSyliusPartnerAdsExtensionTest.php similarity index 81% rename from tests/DependencyInjection/SetonoSyliusPartnerAdsExtensionTest.php rename to tests/Unit/DependencyInjection/SetonoSyliusPartnerAdsExtensionTest.php index bd01913..bc8a116 100644 --- a/tests/DependencyInjection/SetonoSyliusPartnerAdsExtensionTest.php +++ b/tests/Unit/DependencyInjection/SetonoSyliusPartnerAdsExtensionTest.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace Tests\Setono\SyliusPartnerAdsPlugin\DependencyInjection; +namespace Setono\SyliusPartnerAdsPlugin\Tests\Unit\DependencyInjection; use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase; +use PHPUnit\Framework\Attributes\Test; use Setono\SyliusPartnerAdsPlugin\DependencyInjection\SetonoSyliusPartnerAdsExtension; final class SetonoSyliusPartnerAdsExtensionTest extends AbstractExtensionTestCase @@ -14,10 +15,8 @@ protected function getContainerExtensions(): array return [new SetonoSyliusPartnerAdsExtension()]; } - /** - * @test - */ - public function after_loading_the_correct_parameter_has_been_set() + #[Test] + public function after_loading_the_correct_parameter_has_been_set(): void { $this->load(); diff --git a/tests/Unit/EventListener/NotifySubscriberTest.php b/tests/Unit/EventListener/NotifySubscriberTest.php new file mode 100644 index 0000000..192ee0e --- /dev/null +++ b/tests/Unit/EventListener/NotifySubscriberTest.php @@ -0,0 +1,108 @@ +prophesize(MessageBusInterface::class); + $cookieHandler = $this->prophesize(CookieHandlerInterface::class); + $orderTotalCalculator = $this->prophesize(OrderTotalCalculatorInterface::class); + $programContext = $this->prophesize(ProgramContextInterface::class); + $orderRepository = $this->prophesize(OrderRepositoryInterface::class); + $order = $this->prophesize(OrderInterface::class); + $program = $this->prophesize(ProgramInterface::class); + + $session = new Session(new MockArraySessionStorage()); + $session->set('sylius_order_id', 123); + + $request = new Request(); + $request->attributes->set('_route', 'sylius_shop_order_thank_you'); + $request->setSession($session); + + $event = new RequestEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MAIN_REQUEST, + ); + + $orderRepository->find(123)->willReturn($order->reveal()); + $order->getNumber()->willReturn('000000123'); + $cookieHandler->has($request)->willReturn(true); + $cookieHandler->get($request)->willReturn(123); + $programContext->getProgram()->willReturn($program->reveal()); + $program->getProgramId()->willReturn(1234); + $orderTotalCalculator->get($order->reveal())->willReturn(199.0); + + $messageBus->dispatch(Argument::type(Notify::class)) + ->willReturn(new Envelope(new \stdClass())) + ->shouldBeCalled(); + + $subscriber = new NotifySubscriber( + $messageBus->reveal(), + $cookieHandler->reveal(), + $orderTotalCalculator->reveal(), + $programContext->reveal(), + $orderRepository->reveal(), + ); + + $subscriber->notify($event); + } + + #[Test] + public function it_does_nothing_when_the_route_is_not_the_thank_you_page(): void + { + $messageBus = $this->prophesize(MessageBusInterface::class); + $cookieHandler = $this->prophesize(CookieHandlerInterface::class); + $orderTotalCalculator = $this->prophesize(OrderTotalCalculatorInterface::class); + $programContext = $this->prophesize(ProgramContextInterface::class); + $orderRepository = $this->prophesize(OrderRepositoryInterface::class); + + $request = new Request(); + $request->attributes->set('_route', 'sylius_shop_homepage'); + + $event = new RequestEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + HttpKernelInterface::MAIN_REQUEST, + ); + + $messageBus->dispatch(Argument::any())->shouldNotBeCalled(); + + $subscriber = new NotifySubscriber( + $messageBus->reveal(), + $cookieHandler->reveal(), + $orderTotalCalculator->reveal(), + $programContext->reveal(), + $orderRepository->reveal(), + ); + + $subscriber->notify($event); + } +} diff --git a/tests/Unit/EventListener/SetCookieSubscriberTest.php b/tests/Unit/EventListener/SetCookieSubscriberTest.php new file mode 100644 index 0000000..4830a14 --- /dev/null +++ b/tests/Unit/EventListener/SetCookieSubscriberTest.php @@ -0,0 +1,92 @@ +prophesize(CookieHandlerInterface::class); + + $request = new Request([self::PARAM => '123']); + $event = $this->createEvent($request, HttpKernelInterface::SUB_REQUEST); + + $cookieHandler->set(Argument::cetera())->shouldNotBeCalled(); + + $this->createSubscriber($cookieHandler->reveal())->setCookie($event); + } + + #[Test] + public function it_does_nothing_for_xml_http_requests(): void + { + $cookieHandler = $this->prophesize(CookieHandlerInterface::class); + + $request = new Request([self::PARAM => '123']); + $request->headers->set('X-Requested-With', 'XMLHttpRequest'); + $event = $this->createEvent($request, HttpKernelInterface::MAIN_REQUEST); + + $cookieHandler->set(Argument::cetera())->shouldNotBeCalled(); + + $this->createSubscriber($cookieHandler->reveal())->setCookie($event); + } + + #[Test] + public function it_does_nothing_when_the_query_parameter_is_not_set(): void + { + $cookieHandler = $this->prophesize(CookieHandlerInterface::class); + + $request = new Request(); + $event = $this->createEvent($request, HttpKernelInterface::MAIN_REQUEST); + + $cookieHandler->set(Argument::cetera())->shouldNotBeCalled(); + + $this->createSubscriber($cookieHandler->reveal())->setCookie($event); + } + + #[Test] + public function it_sets_the_cookie(): void + { + $cookieHandler = $this->prophesize(CookieHandlerInterface::class); + + $request = new Request([self::PARAM => '123']); + $response = new Response(); + $event = $this->createEvent($request, HttpKernelInterface::MAIN_REQUEST, $response); + + $cookieHandler->set($response, 123)->shouldBeCalled(); + + $this->createSubscriber($cookieHandler->reveal())->setCookie($event); + } + + private function createSubscriber(CookieHandlerInterface $cookieHandler): SetCookieSubscriber + { + return new SetCookieSubscriber($cookieHandler, self::PARAM); + } + + private function createEvent(Request $request, int $requestType, ?Response $response = null): ResponseEvent + { + return new ResponseEvent( + $this->prophesize(HttpKernelInterface::class)->reveal(), + $request, + $requestType, + $response ?? new Response(), + ); + } +} diff --git a/tests/Unit/UrlProvider/NotifyUrlProviderTest.php b/tests/Unit/UrlProvider/NotifyUrlProviderTest.php new file mode 100644 index 0000000..a818a8b --- /dev/null +++ b/tests/Unit/UrlProvider/NotifyUrlProviderTest.php @@ -0,0 +1,41 @@ +provide($programId, $orderId, $value, $partnerId, $ip)); + } + + #[Test] + public function it_throws_an_exception_when_a_variable_is_missing(): void + { + $provider = new NotifyUrlProvider(''); + + $this->expectException(MissingVariableInUrlException::class); + + $provider->provide(123, '123', 123.123, 123, '123'); + } +} diff --git a/src/Resources/translations/messages.da.yaml b/translations/messages.da.yaml similarity index 100% rename from src/Resources/translations/messages.da.yaml rename to translations/messages.da.yaml diff --git a/src/Resources/translations/messages.en.yaml b/translations/messages.en.yaml similarity index 100% rename from src/Resources/translations/messages.en.yaml rename to translations/messages.en.yaml diff --git a/src/Resources/translations/validators.da.yaml b/translations/validators.da.yaml similarity index 100% rename from src/Resources/translations/validators.da.yaml rename to translations/validators.da.yaml diff --git a/src/Resources/translations/validators.en.yaml b/translations/validators.en.yaml similarity index 100% rename from src/Resources/translations/validators.en.yaml rename to translations/validators.en.yaml From dd6037068610ab641c6fae667c81dd6c0bd6015f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20L=C3=B8vgaard?= Date: Mon, 15 Jun 2026 12:02:01 +0200 Subject: [PATCH 2/4] Fix CI - phpunit.xml.dist: restore the intended config (unit/functional test suites + coverage filter); the previous commit accidentally kept the old single-suite config, which broke code coverage - phpstan: drop doctrine objectManagerLoader (align with the skeleton); it booted a second kernel that failed under the static-analysis action - composer-dependency-analyser: disable reporting of unmatched ignores (the sylius split-package ignores are resolution-dependent) - add an (empty) templates/ directory so lint:twig has a target - mark the backwards-compatibility job non-blocking for the major upgrade --- .github/workflows/build.yaml | 4 ++++ composer-dependency-analyser.php | 3 +++ phpstan.neon | 1 - phpunit.xml.dist | 22 +++++++++++++--------- templates/.gitignore | 0 5 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 templates/.gitignore diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 747e983..a63394b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -9,6 +9,10 @@ jobs: backwards-compatibility: runs-on: "ubuntu-latest" if: "github.event_name == 'pull_request'" + # Non-blocking for the 1.x -> 2.x major upgrade: there is no 2.0 baseline to compare against yet + # (and the pre-2.0 base branch can no longer be installed because of api-platform/core advisories). + # Re-enable blocking by removing this line once 2.0 has been released. + continue-on-error: true steps: - uses: "setono/sylius-plugin/backwards-compatibility@v2" diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php index 0d11009..6d47a69 100644 --- a/composer-dependency-analyser.php +++ b/composer-dependency-analyser.php @@ -6,6 +6,9 @@ use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType; return (new Configuration()) + // The Sylius split-package ignores below only apply when sylius/sylius (which "replace"s them) is the + // installed provider; depending on how dependencies resolve they may not match, which is fine. + ->disableReportingUnmatchedIgnores() // Scan the PHP service configuration so symbols only referenced there (e.g. nyholm/psr7) are detected. ->addPathToScan(__DIR__ . '/config', false) ->addPathToExclude(__DIR__ . '/tests') diff --git a/phpstan.neon b/phpstan.neon index f124191..5f92dce 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -18,7 +18,6 @@ parameters: # Doctrine Configuration doctrine: repositoryClass: Doctrine\ORM\EntityRepository - objectManagerLoader: tests/PHPStan/object_manager.php reportUnmatchedIgnoredErrors: false treatPhpDocTypesAsCertain: false diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 557e77e..d77f3ca 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,18 +1,22 @@ - + xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" colors="true" + bootstrap="tests/Application/config/bootstrap.php" cacheDirectory=".phpunit.cache"> - - tests + + tests/Unit + + + tests/Functional - - - + + + + src/ + + diff --git a/templates/.gitignore b/templates/.gitignore new file mode 100644 index 0000000..e69de29 From eb05ecef16a941d646e96def421b39311a8c1810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20L=C3=B8vgaard?= Date: Mon, 15 Jun 2026 12:09:36 +0200 Subject: [PATCH 3/4] Fix dependency analysis and drop BC job for the major upgrade - composer-dependency-analyser: ignore the optional Buzz classes as unknown (kriswallsmith/buzz is not installed when only production dependencies are analysed) - remove the backwards-compatibility CI job for the 1.x -> 2.x upgrade (no 2.0 baseline yet; re-add after 2.0 is released) --- .github/workflows/build.yaml | 18 +++++++++--------- composer-dependency-analyser.php | 7 ++++++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a63394b..c059edd 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,15 +6,15 @@ on: workflow_dispatch: ~ jobs: - backwards-compatibility: - runs-on: "ubuntu-latest" - if: "github.event_name == 'pull_request'" - # Non-blocking for the 1.x -> 2.x major upgrade: there is no 2.0 baseline to compare against yet - # (and the pre-2.0 base branch can no longer be installed because of api-platform/core advisories). - # Re-enable blocking by removing this line once 2.0 has been released. - continue-on-error: true - steps: - - uses: "setono/sylius-plugin/backwards-compatibility@v2" + # NOTE: the backwards-compatibility job has been removed for the 1.x -> 2.x major upgrade. There is no + # 2.0 baseline to compare against yet and a major release intentionally breaks BC. Re-add it once 2.0 + # has been released: + # + # backwards-compatibility: + # runs-on: "ubuntu-latest" + # if: "github.event_name == 'pull_request'" + # steps: + # - uses: "setono/sylius-plugin/backwards-compatibility@v2" coding-standards: runs-on: "ubuntu-latest" diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php index 6d47a69..9e53402 100644 --- a/composer-dependency-analyser.php +++ b/composer-dependency-analyser.php @@ -13,8 +13,13 @@ ->addPathToScan(__DIR__ . '/config', false) ->addPathToExclude(__DIR__ . '/tests') // Buzz is an optional PSR-18 client fallback referenced behind interface_exists()/class_exists() - // guards in the compiler pass and configuration, so it is intentionally a dev dependency. + // guards in the compiler pass and configuration, so it is intentionally a dev dependency and may + // not be installed at all when only production dependencies are analysed. ->ignoreErrorsOnPackage('kriswallsmith/buzz', [ErrorType::DEV_DEPENDENCY_IN_PROD]) + ->ignoreUnknownClasses([ + \Buzz\Client\BuzzClientInterface::class, + \Buzz\Client\Curl::class, + ]) // The sylius/sylius metapackage (dev only) "replace"s the split sylius/* packages this plugin requires. // In this dev environment their classes therefore resolve to sylius/sylius, so the analyser reports // sylius/sylius as a shadow dependency and the split packages as unused. The split packages are the From 232318f31b498e74b557eda812120b31cfafede8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20L=C3=B8vgaard?= Date: Mon, 15 Jun 2026 14:09:18 +0200 Subject: [PATCH 4/4] Address PR review feedback - bundles.php: register the plugin before SyliusGridBundle (and document it in the README) instead of working around the grid/model-class parameter ordering in the extension's prepend() - remove the now-unnecessary setParameter() workaround from prepend() - drop the redundant getModelNamespace() override (it equals the AbstractResourceBundle default) - do not hard-require a specific PSR-17 implementation: require php-http/discovery and discover the request/response factories at runtime; nyholm/psr7 becomes a dev dependency (used by the test app) - composer-dependency-analyser: drop the sylius split-package ignores (not needed in CI) - restore the backwards-compatibility CI job as-is --- .github/workflows/build.yaml | 14 ++++------- README.md | 5 ++-- composer-dependency-analyser.php | 24 ++++--------------- composer.json | 3 ++- config/services.php | 13 ++++++---- .../SetonoSyliusPartnerAdsExtension.php | 24 ++++++++----------- src/SetonoSyliusPartnerAdsPlugin.php | 5 ---- tests/Application/config/bundles.php | 4 +++- 8 files changed, 37 insertions(+), 55 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c059edd..747e983 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,15 +6,11 @@ on: workflow_dispatch: ~ jobs: - # NOTE: the backwards-compatibility job has been removed for the 1.x -> 2.x major upgrade. There is no - # 2.0 baseline to compare against yet and a major release intentionally breaks BC. Re-add it once 2.0 - # has been released: - # - # backwards-compatibility: - # runs-on: "ubuntu-latest" - # if: "github.event_name == 'pull_request'" - # steps: - # - uses: "setono/sylius-plugin/backwards-compatibility@v2" + backwards-compatibility: + runs-on: "ubuntu-latest" + if: "github.event_name == 'pull_request'" + steps: + - uses: "setono/sylius-plugin/backwards-compatibility@v2" coding-standards: runs-on: "ubuntu-latest" diff --git a/README.md b/README.md index 0d4c795..6e58255 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ composer require setono/sylius-partner-ads-plugin ### Step 2: Enable the plugin -If it wasn't done automatically by Symfony Flex, enable the plugin by adding it to the list of registered plugins/bundles -in the `config/bundles.php` file of your project: +Enable the plugin by adding it to the list of registered plugins/bundles in the `config/bundles.php` file of your +project, **before** `SyliusGridBundle` (this is required so the plugin's resource is registered before the grid is built): ```php ['all' => true], + Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true], // ... ]; ``` diff --git a/composer-dependency-analyser.php b/composer-dependency-analyser.php index 9e53402..79107fb 100644 --- a/composer-dependency-analyser.php +++ b/composer-dependency-analyser.php @@ -6,31 +6,17 @@ use ShipMonk\ComposerDependencyAnalyser\Config\ErrorType; return (new Configuration()) - // The Sylius split-package ignores below only apply when sylius/sylius (which "replace"s them) is the - // installed provider; depending on how dependencies resolve they may not match, which is fine. + // Buzz is only used when its optional dev dependency is installed (see below), so its ignore does not + // apply when only production dependencies are analysed. ->disableReportingUnmatchedIgnores() - // Scan the PHP service configuration so symbols only referenced there (e.g. nyholm/psr7) are detected. + // Scan the PHP service configuration so symbols only referenced there (e.g. php-http/discovery) are detected. ->addPathToScan(__DIR__ . '/config', false) ->addPathToExclude(__DIR__ . '/tests') - // Buzz is an optional PSR-18 client fallback referenced behind interface_exists()/class_exists() - // guards in the compiler pass and configuration, so it is intentionally a dev dependency and may - // not be installed at all when only production dependencies are analysed. + // Buzz is an optional PSR-18 client fallback referenced behind interface_exists()/class_exists() guards, + // so it is intentionally a dev dependency and may not be installed when only production deps are analysed. ->ignoreErrorsOnPackage('kriswallsmith/buzz', [ErrorType::DEV_DEPENDENCY_IN_PROD]) ->ignoreUnknownClasses([ \Buzz\Client\BuzzClientInterface::class, \Buzz\Client\Curl::class, ]) - // The sylius/sylius metapackage (dev only) "replace"s the split sylius/* packages this plugin requires. - // In this dev environment their classes therefore resolve to sylius/sylius, so the analyser reports - // sylius/sylius as a shadow dependency and the split packages as unused. The split packages are the - // correct production dependencies for consumers that do not install the sylius/sylius metapackage. - ->ignoreErrorsOnPackage('sylius/sylius', [ErrorType::DEV_DEPENDENCY_IN_PROD]) - ->ignoreErrorsOnPackages([ - 'sylius/channel', - 'sylius/channel-bundle', - 'sylius/core', - 'sylius/core-bundle', - 'sylius/order', - 'sylius/ui-bundle', - ], [ErrorType::UNUSED_DEPENDENCY]) ; diff --git a/composer.json b/composer.json index 6265cc5..51f353f 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "php": ">=8.2", "ext-mbstring": "*", "knplabs/knp-menu": "^3.1", - "nyholm/psr7": "^1.8", + "php-http/discovery": "^1.20", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0 || ^2.0", @@ -37,6 +37,7 @@ "api-platform/symfony": "^4.3.3", "kriswallsmith/buzz": "^1.2", "matthiasnoback/symfony-config-test": "^5.1 || ^6.0", + "nyholm/psr7": "^1.8", "payum/core": "^1.7.5", "setono/sylius-plugin": "^2.0", "sylius/grid-bundle": "^1.15", diff --git a/config/services.php b/config/services.php index abd8a79..9dc2c56 100644 --- a/config/services.php +++ b/config/services.php @@ -4,7 +4,9 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; -use Nyholm\Psr7\Factory\Psr17Factory; +use Http\Discovery\Psr17FactoryDiscovery; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\ResponseFactoryInterface; use Setono\SyliusPartnerAdsPlugin\Calculator\OrderTotalCalculator; use Setono\SyliusPartnerAdsPlugin\Calculator\OrderTotalCalculatorInterface; use Setono\SyliusPartnerAdsPlugin\Client\Client; @@ -36,9 +38,12 @@ ]); $services->alias(NotifyUrlProviderInterface::class, NotifyUrlProvider::class); - // PSR-17 factories. These ids are referenced by the Client and by RegisterHttpClientPass - $services->set('setono_sylius_partner_ads.http_client.request_factory', Psr17Factory::class); - $services->set('setono_sylius_partner_ads.http_client.response_factory', Psr17Factory::class); + // PSR-17 factories, discovered from whichever PSR-17 implementation the application provides. + // These ids are referenced by the Client and by RegisterHttpClientPass. + $services->set('setono_sylius_partner_ads.http_client.request_factory', RequestFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findRequestFactory']); + $services->set('setono_sylius_partner_ads.http_client.response_factory', ResponseFactoryInterface::class) + ->factory([Psr17FactoryDiscovery::class, 'findResponseFactory']); $services->set(Client::class) ->args([ diff --git a/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php b/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php index 7047500..09dea8a 100644 --- a/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php +++ b/src/DependencyInjection/SetonoSyliusPartnerAdsExtension.php @@ -44,20 +44,8 @@ public function load(array $configs, ContainerBuilder $container): void public function prepend(ContainerBuilder $container): void { - /** @var array{resources: array{program: array{classes: array{model: string}}}, messenger: array{transport: string|null}} $config */ - $config = $this->processConfiguration( - $this->getConfiguration([], $container), - $container->getExtensionConfig($this->getAlias()), - ); - - // The model class parameter is normally set by registerResources() during load(), but the - // sylius_grid extension resolves it while loading its own configuration. Depending on bundle - // registration order that can happen before this plugin's load() runs, so we set it here in - // prepend() (which always runs before any load()) to make the grid registration order-independent. - $container->setParameter('setono_sylius_partner_ads.model.program.class', $config['resources']['program']['classes']['model']); - $this->prependGrid($container); - $this->prependMessenger($container, $config['messenger']['transport']); + $this->prependMessenger($container); } private function prependGrid(ContainerBuilder $container): void @@ -95,8 +83,16 @@ private function prependGrid(ContainerBuilder $container): void ]); } - private function prependMessenger(ContainerBuilder $container, ?string $transport): void + private function prependMessenger(ContainerBuilder $container): void { + /** @var array{messenger: array{transport: string|null}} $config */ + $config = $this->processConfiguration( + $this->getConfiguration([], $container), + $container->getExtensionConfig($this->getAlias()), + ); + + $transport = $config['messenger']['transport']; + if (null === $transport) { return; } diff --git a/src/SetonoSyliusPartnerAdsPlugin.php b/src/SetonoSyliusPartnerAdsPlugin.php index cf2decd..ffbbbb4 100644 --- a/src/SetonoSyliusPartnerAdsPlugin.php +++ b/src/SetonoSyliusPartnerAdsPlugin.php @@ -35,11 +35,6 @@ public function getSupportedDrivers(): array ]; } - protected function getModelNamespace(): string - { - return 'Setono\SyliusPartnerAdsPlugin\Model'; - } - protected function getConfigFilesPath(): string { return sprintf( diff --git a/tests/Application/config/bundles.php b/tests/Application/config/bundles.php index e88f492..e745c33 100644 --- a/tests/Application/config/bundles.php +++ b/tests/Application/config/bundles.php @@ -29,6 +29,9 @@ Sylius\Bundle\ReviewBundle\SyliusReviewBundle::class => ['all' => true], Sylius\Bundle\CoreBundle\SyliusCoreBundle::class => ['all' => true], Sylius\Bundle\ResourceBundle\SyliusResourceBundle::class => ['all' => true], + // Must be registered before SyliusGridBundle so the resource (and the + // setono_sylius_partner_ads.model.program.class parameter) is available when the grid is built. + Setono\SyliusPartnerAdsPlugin\SetonoSyliusPartnerAdsPlugin::class => ['all' => true], Sylius\Bundle\GridBundle\SyliusGridBundle::class => ['all' => true], Knp\Bundle\GaufretteBundle\KnpGaufretteBundle::class => ['all' => true], Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true], @@ -55,5 +58,4 @@ Symfony\UX\Autocomplete\AutocompleteBundle::class => ['all' => true], Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true], Sylius\Abstraction\StateMachine\SyliusStateMachineAbstractionBundle::class => ['all' => true], - Setono\SyliusPartnerAdsPlugin\SetonoSyliusPartnerAdsPlugin::class => ['all' => true], ];