├── .github ├── oxid-esales │ └── geo-blocking.yaml └── workflows │ ├── dispatch_module.yaml │ ├── schedule.yaml │ └── trigger.yaml ├── .gitignore ├── .htaccess ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets └── out │ ├── pictures │ └── logo.png │ └── src │ └── js │ └── oegeoblocking.js ├── composer.json ├── metadata.php ├── migration ├── data │ ├── .gitkeep │ └── Version20230106130208.php └── migrations.yml ├── src ├── Component │ └── UserComponent.php ├── Controller │ ├── Admin │ │ └── CountryMain.php │ └── OrderController.php ├── Core │ ├── Events.php │ └── InputValidator.php ├── Model │ ├── Address.php │ ├── Country.php │ ├── CountryToShop.php │ └── UserAddressList.php └── Service │ ├── CountryToShopService.php │ ├── NotInvoiceOnlyCountryListService.php │ └── PickupAddressService.php ├── tests ├── Codeception │ ├── Acceptance.suite.yml │ ├── Acceptance │ │ ├── FrontendCest.php │ │ └── _bootstrap.php │ ├── Config │ │ └── params.php │ └── Support │ │ ├── AcceptanceTester.php │ │ ├── Data │ │ ├── .gitkeep │ │ ├── dump.sql │ │ ├── fixtures.php │ │ └── fixtures_ee.php │ │ ├── Helper │ │ └── Acceptance.php │ │ └── Step │ │ └── Acceptance │ │ └── Basket.php ├── Integration │ ├── Component │ │ └── UserComponentTest.php │ ├── Controller │ │ ├── Admin │ │ │ └── CountryMainTest.php │ │ └── OrderControllerTest.php │ ├── Core │ │ └── InputValidatorTest.php │ ├── Model │ │ ├── AddressTest.php │ │ ├── CountryTest.php │ │ └── UserAddressListTest.php │ └── Service │ │ ├── CountryToShopServiceTest.php │ │ ├── NotInvoiceOnlyCountryListServiceTest.php │ │ └── PickupAddressServiceTest.php ├── PhpMd │ └── standard.xml ├── PhpStan │ ├── phpstan-bootstrap.php │ └── phpstan.neon ├── codeception.yml ├── phpcs.xml └── phpunit.xml ├── translations ├── de │ └── oegeoblocking_lang.php └── en │ └── oegeoblocking_lang.php └── views ├── admin_twig ├── de │ └── oegeoblocking_lang.php └── en │ └── oegeoblocking_lang.php └── twig └── extensions └── themes ├── admin_twig └── country_main.html.twig ├── apex └── form │ ├── fieldset │ ├── user_billing.html.twig │ └── user_shipping.html.twig │ └── user_checkout_change.html.twig └── twig └── form ├── fieldset ├── user_billing.html.twig └── user_shipping.html.twig └── user_checkout_change.html.twig /.github/oxid-esales/geo-blocking.yaml: -------------------------------------------------------------------------------- 1 | install_shop_with_modules: 2 | cache: 3 | prepared_shop: false 4 | composer: 5 | transform: | 6 | { 7 | "require": { 8 | "oxid-esales/oxideshop-ce": "{{ .Data.global.composer.dev_ref }}", 9 | "oxid-esales/twig-component": "{{ .Data.global.composer.dev_ref }}", 10 | "oxid-esales/twig-admin-theme": "{{ .Data.global.composer.dev_ref }}", 11 | "oxid-esales/apex-theme": "{{ .Data.global.composer.dev_ref }}", 12 | "oxid-esales/geo-blocking-module": "{{ .Data.global.composer.ref_name }}" 13 | }, 14 | "repositories": { 15 | "oxid-esales/geo-blocking-module": { 16 | "type": "git", 17 | "url": "https://github.com/OXID-eSales/geo-blocking-module.git" 18 | } 19 | } 20 | } 21 | custom_script_container: | 22 | vendor/bin/oe-console oe:theme:activate apex 23 | vendor/bin/oe-console oe:module:activate oegeoblocking 24 | 25 | runscript: &runscript 26 | matrix: 27 | script: | 28 | [ 29 | "geo_blocking:tests-integration", 30 | "geo_blocking:tests-codeception" 31 | ] 32 | geo_blocking: 33 | path: 'vendor/oxid-esales/geo-blocking-module' 34 | 35 | runslim: 36 | <<: *runscript 37 | matrix: 38 | script: | 39 | [ 40 | "geo_blocking:phpcs-report", 41 | "geo_blocking:phpmd-report", 42 | "geo_blocking:phpstan-report" 43 | ] 44 | 45 | sonarcloud: 46 | matrix: 47 | testplan: '["-"]' 48 | strip_path: '/var/www/vendor/oxid-esales/geo-blocking-module/' 49 | project_key: 'OXID-eSales_geo-blocking-module' 50 | project_name: 'oxid-esales/geo-blocking-module' 51 | organization: 'oxid-esales' 52 | parameters: | 53 | -Dsonar.language=php \ 54 | -Dsonar.scm.provider=git \ 55 | -Dsonar.sources=src \ 56 | -Dsonar.tests=tests \ 57 | -Donar.php.phpstan.reportPaths=coverage-reports/phpstan.report.json 58 | 59 | finish: 60 | slack_title: 'Geo Blocking ({{ .Data.global.git.shop_ref }}) by {{ .Github.Actor }}' -------------------------------------------------------------------------------- /.github/workflows/dispatch_module.yaml: -------------------------------------------------------------------------------- 1 | name: Manual trigger 2 | # Matrix workflow using re-usable github actions 3 | 4 | on: 5 | workflow_dispatch: 6 | inputs: 7 | limit: 8 | type: choice 9 | options: 10 | - 'no' 11 | - 'PHP8.2/MySQL8.0' 12 | - 'PHP8.2/MariaDb11' 13 | - 'PHP8.3/MySQL8.0' 14 | - 'PHP8.3/MariaDb11' 15 | - 'PHP8.4/MySQL8.0' 16 | - 'PHP8.4/MariaDb11' 17 | default: 'PHP8.3/MySQL8.0' 18 | description: 'Limit to one PHP/MySQL combination' 19 | 20 | jobs: 21 | build_testplan: 22 | runs-on: ubuntu-latest 23 | outputs: 24 | testplan: '${{ steps.build.outputs.testplan }}' 25 | steps: 26 | - name: 'Build testplan' 27 | id: build 28 | run: | 29 | # Build testplan 30 | # shellcheck disable=SC2088 31 | case "${{ inputs.limit }}" in 32 | "no") LIMIT='';; 33 | "PHP8.2/MySQL8.0") LIMIT='~/defaults/php8.2_mysql8.0_only.yaml,' ;; 34 | "PHP8.2/MariaDb11") LIMIT='~/defaults/php8.2_mariadb11_only.yaml,' ;; 35 | "PHP8.3/MySQL8.0") LIMIT='~/defaults/php8.3_mysql8.0_only.yaml,' ;; 36 | "PHP8.3/MariaDb11") LIMIT='~/defaults/php8.3_mariadb11_only.yaml,' ;; 37 | "PHP8.4/MySQL8.0") LIMIT='~/defaults/php8.4_mysql8.0_only.yaml,' ;; 38 | "PHP8.4/MariaDb11") LIMIT='~/defaults/php8.4_mariadb11_only.yaml,' ;; 39 | *) echo "Illegal choice, fix the workflow" 40 | exit 1 41 | ;; 42 | esac 43 | # shellcheck disable=SC2088 44 | TESTPLAN="~/defaults/7.3.x.yaml,${LIMIT}~/geo-blocking.yaml" 45 | echo "testplan=${TESTPLAN}" | tee -a "${GITHUB_OUTPUT}" 46 | 47 | dispatch_stable: 48 | needs: build_testplan 49 | uses: oxid-eSales/github-actions/.github/workflows/universal_workflow_light.yaml@v4 50 | with: 51 | testplan: ${{ needs.build_testplan.outputs.testplan }} 52 | runs_on: '"ubuntu-latest"' 53 | defaults: 'v4' 54 | plan_folder: '.github/oxid-esales' 55 | secrets: 56 | DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} 57 | DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }} 58 | CACHE_ENDPOINT: ${{ secrets.CACHE_ENDPOINT }} 59 | CACHE_ACCESS_KEY: ${{ secrets.CACHE_ACCESS_KEY }} 60 | CACHE_SECRET_KEY: ${{ secrets.CACHE_SECRET_KEY }} 61 | enterprise_github_token: ${{ secrets.enterprise_github_token }} 62 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 63 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} -------------------------------------------------------------------------------- /.github/workflows/schedule.yaml: -------------------------------------------------------------------------------- 1 | name: Scheduled weekly run 2 | # Matrix workflow using re-usable github actions 3 | 4 | on: 5 | schedule: 6 | - cron: '16 1 */7 * *' 7 | 8 | jobs: 9 | geo_blocking_php82_mysql80: 10 | if: always() 11 | uses: oxid-eSales/github-actions/.github/workflows/universal_workflow_light.yaml@v4 12 | with: 13 | testplan: '~/defaults/7.3.x.yaml,~/defaults/scheduled.yaml,~/geo-blocking.yaml' 14 | runs_on: '"ubuntu-latest"' 15 | defaults: 'v4' 16 | plan_folder: '.github/oxid-esales' 17 | use_scheduled_slack_channel: true 18 | secrets: 19 | DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} 20 | DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }} 21 | CACHE_ENDPOINT: ${{ secrets.CACHE_ENDPOINT }} 22 | CACHE_ACCESS_KEY: ${{ secrets.CACHE_ACCESS_KEY }} 23 | CACHE_SECRET_KEY: ${{ secrets.CACHE_SECRET_KEY }} 24 | enterprise_github_token: ${{ secrets.enterprise_github_token }} 25 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 26 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 27 | SLACK_SCHEDULED_WEBHOOK_URL: ${{ secrets.SLACK_SCHEDULED_WEBHOOK_URL }} 28 | -------------------------------------------------------------------------------- /.github/workflows/trigger.yaml: -------------------------------------------------------------------------------- 1 | name: Auto trigger on push or pull requests 2 | # Matrix workflow using re-usable github actions 3 | 4 | on: 5 | pull_request: {} 6 | push: 7 | branches: 8 | - 'b-7.3.x*' 9 | 10 | jobs: 11 | geo_blocking_php83_mysql80: 12 | uses: oxid-eSales/github-actions/.github/workflows/universal_workflow_light.yaml@v4 13 | with: 14 | testplan: '~/defaults/7.3.x.yaml,~/defaults/php8.3_mysql8.0_only.yaml,~/geo-blocking.yaml' 15 | runs_on: '"ubuntu-latest"' 16 | defaults: 'v4' 17 | plan_folder: '.github/oxid-esales' 18 | secrets: 19 | DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} 20 | DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }} 21 | CACHE_ENDPOINT: ${{ secrets.CACHE_ENDPOINT }} 22 | CACHE_ACCESS_KEY: ${{ secrets.CACHE_ACCESS_KEY }} 23 | CACHE_SECRET_KEY: ${{ secrets.CACHE_SECRET_KEY }} 24 | enterprise_github_token: ${{ secrets.enterprise_github_token }} 25 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 26 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Tests/Codeception/_support/_generated/* 2 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | Deny from all 3 | 4 | Allow from all 5 | 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log for OXID geo-blocking module 2 | 3 | All notable changes to this project will be documented in this file. 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## [2.3.0-rc.1] - 2025-04-24 8 | 9 | ### Added 10 | - PHP 8.4 11 | - Upgraded to work with OXID eShop 7.3.x 12 | 13 | ## [2.2.0] - 2024-11-26 14 | This is stable release for v2.2.0. No changes have been made since v2.2.0-rc.2. 15 | 16 | ## [2.2.0-rc.2] - 2024-10-31 17 | 18 | ### Fixed 19 | - Shop owners suggested Pick Up Address cannot be used for order if no salutation is included [0007734](https://bugs.oxid-esales.com/view.php?id=7734) 20 | 21 | ## [2.2.0-rc.1] - 2024-10-17 22 | 23 | ### Added 24 | - PHP 8.3 25 | - Upgraded to work with OXID eShop 7.2.x 26 | - Static analysis tools: 27 | - PhpCs 28 | - PhpMd 29 | - PhpStan 30 | 31 | ### Fixed 32 | - Multiple instances of coding standard and style errors 33 | 34 | ### Removed 35 | - Support of PHP 8.1 36 | 37 | ## [2.1.0] - 2024-06-26 38 | This is the stable release for v2.1.0. No changes have been made since v2.1.0-rc.1. 39 | 40 | ## [2.1.0-rc.1] - 2024-05-27 41 | 42 | ### Added 43 | - PHP 8.2 44 | - Upgraded to work with OXID eShop 7.1.x 45 | 46 | ### Changed 47 | - New module logo 48 | - Updated the structure to Codeception 5 49 | - PhpUnit updated to 10+ 50 | - Modify GitHub workflows to use new light workflow 51 | 52 | ### Removed 53 | - PHP 8.0 support 54 | - Legacy Smarty engine variant is not supported anymore 55 | 56 | ## [2.0.0] - 2023-06-08 57 | 58 | ### Added 59 | - Support for twig template engine 60 | - Migrations directory configured, queries from activation events moved to migrations 61 | - Development workflows with test runners 62 | - Module works on smarty engine (Smarty related extensions in views/smarty resp. views/admin_smarty directory) 63 | - Module works on twig engine (Twig related extensions in views/twig resp. views/admin_twig directory) 64 | - Support for APEX theme. 65 | 66 | ### Changed 67 | - Adapted module to work with OXID eShop 7.0.x 68 | - Adapted test to work with OXID eShop 7.0.x and without testing library 69 | - Moved all php code to src directory with some cleanups: 70 | - Application folder omitted 71 | - All assets moved to `assets` folder to be available after module installation 72 | 73 | ## [1.1.2] - unreleased 74 | 75 | ### Changed 76 | - License updated - now using OXID Module and Component License 77 | 78 | ## [1.1.1] - 2022-06-13 79 | 80 | ### Fixed 81 | - Updated documentation link 82 | 83 | ## [1.1.0] - 2021-07-14 84 | 85 | ### Added 86 | - Ensure module works with php 7.2 87 | 88 | ### Removed 89 | - Support of php 5.6 and 7.0 90 | 91 | ### Fixed 92 | - Fixed tests to work with latest module registration/activation changes 93 | - Fixed compatibility issues regarding setUp and tearDown phpunit methods. 94 | 95 | ## [1.0.0] - 2019-02-25 96 | 97 | [2.3.0-rc.1]: https://github.com/OXID-eSales/geo-blocking-module/compare/v2.2.0...2.3.0-rc.1 98 | [2.2.0]: https://github.com/OXID-eSales/geo-blocking-module/compare/v2.2.0-rc.2...v2.2.0 99 | [2.2.0-rc.2]: https://github.com/OXID-eSales/geo-blocking-module/compare/v2.2.0-rc.1...v2.2.0-rc.2 100 | [2.2.0-rc.1]: https://github.com/OXID-eSales/geo-blocking-module/compare/v2.1.0...v2.2.0-rc.1 101 | [2.1.0]: https://github.com/OXID-eSales/geo-blocking-module/compare/v2.1.0-rc.1...v2.1.0 102 | [2.1.0-rc.1]: https://github.com/OXID-eSales/geo-blocking-module/compare/v2.0.0...v2.1.0-rc.1 103 | [2.0.0]: https://github.com/OXID-eSales/geo-blocking-module/compare/v1.1.2...v2.0.0 104 | [1.1.2]: https://github.com/OXID-eSales/geo-blocking-module/compare/v1.1.1...v1.1.2 105 | [1.1.1]: https://github.com/OXID-eSales/geo-blocking-module/compare/v1.1.0...v1.1.1 106 | [1.1.0]: https://github.com/OXID-eSales/geo-blocking-module/compare/v1.0.0...v1.1.0 107 | [1.0.0]: https://github.com/OXID-eSales/geo-blocking-module/compare/c0cb05009601a58d0815efa9e09bd4ad758b1595...v1.0.0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | OXID Modul & Komponenten-Lizenz 2023 2 | 3 | 1. Präambel 4 | Diese Software ist ausschließlich für den Einsatz mit den für eine kommerzielle Nutzung freigegebenen Editionen des OXID eShop bestimmt. Dies sind die Professional Edition und die Enterprise Edition, sowie die OXID eShop CE-Software, vorausgesetzt, für diese wird eine monatliche Nutzungsgebühr bezahlt. 5 | 6 | 2. Urheberrecht 7 | Die Software ist urheberrechtlich geschützt und geschütztes Geschäftsgeheimnis von OXID eSales. 8 | OXID eSales behält sich alle Rechte vor, sofern Ihnen in dieser Lizenzvereinbarung keine ausdrücklichen Rechte an der Software eingeräumt werden. 9 | 10 | 3. Rechteeinräumung 11 | OXID eSales räumt Ihnen an der Software das nicht ausschließliche und nicht übertragbare Recht zur Nutzung der Software ein. 12 | 13 | 4. Nutzungsbedingungen 14 | Sie erhalten das Recht zur Nutzung unter der Bedingung, dass Sie diese Lizenzbedingungen und die darin enthalenen Nutzungsbedingungen akzeptieren. 15 | 16 | 5. Einschränkungen 17 | a. Die Nutzung von unter dieser Lizenz veröffentlichten Softwareprodukten oder -modulen in Verbindung mit früheren Versionen der OXID eShop CE Software (vor Version 6.4.2) bzw. von dieser abgeleiteten Softwareprodukten (Forks) ist nicht zulässig. 18 | b. Die Nutzung dieser Software oder Teilen davon durch Module oder Software Dritter unterliegt diesen Nutzungsbedingungen. 19 | c. Die Software kann Softwareprodukte von Fremdherstellern enthalten. Die Fremdprodukte können Sie nach der Installation der composer.lock-Datei entnehmen. Für diese Fremdprodukte gelten zusätzliche Lizenzbestimmungen, die sie der entsprechenden Lizenzdatei des Fremdprodukts entnehmen können. 20 | d. Sie dürfen die Software weder umarbeiten, anpassen noch in eine andere Programmiersprache übersetzen, ebenso sind Reverse Engineering und Nachbau der Software nicht erlaubt. 21 | e. Jede gemäß dieser Lizenz zulässige Kopie der Software muss die Urheberrechts- und Schutzrechtsvermerke von OXID eSales tragen, die auf oder in der lizensierten Software vorhanden sind. 22 | f. Sie dürfen die Software Dritten weder vermieten, verleihen, unterlizensieren oder übertragen. 23 | g. Sie dürfen den Quellcode der Software Dritten nicht zugänglich machen, es sei denn, 24 | - die entsprechenden Dateien sind von OXID eSales explizit als öffentlich (open source) gekennzeichnet oder 25 | - der Dritte benötigt den Quellcode zur Durchführung seiner Tätigkeit für Sie und hat mit OXID eSales eine schriftliche Geheimhaltungsvereinbarung abgeschlossen. 26 | 27 | 6. Nutzungsuntersagung und Nutzungsentschädigung 28 | Wenn Sie die Bestimmungen von Ziff. 4 und 5 nicht oder nicht vollständig erfüllen, ist OXID eSales ohne weiteres berechtigt, Ihnen die Nutzung der Software zu untersagen. Schadensersatzansprüche von OXID eSales bleiben vorbehalten. 29 | Werden die Nutzungsbedingungen nicht eingehalten und gibt es keine andere Vereinbarung, stimmt der Lizenznehmer der jeweils gültigen Nutzungsentschädigung (Stand 31.12.2022: 111€) zuzüglich des Inflationsausgleichs gemäß der vom statistischen Bundesamt festgestellten jährlichen Inflationsrate für jeden Monat unrechtmäßiger Nutzung der Software mit anderen Softwareprodukten zu. Diese Entschädigung entbindet nicht vom Abschluss eines der Nutzung entsprechenden Lizenzvertrags. 30 | Für spätere Versionen behält sich OXID eine Anpassung der Nutzungsgebühr vor. 31 | Werden mehrere Shops oder Teile der OXID Professional Edition oder OXID Enterprise Edition oder vergleichbare Funktionalität, die durch Dritte auf Basis von OXID Software bereitgestellt wurde, mit dieser Software genutzt, wird eine Lizenzmiete für die Professional Edition oder Enterprise Edition gemäß der OXID Preisliste fällig. Es gilt die Preisliste des Monats, in dem die erste Lizenzmiete bezahlt wird. 32 | 33 | 7. Support und Wartung 34 | Support- und Wartungsleistungen sind nicht Bestandteil dieser Lizenzvereinbarung. Wenn Sie solche Leistungen in Anspruch nehmen wollen, wenden Sie sich bitte an sales@oxid-esales.com. 35 | 36 | 8. Rechte bei Mängeln 37 | a. Die vertragsgemäße Beschaffenheit der Software bestimmt sich ausschließlich nach den Spezifikationen der Dokumentation in der bei Abschluss dieses Lizenzvertrages gültigen Fassung. 38 | b. Die Verjährungsfrist beträgt 12 Monate nach Lieferung der Software (Bereitstellung zum Download). 39 | c. Die Software wird Ihnen in der Beschaffenheit überlassen, wie sie sich zum Zeitpunkt des Abschlusses dieses Lizenzvertrages befindet. OXID eSales übernimmt keine Haftung für Sach- und Rechtsmängel, insbesondere übernehmen wir keine Haftung für die vertragsgemäße Beschaffenheit oder die Eignung für den vertraglich vorausgesetzten Verwendungszweck. Die in der Dokumentation gegebene Beschreibung der Software darf in keinem Fall als Zusicherung oder Garantie verstanden werden. Unsere Haftung für vorsätzliches und/oder arglistiges Handeln bleibt davon jedoch unberührt. 40 | 41 | 9. Haftung 42 | a. OXID eSales haftet nur bei Vorsatz und grober Fahrlässigkeit, Ansprüchen nach dem deutschen Produkthaftungsgesetz sowie bei einer Verletzung des Lebens, des Körpers oder der Gesundheit. Im Übrigen haften die Parteien unbeschränkt nach den gesetzlichen Vorschriften 43 | b. Alle anderen Ansprüche sind ausgeschlossen. 44 | 45 | 10. Sonstiges 46 | a. Dieser Lizenzvertrag unterliegt deutschem Recht. 47 | b. Sollte eine Bestimmung dieses Lizenzvertrages unwirksam oder nichtig sein oder werden, so bleibt seine Wirksamkeit im Übrigen unberührt. 48 | c. Für die Auslegung dieses Lizenzvertrages ist die deutsche Sprachfassung verbindlich. 49 | d. Für alle Streitigkeiten, die aus dieser Lizenzvereinbarung entstehen, wird die Zuständigkeit des Landgerichts Freiburg vereinbart. 50 | 51 | 52 | 53 | ENGLISH VERSION 54 | 55 | This is a rough translation of the German language version for informational purposes. The German language version of this license agreement is legally binding. 56 | 57 | OXID Module and Component License 2023 58 | 59 | 1. Preamble 60 | This software is intended exclusively for use with the editions of OXID eShop released for commercial use. These are the Professional Edition and the Enterprise Edition, as well as the OXID eShop CE software, provided that a monthly fee is paid for these. 61 | 62 | 2. Copyright 63 | The software is copyrighted and protected trade secret of OXID eSales. 64 | OXID eSales reserves all rights unless you are granted explicit rights to the software in this license agreement. 65 | 66 | 3. Granting of rights 67 | OXID eSales grants you the non-exclusive and non-transferable right to use the software. 68 | 69 | 4. Terms of use 70 | You are granted the right to use the software under the condition that you accept this license agreement and the included terms of use. 71 | 72 | 5. Restrictions 73 | a. The use of software products or modules published under this licence in connection with earlier versions of the OXID eShop CE software (prior to version 6.4.2) or software products derived from it (forks) is not permitted. 74 | b. The use of this software or parts thereof by third party modules or software is subject to these Terms of Use. 75 | c. The software contains software products from third-party manufacturers. You can find the third-party products in the composer.lock file after installation. Additional license conditions apply to these third-party products, which you can find in the corresponding license file of the third-party product. 76 | d. You may not modify, adapt or translate this software, nor may you reverse engineer or decompile the software. 77 | e. Any copy of the Software permitted under this license must bear the copyright and proprietary notices of OXID eSales that are present on or in the Licensed Software. 78 | f. You may not rent, loan, sublicense or transfer the Software to any third party. 79 | g. You may not make the source code of the software available to third parties unless, 80 | - the corresponding files are explicitly marked as public (open source) by OXID eSales or 81 | - the third party requires the source code to carry out its activities for you and has concluded a written non-disclosure agreement with OXID eSales. 82 | 83 | 6. Prohibition of Use and Compensation for Use 84 | If you do not or not completely fulfill the provisions of clauses 4 and 5, OXID eSales is entitled without further ado to prohibit you from using the software. OXID eSales reserves the right to claim damages. 85 | If the terms of use are not complied with and there is no other agreement, the licensee agrees to compensation for use of € 111 plus inflation compensation in accordance with the annual inflation rate determined by the Federal Statistical Office of Germany for each month of unlawful use. This compensation does not release from the conclusion of a license agreement corresponding to the use. 86 | For later versions OXID reserves the right to adjust the usage fee. 87 | If several shops or parts of the OXID Professional Edition or OXID Enterprise Edition or comparable functionality provided by third parties based on OXID software are used, a license fee according to the OXID price list is due. The price list of the month in which the first license fee is paid applies. 88 | 89 | 7. Support and Maintenance 90 | Support and maintenance services are not part of this license agreement. If you wish to make use of such services, please contact sales@oxid-esales.com. 91 | 92 | 8. Rights in the Event of Defects 93 | a. The contractual quality of the software is determined exclusively by the specifications of the documentation in the version valid at the time of conclusion of this license agreement. 94 | b. The limitation period is 12 months after delivery of the software (provision for download). 95 | c. The software is provided to you in the condition as it is at the time of the conclusion of this license agreement. OXID eSales accepts no liability for material defects or defects of title, in particular we accept no liability for the contractual condition or suitability for the contractually assumed purpose. The description of the software given in the documentation may in no case be understood as an assurance or guarantee. However, this shall not affect our liability for intentional and/or fraudulent acts. 96 | 97 | 9. Liability 98 | a. OXID eSales shall only be liable in the event of intent and gross negligence, claims under the German Product Liability Act and in the event of injury to life or health. In all other respects the parties shall be liable without limitation in accordance with the statutory provisions. 99 | b. All other claims are excluded. 100 | 101 | 10. Miscellaneous 102 | a. This license agreement is subject to German law. 103 | b. Should any provision of this license agreement be or become invalid or void, the validity of the remaining provisions shall remain unaffected. 104 | c. The German language version shall be binding for the interpretation of this license agreement. 105 | d. It is agreed that the Regional Court of Freiburg shall have jurisdiction over all disputes arising from this licence agreement. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OXID geo-blocking module 2 | ======================== 3 | 4 | This module provides a vast range of extra options concerning the so called geo-blocking regulation (EU 2018/302), additionally to the in-application solution provided here:[Geo-blocking Regulation: how to configure OXID eShop to be compliant?](https://forum.oxid-esales.com/t/geo-blocking-regulation-how-to-configure-oxid-eshop-to-be-compliant/) 5 | 6 | Further, this module provides a possibility to mark countries as "Invoice only" and to define an alternative pickup address. 7 | 8 | ## Compatability 9 | 10 | * Module v2.3 (or b-7.3.x branch) is compatible with OXID eShop ^7.3 11 | * Module v2.2 (or b-7.2.x branch) is compatible with OXID eShop ^7.2 12 | * Module v2.1 (or b-7.1.x branch) is compatible with OXID eShop ^7.1, works with `Twig engine` only 13 | * Module v2.0 (or b-7.0.x branch) is compatible with OXID eShop ^7.0 14 | * Module v1.1 (or b-1.x branch) is compatible with OXID eShop ^v6.2 to ^v6.5 15 | * Module v1.0 version works with OXID eShop compilation v6.0.0 to v6.1.x 16 | 17 | ### Module installation via composer 18 | 19 | * **composer require oxid-esales/geo-blocking-module:^1.1** to install the released version compatible with OXID eShop 6.2.x - 6.5.x compilations 20 | * **composer require oxid-esales/geo-blocking-module:^2.0** to install the latest version 2.0 from github, compatible with shop 7.0.x 21 | * **composer require oxid-esales/geo-blocking-module:^2.1** to install the latest version 2.1 from github, compatible with shop 7.1.x 22 | * **composer require oxid-esales/geo-blocking-module:^2.2** to install the latest version 2.2 from github, compatible with shop 7.2.x 23 | * **composer require oxid-esales/geo-blocking-module:^2.3** to install the latest version 2.3 from github, compatible with shop 7.3.x 24 | 25 | ## Documentation 26 | 27 | The module documentation can be found on our documentation platform: https://docs.oxid-esales.com/modules/geo-blocking/en/latest/. 28 | 29 | ## License 30 | 31 | See LICENSE file for license details. 32 | -------------------------------------------------------------------------------- /assets/out/pictures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OXID-eSales/geo-blocking-module/3912d0be9109b3fd58fafa2785f449e8d065a772/assets/out/pictures/logo.png -------------------------------------------------------------------------------- /assets/out/src/js/oegeoblocking.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © OXID eSales AG. All rights reserved. 3 | * See LICENSE file for license details. 4 | */ 5 | 6 | addSelectEventListener = () => { 7 | let invCountrySelect = document.querySelector('#invCountrySelect'); 8 | 9 | invCountrySelect.addEventListener('click', checkInvoiceCountry); 10 | checkInvoiceCountry(); 11 | }; 12 | 13 | checkInvoiceCountry = () => { 14 | let invoiceonly = invCountrySelect.options[invCountrySelect.selectedIndex].dataset.invoiceonly; 15 | 16 | if (invoiceonly == 'true') { 17 | // Country is marked as "invoice only" 18 | let shippingAddress = document.querySelector('#shippingAddress'); 19 | const style = getComputedStyle(shippingAddress); 20 | 21 | if (style.display === 'none') { 22 | document.querySelector('#showShipAddress').click(); 23 | } 24 | document.querySelector('.invoiceonlyhint').classList.remove('hidden'); 25 | document.querySelector('.invoiceonlyhint').style.display = ''; 26 | document.querySelector('#showShipAddress').setAttribute("disabled", "disabled"); 27 | } else { 28 | // Country is NOT marked as "invoice only" 29 | document.querySelector('.invoiceonlyhint').classList.add('hidden'); 30 | document.querySelector('.invoiceonlyhint').style.display = 'none'; 31 | document.querySelector('#showShipAddress').removeAttribute("disabled"); 32 | } 33 | }; 34 | 35 | window.addEventListener("load", function() { 36 | addSelectEventListener(); 37 | }, false ); 38 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oxid-esales/geo-blocking-module", 3 | "description": "The module enables OXID eShop to be compliant with the EU geo-blocking regulations.", 4 | "type": "oxideshop-module", 5 | "keywords": ["oxid", "modules", "eShop"], 6 | "homepage": "https://www.oxid-esales.com", 7 | "license": [ 8 | "proprietary" 9 | ], 10 | "minimum-stability": "dev", 11 | "prefer-stable": true, 12 | "prefer-dist": true, 13 | "conflict": { 14 | "oxid-esales/oxideshop-ce": "<7.3" 15 | }, 16 | "require": { 17 | "php": "^8.2" 18 | }, 19 | "require-dev": { 20 | "phpstan/phpstan": "^1.9.14", 21 | "squizlabs/php_codesniffer": "3.*", 22 | "phpmd/phpmd": "^2.11", 23 | "phpunit/phpunit": "^10.4", 24 | "oxid-esales/oxideshop-ce": "dev-b-7.3.x", 25 | "mikey179/vfsstream": "~1.6.8", 26 | "codeception/codeception": "^5.0", 27 | "codeception/module-asserts": "*", 28 | "codeception/module-db": "*", 29 | "codeception/module-filesystem": "*", 30 | "codeception/module-webdriver": "*", 31 | "oxid-esales/codeception-modules": "dev-b-7.3.x", 32 | "oxid-esales/codeception-page-objects": "dev-b-7.3.x" 33 | }, 34 | "autoload": { 35 | "psr-4": { 36 | "OxidEsales\\GeoBlocking\\": "src/", 37 | "OxidEsales\\GeoBlocking\\Tests\\": "tests/" 38 | } 39 | }, 40 | "scripts": { 41 | "phpcs": "phpcs --standard=tests/phpcs.xml --report=full", 42 | "phpcs-report": "phpcs --standard=tests/phpcs.xml --report=json --report-file=tests/Reports/phpcs.report.json", 43 | "phpcbf": "phpcbf --standard=tests/phpcs.xml", 44 | 45 | "phpstan": "phpstan -ctests/PhpStan/phpstan.neon analyse src/", 46 | "phpstan-report": "phpstan -ctests/PhpStan/phpstan.neon analyse src/ --error-format=json > tests/Reports/phpstan.report.json", 47 | 48 | "phpmd": "phpmd src ansi tests/PhpMd/standard.xml --ignore-errors-on-exit --ignore-violations-on-exit", 49 | "phpmd-report": "phpmd src json tests/PhpMd/standard.xml --ignore-errors-on-exit --ignore-violations-on-exit --reportfile tests/Reports/phpmd.report.json", 50 | 51 | "static": [ 52 | "@phpcs", 53 | "@phpstan", 54 | "@phpmd" 55 | ], 56 | 57 | "tests-integration": "XDEBUG_MODE=coverage vendor/bin/phpunit --bootstrap=/var/www/source/bootstrap.php --config=tests/ --testsuite=Integration --coverage-clover=tests/Reports/coverage_integration_geo-blocking-module.xml", 58 | "tests-coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text --bootstrap=/var/www/source/bootstrap.php --config=tests/ --coverage-html=tests/reports/coverage", 59 | 60 | "tests-codeception": [ 61 | "Composer\\Config::disableProcessTimeout", 62 | "THEME_ID=apex MODULE_IDS=oegeoblocking SHOP_ROOT_PATH=/var/www vendor/bin/codecept run Acceptance -c tests/codeception.yml --no-redirect" 63 | ] 64 | 65 | }, 66 | "config": { 67 | "allow-plugins": { 68 | "oxid-esales/oxideshop-unified-namespace-generator": true, 69 | "oxid-esales/oxideshop-composer-plugin": false 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /metadata.php: -------------------------------------------------------------------------------- 1 | 'oegeoblocking', 26 | 'title' => 'OXID geo-blocking module', 27 | 'description' => [ 28 | 'de' => 'Dieses Modul ermöglicht es, den OXID eShop konform zu der EU Geoblocking-Verordnung einzurichten.', 29 | 'en' => 'The module enables OXID eShop to be compliant with the EU geo-blocking regulations.', 30 | ], 31 | 'thumbnail' => '/out/pictures/logo.png', 32 | 'version' => '2.3.0-rc.1', 33 | 'author' => 'OXID eSales AG', 34 | 'url' => 'https://www.oxid-esales.com', 35 | 'email' => 'info@oxid-esales.com', 36 | 'extend' => [ 37 | \OxidEsales\Eshop\Application\Controller\Admin\CountryMain::class => CountryMain::class, 38 | \OxidEsales\Eshop\Application\Controller\OrderController::class => OrderController::class, 39 | \OxidEsales\Eshop\Application\Model\Country::class => Country::class, 40 | \OxidEsales\Eshop\Application\Model\UserAddressList::class => UserAddressList::class, 41 | \OxidEsales\Eshop\Application\Model\Address::class => Address::class, 42 | \OxidEsales\Eshop\Application\Component\UserComponent::class => UserComponent::class, 43 | \OxidEsales\Eshop\Core\InputValidator::class => InputValidator::class, 44 | ], 45 | 'events' => [ 46 | 'onActivate' => '\OxidEsales\GeoBlocking\Core\Events::onActivate', 47 | ], 48 | 'blocks' => [ 49 | ], 50 | ]; 51 | -------------------------------------------------------------------------------- /migration/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OXID-eSales/geo-blocking-module/3912d0be9109b3fd58fafa2785f449e8d065a772/migration/data/.gitkeep -------------------------------------------------------------------------------- /migration/data/Version20230106130208.php: -------------------------------------------------------------------------------- 1 | addSql("CREATE TABLE IF NOT EXISTS `oegeoblocking_country_to_shop` ( 23 | `OXID` char(32) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL COMMENT 'Record id', 24 | `OXCOUNTRYID` char(32) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL COMMENT 'Country id', 25 | `OXSHOPID` int(11) NOT NULL DEFAULT '1' COMMENT 'Shop id (oxshops)', 26 | `PICKUP_ADDRESSID` char(32) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL COMMENT 'oxaddress id', 27 | `PICKUP_ADDRESS_ACTIVE` tinyint NOT NULL DEFAULT 0, 28 | `INVOICE_ONLY` tinyint NOT NULL DEFAULT 0, 29 | `OXTIMESTAMP` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Timestamp', 30 | PRIMARY KEY (`OXID`), 31 | UNIQUE KEY `OXCOUNTRYID` (`OXCOUNTRYID`,`OXSHOPID`) 32 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Shows many-to-many relationship between fields and shops (multishops fields)';"); 33 | } 34 | 35 | public function down(Schema $schema): void 36 | { 37 | // this down() migration is auto-generated, please modify it to your needs 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /migration/migrations.yml: -------------------------------------------------------------------------------- 1 | table_storage: 2 | table_name: oxmigrations_geo_blocking 3 | migrations_paths: 4 | 'OxidEsales\ModuleTemplate\Migrations': data 5 | -------------------------------------------------------------------------------- /src/Component/UserComponent.php: -------------------------------------------------------------------------------- 1 | getRequestEscapedParameter('deladr', ''); 31 | $deliveryAddressInfo = $this->trimAddress($deliveryAddressInfo); 32 | $countryToShop = $this->oeGeoBlockingCreateCountryToShopByAddressId( 33 | Registry::getRequest()->getRequestEscapedParameter('oxaddressid', '') 34 | ); 35 | /** @var \OxidEsales\GeoBlocking\Model\Address $address */ 36 | $address = Registry::get(Address::class); 37 | if ($address->load((string)$countryToShop->getFieldData('pickup_addressid'))) { 38 | if ($address->oeGeoBlockingIsUserChangingAddress($deliveryAddressInfo)) { 39 | Registry::getUtilsView()->addErrorToDisplay( 40 | 'OEGEOBLOCKING_PICKUP_ADDRESS_CHANGE_NOT_ALLOWED', 41 | false, 42 | true 43 | ); 44 | return false; 45 | } 46 | } 47 | 48 | return parent::changeUserWithoutRedirect(); 49 | } 50 | 51 | /** 52 | * Override does not allow to delete predefined shipping address. 53 | * 54 | * @see \OxidEsales\Eshop\Application\Component\UserComponent::deleteShippingAddress() 55 | * 56 | * @return void 57 | */ 58 | public function deleteShippingAddress() 59 | { 60 | $addressId = Registry::getRequest()->getRequestEscapedParameter('oxaddressid', ''); 61 | $countryToShop = $this->oeGeoBlockingCreateCountryToShopByAddressId($addressId); 62 | if ($countryToShop->getId()) { 63 | Registry::getUtilsView()->addErrorToDisplay('OEGEOBLOCKING_PICKUP_ADDRESS_CHANGE_NOT_ALLOWED', false, true); 64 | } else { 65 | parent::deleteShippingAddress(); 66 | } 67 | } 68 | 69 | /** 70 | * Factory method for object creation. 71 | * 72 | * @param string $addressId 73 | * 74 | * @return \OxidEsales\GeoBlocking\Model\CountryToShop 75 | */ 76 | private function oeGeoBlockingCreateCountryToShopByAddressId($addressId) 77 | { 78 | $countryToShopService = oxNew(CountryToShopService::class); 79 | $countryToShop = $countryToShopService->getByAddressId($addressId); 80 | return $countryToShop; 81 | } 82 | 83 | /** 84 | * Returns trimmed address. 85 | * 86 | * @param array $address 87 | * 88 | * @return array 89 | */ 90 | private function trimAddress($address) 91 | { 92 | if (is_array($address)) { 93 | $fields = oxNew(FormFields::class, $address); 94 | $trimmer = oxNew(FormFieldsTrimmer::class); 95 | 96 | $address = (array)$trimmer->trim($fields); 97 | } 98 | 99 | return $address; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Controller/Admin/CountryMain.php: -------------------------------------------------------------------------------- 1 | _aViewData['edit'])) { 32 | /** @var Country $country */ 33 | $country = $this->_aViewData['edit']; 34 | $this->_aViewData['invoiceCountry'] = oxNew(CountryToShopService::class)->getByCountryId($country->getId()); 35 | $this->_aViewData['pickupAddress'] = oxNew(PickupAddressService::class)->getByCountryId($country->getId()); 36 | 37 | $countryListService = oxNew(NotInvoiceOnlyCountryListService::class); 38 | $this->_aViewData["countryList"] = 39 | $countryListService->getWithSelectedLanguage(Registry::getLang()->getObjectTplLanguage()); 40 | } 41 | 42 | return $templateName; 43 | } 44 | 45 | /** 46 | * @see \OxidEsales\Eshop\Application\Controller\Admin\CountryMain::save() 47 | * 48 | * @return void 49 | * @throws \Exception 50 | */ 51 | public function save() 52 | { 53 | parent::save(); 54 | 55 | $requestParameters = Registry::getRequest()->getRequestEscapedParameter('editval_gb'); 56 | 57 | $address = oxNew(PickupAddressService::class)->getByAddressId((string)$requestParameters['oxaddress_oxid']); 58 | $address->assign($requestParameters); 59 | $address->save(); 60 | 61 | $countryToShop = oxNew(CountryToShopService::class)->getByCountryId((string)$this->getEditObjectId()); 62 | $countryToShop->assign($requestParameters); 63 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field($address->getId()); 64 | $countryToShop->save(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Controller/OrderController.php: -------------------------------------------------------------------------------- 1 | getUser(); 26 | $billingAddrParams['oxuser__oxcountryid'] = $user->getFieldData('oxcountryid'); 27 | $shippingAddress = $this->getDelAddress(); 28 | if (is_object($shippingAddress)) { 29 | $shippingAddrParams['oxaddress__oxcountryid'] = $shippingAddress->getFieldData('oxcountryid'); 30 | } else { 31 | $shippingAddrParams['oxaddress__oxcountryid'] = $user->getFieldData('oxcountryid'); 32 | } 33 | 34 | /** @var InputValidator $inputValidator */ 35 | $inputValidator = Registry::getInputValidator(); 36 | $inputValidator->checkCountries($user, $billingAddrParams, $shippingAddrParams); 37 | if ($error = Registry::getInputValidator()->getFirstValidationError()) { 38 | Registry::getUtilsView()->addErrorToDisplay($error); 39 | return 'user'; 40 | } 41 | 42 | return parent::execute(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Core/Events.php: -------------------------------------------------------------------------------- 1 | build(); 46 | 47 | $output = new BufferedOutput(); 48 | $migrations->setOutput($output); 49 | $neeedsUpdate = $migrations->execute('migrations:up-to-date', 'oegeoblocking'); 50 | 51 | if ($neeedsUpdate) { 52 | $migrations->execute('migrations:migrate', 'oegeoblocking'); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Core/InputValidator.php: -------------------------------------------------------------------------------- 1 | getActiveView()->getClassKey() === 'user' 36 | || Registry::getConfig()->getActiveView()->getClassKey() === 'account_user' 37 | || Registry::getConfig()->getActiveView()->getClassKey() === 'order' 38 | ) { 39 | $billingCountryId = $invoiceAddrParams['oxuser__oxcountryid'] ?? null; 40 | $deliveryCountryId = $deliveryAddrParams['oxaddress__oxcountryid'] ?? null; 41 | 42 | if ($billingCountryId || $deliveryCountryId) { 43 | $deliveryCountryId = $deliveryCountryId ? $deliveryCountryId : $billingCountryId; 44 | $countryToShopService = oxNew(CountryToShopService::class); 45 | $countryToShop = $countryToShopService->getByCountryId($deliveryCountryId); 46 | 47 | if ( 48 | $countryToShop->getId() && 49 | $countryToShop->getRawFieldData('oegeoblocking_country_to_shop__invoice_only') == 1 50 | ) { 51 | $exception = oxNew( 52 | UserException::class, 53 | Registry::getLang()->translateString('OEGEOBLOCKING_ERROR_MESSAGE_INPUT_COUNTRY_NOT_ALLOWED') 54 | ); 55 | $this->addValidationError('', $exception); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Model/Address.php: -------------------------------------------------------------------------------- 1 | getByAddressId($this->getId()); 24 | if ($countryToShop->getId()) { 25 | return false; 26 | } else { 27 | return true; 28 | } 29 | } 30 | 31 | /** 32 | * @param array $addressInfo 33 | * @return bool 34 | */ 35 | public function oeGeoBlockingIsUserChangingAddress($addressInfo) 36 | { 37 | $tableName = $this->getCoreTableName(); 38 | foreach ($this->getFieldNames() as $fieldName) { 39 | $fieldNameWithTable = $tableName . '__' . $fieldName; 40 | if ( 41 | isset($addressInfo[$fieldNameWithTable]) && 42 | $addressInfo[$fieldNameWithTable] !== $this->{$fieldNameWithTable}->value 43 | ) { 44 | return true; 45 | } 46 | } 47 | 48 | return false; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Model/Country.php: -------------------------------------------------------------------------------- 1 | getByCountryId($this->getId()); 24 | return (bool) $invoiceCountryToShop->getFieldData('invoice_only'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Model/CountryToShop.php: -------------------------------------------------------------------------------- 1 | 0, 38 | 'oxcountryid' => 0, 39 | 'oxshopid' => 0, 40 | 'invoice_only' => 0, 41 | 'pickup_addressid' => 0, 42 | 'pickup_address_active' => 0, 43 | ]; 44 | } 45 | -------------------------------------------------------------------------------- /src/Model/UserAddressList.php: -------------------------------------------------------------------------------- 1 | isAdmin()) { 28 | parent::load($userId); 29 | } else { 30 | $this->loadAddressesForFrontendOnly($userId); 31 | } 32 | } 33 | 34 | /** 35 | * Loads user addresses together with predefined addresses by administrator. 36 | * 37 | * @param string $userId 38 | * @return void 39 | * @throws \OxidEsales\Eshop\Core\Exception\DatabaseConnectionException 40 | */ 41 | private function loadAddressesForFrontendOnly($userId) 42 | { 43 | $shopId = Registry::getConfig()->getShopId(); 44 | $viewName = Registry::get(TableViewNameGenerator::class)->getViewName('oxcountry'); 45 | $baseObject = $this->getBaseObject(); 46 | $selectFields = $baseObject->getSelectFields(); 47 | 48 | $query = " 49 | SELECT {$selectFields}, `oxcountry`.`oxtitle` AS oxcountry, 50 | if(isnull(gbc2s.oxid), 0, 1) AS is_pickup, gbc2s.oxcountryid AS pickup_countryid 51 | FROM oxaddress 52 | LEFT JOIN {$viewName} AS oxcountry 53 | ON oxaddress.oxcountryid = oxcountry.oxid 54 | 55 | -- get only already saved deliveryaddresses with allowed deliverycountrys and remove all others 56 | LEFT JOIN oegeoblocking_country_to_shop gbInvOnly 57 | ON gbInvOnly.oxshopid = " . $shopId . " 58 | AND gbInvOnly.oxcountryid = oxaddress.oxcountryid 59 | LEFT JOIN oegeoblocking_country_to_shop gbc2s 60 | ON gbc2s.oxshopid = " . $shopId . " 61 | AND gbc2s.pickup_addressid = oxaddress.oxid 62 | AND gbc2s.pickup_address_active = 1 63 | WHERE ( 64 | ( 65 | oxaddress.oxuserid = " . DatabaseProvider::getDb()->quote($userId) . " 66 | AND (gbInvOnly.oxid IS NULL OR gbInvOnly.invoice_only = 0) 67 | ) -- get user addresses that are not invoice only 68 | OR gbc2s.oxid IS NOT NULL 69 | ) -- additionally all pickup addresses 70 | ORDER BY is_pickup asc"; 71 | 72 | $this->selectString($query); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Service/CountryToShopService.php: -------------------------------------------------------------------------------- 1 | countryToShop = oxNew(CountryToShop::class); 31 | } 32 | 33 | /** 34 | * @param string $countryId 35 | * @return CountryToShop 36 | */ 37 | public function getByCountryId($countryId) 38 | { 39 | $parameters = [ 40 | $this->countryToShop->getViewName() . '.OXCOUNTRYID' => $countryId, 41 | $this->countryToShop->getViewName() . '.OXSHOPID' => Registry::getConfig()->getShopId(), 42 | ]; 43 | $record = $this->getById($parameters); 44 | 45 | $isLoaded = false; 46 | if (is_array($record) && count($record)) { 47 | $this->countryToShop->assign($record); 48 | $isLoaded = true; 49 | } 50 | 51 | if (!$isLoaded) { 52 | $this->countryToShop->assign( 53 | [ 54 | 'oxcountryid' => $countryId, 55 | 'oxshopid' => Registry::getConfig()->getShopId() 56 | ] 57 | ); 58 | } 59 | 60 | return $this->countryToShop; 61 | } 62 | 63 | /** 64 | * @param string $addressId 65 | * @return CountryToShop 66 | */ 67 | public function getByAddressId($addressId) 68 | { 69 | $parameters = [ 70 | $this->countryToShop->getViewName() . '.PICKUP_ADDRESSID' => $addressId, 71 | $this->countryToShop->getViewName() . '.OXSHOPID' => Registry::getConfig()->getShopId(), 72 | ]; 73 | 74 | $record = $this->getById($parameters); 75 | if (is_array($record) && count($record)) { 76 | $this->countryToShop->assign($record); 77 | } 78 | 79 | return $this->countryToShop; 80 | } 81 | 82 | /** 83 | * @param array $parameters 84 | * @return mixed 85 | * @throws \Psr\Container\ContainerExceptionInterface 86 | * @throws \Psr\Container\NotFoundExceptionInterface 87 | */ 88 | private function getById(array $parameters) 89 | { 90 | $selectQuery = $this->countryToShop->buildSelectString($parameters); 91 | 92 | $connection = ContainerFactory::getInstance() 93 | ->getContainer() 94 | ->get(QueryBuilderFactoryInterface::class) 95 | ->create() 96 | ->getConnection(); 97 | 98 | return $connection 99 | ->executeQuery($selectQuery) 100 | ->fetchAssociative(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Service/NotInvoiceOnlyCountryListService.php: -------------------------------------------------------------------------------- 1 | countryList = oxNew(CountryList::class); 30 | } 31 | 32 | /** 33 | * @param int $languageId 34 | * 35 | * @return CountryList 36 | */ 37 | public function getWithSelectedLanguage($languageId) 38 | { 39 | $shopId = Registry::getConfig()->getShopId(); 40 | $tableViewNAmeGen = Registry::get(TableViewNameGenerator::class); 41 | $countryViewName = $tableViewNAmeGen->getViewName('oxcountry', $languageId); 42 | $countryShopViewName = $tableViewNAmeGen->getViewName('oegeoblocking_country_to_shop', $languageId); 43 | 44 | $select = "SELECT c.oxid, c.oxtitle, c.oxisoalpha2 45 | FROM {$countryViewName} c 46 | LEFT JOIN {$countryShopViewName} gbc2s 47 | on gbc2s.oxcountryid = c.oxid 48 | AND gbc2s.oxshopid = {$shopId} 49 | WHERE c.oxactive = '1' 50 | AND (gbc2s.invoice_only = 0 or gbc2s.invoice_only is null) 51 | ORDER BY oxorder, oxtitle "; 52 | 53 | $this->countryList->selectString($select); 54 | 55 | return $this->countryList; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Service/PickupAddressService.php: -------------------------------------------------------------------------------- 1 | address = oxNew(Address::class); 30 | } 31 | 32 | /** 33 | * @param string $countryId 34 | * @return Address 35 | */ 36 | public function getByCountryId($countryId) 37 | { 38 | $shopId = Registry::getConfig()->getShopid(); 39 | $selectQuery = "select pickup_addressid from oegeoblocking_country_to_shop 40 | where oegeoblocking_country_to_shop.oxcountryid = '{$countryId}' 41 | and oegeoblocking_country_to_shop.oxshopid = '{$shopId}'"; 42 | 43 | $oxId = DatabaseProvider::getDb()->getOne($selectQuery); 44 | if ($oxId) { 45 | $this->address->load($oxId); 46 | } 47 | 48 | return $this->address; 49 | } 50 | 51 | /** 52 | * @param string $addressId 53 | * @return Address 54 | */ 55 | public function getByAddressId($addressId) 56 | { 57 | $shopId = Registry::getConfig()->getShopid(); 58 | $selectQuery = "select pickup_addressid from oegeoblocking_country_to_shop 59 | where oegeoblocking_country_to_shop.pickup_addressid = '{$addressId}' 60 | and oegeoblocking_country_to_shop.oxshopid = '{$shopId}'"; 61 | 62 | $oxId = DatabaseProvider::getDb()->getOne($selectQuery); 63 | if ($oxId) { 64 | $this->address->load($oxId); 65 | } 66 | 67 | return $this->address; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/Codeception/Acceptance.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for acceptance tests. 4 | # Perform tests in browser using the WebDriver or PhpBrowser. 5 | # If you need both WebDriver and PHPBrowser tests - create a separate suite. 6 | 7 | actor: AcceptanceTester 8 | path: Acceptance 9 | bootstrap: _bootstrap.php 10 | 11 | modules: 12 | enabled: 13 | - Asserts 14 | - WebDriver: 15 | url: '%SHOP_URL%' 16 | host: '%SELENIUM_SERVER_HOST%' 17 | browser: '%BROWSER_NAME%' 18 | port: '%SELENIUM_SERVER_PORT%' 19 | window_size: 1920x1024 20 | clear_cookies: true 21 | - Db: 22 | dsn: 'mysql:host=%DB_HOST%;dbname=%DB_NAME%;charset=utf8' 23 | user: '%DB_USERNAME%' 24 | password: '%DB_PASSWORD%' 25 | port: '%DB_PORT%' 26 | dump: '%DUMP_PATH%' 27 | module_dump: '%MODULE_DUMP_PATH%' 28 | mysql_config: '%MYSQL_CONFIG_PATH%' 29 | populate: true # run populator before all tests 30 | cleanup: false # run populator before each test 31 | populator: > 32 | mysql --defaults-file=$mysql_config --default-character-set=utf8 $dbname < $dump 33 | && mysql --defaults-file=$mysql_config --default-character-set=utf8 $dbname < $module_dump 34 | - \OxidEsales\Codeception\Module\Oxideshop: 35 | depends: 36 | - WebDriver 37 | - Db 38 | - \OxidEsales\Codeception\Module\Database: 39 | config_key: 'fq45QS09_fqyx09239QQ' 40 | depends: Db 41 | - \OxidEsales\Codeception\Module\SelectTheme: 42 | theme_id: '%THEME_ID%' 43 | depends: 44 | - \OxidEsales\Codeception\Module\Database 45 | - Db 46 | - \OxidEsales\Codeception\Module\Translation\TranslationsModule: 47 | shop_path: '%SHOP_SOURCE_PATH%' 48 | paths: 49 | - Application/views/%THEME_ID% 50 | - Application/views/admin_twig 51 | - ../vendor/oxid-esales/geo-blocking-module/views/admin_twig 52 | - ../vendor/oxid-esales/geo-blocking-module/translations 53 | step_decorators: 54 | - \Codeception\Step\Retry 55 | -------------------------------------------------------------------------------- /tests/Codeception/Acceptance/FrontendCest.php: -------------------------------------------------------------------------------- 1 | haveInDatabase('oegeoblocking_country_to_shop', Fixtures::get('countryToShopData')); 22 | } 23 | 24 | public function registerUserWithCountryWhichIsInvoiceOnly(AcceptanceTester $I) 25 | { 26 | $I->wantToTest('user registration with "invoice only" country.'); 27 | 28 | $startPage = $I->openShop(); 29 | $registrationPage = $startPage->openUserRegistrationPage(); 30 | 31 | $registrationPage->enterUserLoginData(Fixtures::get('userLoginData')); 32 | $registrationPage->enterUserData(Fixtures::get('userData')); 33 | $registrationPage->enterAddressData(Fixtures::get('userAddressData')); 34 | $I->dontSeeInPageSource(Translator::translate('OEGEOBLOCKING_HINT')); 35 | $I->clickWithLeftButton($registrationPage->saveFormButton); 36 | $I->see(Translator::translate('MESSAGE_WELCOME_REGISTERED_USER')); 37 | } 38 | 39 | public function checksIfNotPossibleToUseBillingAddressForShippingInCheckout(AcceptanceTester $I) 40 | { 41 | $I->wantToTest('checkout step 2 when not possible to use billing address'); 42 | $basket = new Basket($I); 43 | 44 | $I->haveInDatabase('oxuser', Fixtures::get('user')); 45 | 46 | $startPage = $I->openShop(); 47 | $startPage->loginUser('testing_account@oxid-esales.local', 'useruser'); 48 | 49 | /** @var UserCheckout $paymentCheckout */ 50 | $userCheckout = $basket->addProductToBasketAndOpenUserCheckout(1000, 1); 51 | 52 | $userCheckout->openUserBillingAddressForm(); 53 | $I->wait(1); 54 | $userCheckout->enterUserData(Fixtures::get('userData')); 55 | $userCheckout->enterAddressData(Fixtures::get('userAddressData')); 56 | $I->see(Translator::translate('OEGEOBLOCKING_HINT')); 57 | 58 | $I->clickWithLeftButton($userCheckout->delCountryId); 59 | $I->see('Austria', $userCheckout->shipAddressForm); 60 | $I->dontSee('United Kingdom', $userCheckout->shipAddressForm); 61 | 62 | $I->dontSeeCheckboxIsChecked($userCheckout->openShipAddressForm); 63 | $I->retryClick($userCheckout->nextStepButton); 64 | $I->see(Translator::translate('DD_FORM_VALIDATION_REQUIRED')); 65 | } 66 | 67 | public function checkIfNotPossibleToEditPickupAddressInCheckout(AcceptanceTester $I) 68 | { 69 | $I->wantToTest('checkout step 2 when not possible to edit or delete pickup address in checkout'); 70 | $basket = new Basket($I); 71 | 72 | $I->haveInDatabase('oxuser', Fixtures::get('user')); 73 | $this->addAddressData($I); 74 | 75 | $startPage = $I->openShop(); 76 | $startPage->loginUser('testing_account@oxid-esales.local', 'useruser'); 77 | /** @var UserCheckout $paymentCheckout */ 78 | $userCheckout = $basket->addProductToBasketAndOpenUserCheckout(1000, 1); 79 | 80 | $I->see(Translator::translate('OEGEOBLOCKING_HINT')); 81 | 82 | $I->dontSeeCheckboxIsChecked($userCheckout->openShipAddressForm); 83 | $I->seeElement(sprintf($userCheckout->openShipAddress, 1)); 84 | $I->dontSeeElement(sprintf($userCheckout->openShipAddress, 2)); 85 | $I->dontSeeElement(sprintf($userCheckout->deleteShipAddress, 2)); 86 | $I->seeElement(sprintf($userCheckout->selectShipAddress, 2)); 87 | } 88 | 89 | public function checksIfNotPossibleToUseBillingAddressForShippingInUserAccount(AcceptanceTester $I) 90 | { 91 | $I->wantToTest('user account when not possible to use billing address'); 92 | $I->haveInDatabase('oxuser', Fixtures::get('user')); 93 | $this->addAddressData($I); 94 | 95 | $startPage = $I->openShop(); 96 | $startPage->loginUser('testing_account@oxid-esales.local', 'useruser'); 97 | $userAccount = $startPage->openAccountPage(); 98 | $userAddress = $userAccount->openUserAddressPage(); 99 | 100 | $I->dontSeeCheckboxIsChecked($userAddress->openShipAddressPanel); 101 | $I->seeElement(sprintf($userAddress->openShipAddressForm, 1)); 102 | $I->dontSeeElement(sprintf($userAddress->openShipAddressForm, 2)); 103 | $I->dontSeeElement(sprintf($userAddress->deleteShipAddress, 2)); 104 | $I->seeElement(sprintf($userAddress->selectShipAddress, 2)); 105 | 106 | $userAddress->selectShippingAddress(1); 107 | 108 | $I->waitForElement($userAddress->delCountryId); 109 | $I->scrollTo($userAddress->delCountryId); 110 | $I->wait(1); 111 | $I->click($userAddress->delCountryId); 112 | $I->see('Austria', $userAddress->shipAddressForm); 113 | $I->dontSee('United Kingdom', $userAddress->shipAddressForm); 114 | } 115 | 116 | /** 117 | * @param AcceptanceTester $I 118 | */ 119 | private function addAddressData(AcceptanceTester $I) 120 | { 121 | $I->haveInDatabase('oxaddress', Fixtures::get('pickupAddress')); 122 | $I->haveInDatabase('oxaddress', Fixtures::get('userAddress')); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /tests/Codeception/Acceptance/_bootstrap.php: -------------------------------------------------------------------------------- 1 | getShopRootPath(), 'source', 'bootstrap.php'); 12 | 13 | $helper = new \OxidEsales\Codeception\Module\FixturesHelper(); 14 | $fixturesPath = dirname(__FILE__) . '/../Support/Data/fixtures.php'; 15 | if ((new Facts())->isEnterprise()) { 16 | $fixturesPath = dirname(__FILE__) . '/../Support/Data/fixtures_ee.php'; 17 | } 18 | $helper->loadRuntimeFixtures($fixturesPath); 19 | -------------------------------------------------------------------------------- /tests/Codeception/Config/params.php: -------------------------------------------------------------------------------- 1 | $facts->getShopUrl(), 24 | 'SHOP_SOURCE_PATH' => $facts->getSourcePath(), 25 | 'VENDOR_PATH' => $facts->getVendorPath(), 26 | 'DB_NAME' => $facts->getDatabaseName(), 27 | 'DB_USERNAME' => $facts->getDatabaseUserName(), 28 | 'DB_PASSWORD' => $facts->getDatabasePassword(), 29 | 'DB_HOST' => $facts->getDatabaseHost(), 30 | 'DB_PORT' => $facts->getDatabasePort(), 31 | 'DUMP_PATH' => getTestDataDumpFilePath(), 32 | 'MODULE_DUMP_PATH' => getModuleTestDataDumpFilePath(), 33 | 'MYSQL_CONFIG_PATH' => getMysqlConfigPath(), 34 | 'SELENIUM_SERVER_PORT' => $seleniumServerPort, 35 | 'SELENIUM_SERVER_HOST' => getenv('SELENIUM_SERVER_HOST') ?: 'selenium', 36 | 'BROWSER_NAME' => getenv('BROWSER_NAME') ?: 'chrome', 37 | 'THEME_ID' => getenv('THEME_ID') ?: 'twig', 38 | 'PHP_BIN' => $php, 39 | ]; 40 | 41 | function getTestDataDumpFilePath() 42 | { 43 | return Path::join(__DIR__, '/../', 'Support','Data', 'dump.sql'); 44 | } 45 | 46 | function getShopTestPath() 47 | { 48 | $facts = new Facts(); 49 | 50 | if ($facts->isEnterprise()) { 51 | $shopTestPath = $facts->getEnterpriseEditionRootPath() . '/Tests'; 52 | } else { 53 | $shopTestPath = getShopSuitePath($facts); 54 | } 55 | 56 | return $shopTestPath; 57 | } 58 | 59 | function getShopSuitePath($facts) 60 | { 61 | $testSuitePath = getenv('TEST_SUITE'); 62 | 63 | if (!$testSuitePath) { 64 | $testSuitePath = $facts->getShopRootPath() . '/tests'; 65 | } 66 | 67 | return $testSuitePath; 68 | } 69 | 70 | function getModuleTestDataDumpFilePath() 71 | { 72 | return __DIR__ . '/../Support/Data/dump.sql'; 73 | } 74 | 75 | function getMysqlConfigPath() 76 | { 77 | $facts = new Facts(); 78 | $configFilePath = Path::join($facts->getSourcePath(), 'config.inc.php'); 79 | $configFile = new ConfigFile($configFilePath); 80 | $generator = new DatabaseDefaultsFileGenerator($configFile); 81 | 82 | return $generator->generate(); 83 | } 84 | -------------------------------------------------------------------------------- /tests/Codeception/Support/AcceptanceTester.php: -------------------------------------------------------------------------------- 1 | amOnPage($homePage->URL); 42 | return $homePage; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Codeception/Support/Data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OXID-eSales/geo-blocking-module/3912d0be9109b3fd58fafa2785f449e8d065a772/tests/Codeception/Support/Data/.gitkeep -------------------------------------------------------------------------------- /tests/Codeception/Support/Data/dump.sql: -------------------------------------------------------------------------------- 1 | #Add default user 2 | REPLACE INTO `oxuser` (`OXID`, `OXACTIVE`, `OXRIGHTS`, `OXSHOPID`, `OXUSERNAME`, `OXPASSWORD`, `OXPASSSALT`, `OXCREATE`, `OXREGISTER`, `OXTIMESTAMP`, `OXBIRTHDATE`) VALUES 3 | ('oxdefaultuser',1,'user',1,'user@oxid-esales.com','$2y$10$ljaDXMPHOyC7ELlnC5ErK.3ET4B0oAN3WVr/Tk.RKlUfiuBcQEVVC','', '2003-01-01 00:00:00', '2003-01-01 00:00:00', '2003-01-01 00:00:00', '1985-01-01'); 4 | -------------------------------------------------------------------------------- /tests/Codeception/Support/Data/fixtures.php: -------------------------------------------------------------------------------- 1 | [ 10 | 'OXID' => '478ec8995365172e5e1da6852dfc0a76', 11 | 'OXCOUNTRYID' => 'a7c40f632a0804ab5.18804076', 12 | 'OXSHOPID' => 1, 13 | 'PICKUP_ADDRESSID' => 'pickup_address_id', 14 | 'PICKUP_ADDRESS_ACTIVE' => 1, 15 | 'INVOICE_ONLY' => 1, 16 | 'OXTIMESTAMP' => '2019-01-24 16:32:24', 17 | ], 18 | 'productsData' => [ 19 | 'oxarticles' => [ 20 | 'OXID' => '1000', 21 | 'OXSHOPID' => 1, 22 | 'OXACTIVE' => 1, 23 | 'OXARTNUM' => '1000', 24 | 'OXTITLE' => 'Test product', 25 | 'OXSHORTDESC' => 'Test product short desc', 26 | 'OXPRICE' => 10, 27 | 'OXUNITNAME' => 'kg', 28 | 'OXUNITQUANTITY' => 2, 29 | 'OXVAT' => null, 30 | 'OXWEIGHT' => 24, 31 | 'OXSTOCK' => 15, 32 | 'OXSTOCKFLAG' => 1, 33 | 'OXINSERT' => '2008-02-04', 34 | 'OXTIMESTAMP' => '2008-02-04 17:07:29', 35 | 'OXLENGTH' => 1, 36 | 'OXWIDTH' => 2, 37 | 'OXHEIGHT' => 2, 38 | 'OXSEARCHKEYS' => 'search1000', 39 | 'OXISSEARCH' => 1, 40 | 'OXVARMINPRICE' => 50, 41 | 'OXTITLE_1' => 'Test product', 42 | 'OXSHORTDESC_1' => 'Test product short desc', 43 | 'OXSUBCLASS' => 'oxarticle', 44 | 'OXACTIVEFROM' => '2008-02-04 17:07:29', 45 | 'OXACTIVETO' => '2600-02-04 17:07:29', 46 | 'OXDELIVERY' => '2008-02-04', 47 | ], 48 | ], 49 | 'pickupAddress' => [ 50 | 'OXID' => 'pickup_address_id', 51 | 'OXADDRESSUSERID' => '', 52 | 'OXCOMPANY' => 'Pickup address', 53 | 'OXFNAME' => 'TestName', 54 | 'OXLNAME' => 'TestSurname', 55 | 'OXSTREET' => 'Test street', 56 | 'OXSTREETNR' => '10', 57 | 'OXCITY' => 'Freiburg', 58 | 'OXCOUNTRY' => 'Germany', 59 | 'OXCOUNTRYID' => 'a7c40f631fc920687.20179984', 60 | 'OXZIP' => '111', 61 | ], 62 | 'userAddress' => [ 63 | 'OXID' => 'user_defined_pickup_address_id', 64 | 'OXUSERID' => 'oegeoblockingtestuser', 65 | 'OXADDRESSUSERID' => '', 66 | 'OXCOMPANY' => 'Some company', 67 | 'OXFNAME' => 'TestName', 68 | 'OXLNAME' => 'TestSurname', 69 | 'OXSTREET' => 'Test street 2', 70 | 'OXSTREETNR' => '10', 71 | 'OXCITY' => 'Freiburg', 72 | 'OXCOUNTRY' => 'Germany', 73 | 'OXCOUNTRYID' => 'a7c40f631fc920687.20179984', 74 | 'OXZIP' => '111', 75 | ], 76 | 'user' => [ 77 | 'OXID' => 'oegeoblockingtestuser', 78 | 'OXACTIVE' => 1, 79 | 'OXRIGHTS' => 'user', 80 | 'OXSHOPID' => 1, 81 | 'OXUSERNAME' => 'testing_account@oxid-esales.local', 82 | 'OXPASSWORD' => '13d726b9144af35f87b353e86185246fa4dc763f059d01e482d1360765ff3db96ec143df98c14df28b8d9414d40b5f32d090280c7d405a90d27de7f414437d7a', 83 | 'OXPASSSALT' => '8f9c890adba62e6b8610544792b9eecc', 84 | 'OXCUSTNR' => 1000, 85 | 'OXFNAME' => 'FirstName', 86 | 'OXLNAME' => 'LastName', 87 | 'OXSTREET' => 'StreetName', 88 | 'OXSTREETNR' => 'StreetNr', 89 | 'OXZIP' => '79098', 90 | 'OXCITY' => 'United Kingdom', 91 | 'OXCOUNTRYID' => 'a7c40f632a0804ab5.18804076', 92 | 'OXCREATE' => '2000-01-01 00:00:00', 93 | 'OXREGISTER' => '2000-01-01 00:00:00', 94 | 'OXBIRTHDATE' => '2000-01-01', 95 | ], 96 | 'userAddressData' => [ 97 | "userSalutation" => 'Mrs', 98 | "userFirstName" => "user name_šÄßüл", 99 | "userLastName" => "user last name_šÄßüл", 100 | "companyName" => "user company_šÄßüл", 101 | "street" => "user street_šÄßüл", 102 | "streetNr" => "111", 103 | "ZIP" => "1234", 104 | "city" => "user city_šÄßüл", 105 | "countryId" => 'United Kingdom', 106 | ], 107 | 'userData' => [ 108 | "userUstIDField" => "", 109 | "userMobFonField" => "111-111111", 110 | "userPrivateFonField" => "11111111", 111 | "userBirthDateDayField" => rand(10, 28), 112 | "userBirthDateMonthField" => rand(10, 12), 113 | "userBirthDateYearField" => rand(1960, 2000), 114 | ], 115 | 'userLoginData' => [ 116 | "userLoginNameField" => "test_registration@oxid-esales.local", 117 | "userPasswordField" => 'useruser', 118 | ], 119 | ]; 120 | -------------------------------------------------------------------------------- /tests/Codeception/Support/Data/fixtures_ee.php: -------------------------------------------------------------------------------- 1 | amOnPage(BasketPage::route($params)); 34 | if ($controller === 'user') { 35 | $userCheckoutPage = new UserCheckout($I); 36 | $breadCrumbName = Translator::translate("ADDRESS"); 37 | $userCheckoutPage->seeOnBreadCrumb($breadCrumbName); 38 | return $userCheckoutPage; 39 | } else { 40 | $basketPage = new BasketPage($I); 41 | $breadCrumbName = Translator::translate("CART"); 42 | $basketPage->seeOnBreadCrumb($breadCrumbName); 43 | return $basketPage; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/Integration/Component/UserComponentTest.php: -------------------------------------------------------------------------------- 1 | setId('test_model_id'); 27 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 28 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id'); 29 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('address_id'); 30 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 31 | $countryToShop->save(); 32 | 33 | $address = new EShopAddress(); 34 | $address->setId('address_id'); 35 | $address->save(); 36 | 37 | $address2 = new EShopAddress(); 38 | $address2->setId('address_id2'); 39 | $address2->save(); 40 | } 41 | 42 | protected function tearDown(): void 43 | { 44 | unset($_GET['oxaddressid']); 45 | parent::tearDown(); 46 | } 47 | 48 | public function testChangeUserWithoutRedirectWhenNotAllowedToChangeAddressData() 49 | { 50 | /** @var \OxidEsales\GeoBlocking\Component\UserComponent $userComponent */ 51 | $userComponent = oxNew(UserComponent::class); 52 | $_GET['oxaddressid'] = 'address_id'; 53 | $_GET['deladr'] = 'test'; 54 | 55 | $addressMock = $this->getMockBuilder(Address::class) 56 | ->onlyMethods(['oeGeoBlockingIsUserChangingAddress']) 57 | ->getMock(); 58 | $addressMock->method('oeGeoBlockingIsUserChangingAddress')->willReturn(true); 59 | Registry::set(EShopAddress::class, $addressMock); 60 | 61 | $this->assertFalse($userComponent->changeUserWithoutRedirect()); 62 | $errors = Registry::getSession()->getVariable('Errors'); 63 | $this->assertSame(1, count($errors)); 64 | } 65 | 66 | public function testChangeUserWithoutRedirectWhenAllowedToChangeAddressData() 67 | { 68 | /** @var \OxidEsales\GeoBlocking\Component\UserComponent $userComponent */ 69 | $userComponent = oxNew(UserComponent::class); 70 | $_GET['oxaddressid'] = 'address_id'; 71 | 72 | $addressMock = $this->getMockBuilder(Address::class) 73 | ->onlyMethods(['oeGeoBlockingIsUserChangingAddress']) 74 | ->getMock(); 75 | $addressMock->method('oeGeoBlockingIsUserChangingAddress')->willReturn(false); 76 | Registry::set(EShopAddress::class, $addressMock); 77 | 78 | $this->assertNotFalse($userComponent->changeUserWithoutRedirect()); 79 | $errors = Registry::getSession()->getVariable('Errors'); 80 | $this->assertNull($errors); 81 | } 82 | 83 | public function testChangeUserWithoutRedirectWithWhiteSpacesInAddress() 84 | { 85 | /** @var \OxidEsales\GeoBlocking\Component\UserComponent $userComponent */ 86 | $userComponent = oxNew(UserComponent::class); 87 | $_GET['oxaddressid'] = 'address_id'; 88 | $_GET['deladr'] = [ 89 | "oxaddress__oxsal" => " ", 90 | "oxaddress__oxuserid" => " user_id ", 91 | "oxaddress__oxcountryid" => " country_id" 92 | ]; 93 | 94 | $this->assertNotFalse($userComponent->changeUserWithoutRedirect()); 95 | $errors = Registry::getSession()->getVariable('Errors'); 96 | $this->assertNull($errors); 97 | } 98 | 99 | public function testDeleteShippingAddressWhenNotAllowed() 100 | { 101 | $_GET['oxaddressid'] = 'address_id'; 102 | /** @var \OxidEsales\GeoBlocking\Component\UserComponent $userComponent */ 103 | $userComponent = oxNew(UserComponent::class); 104 | $userComponent->deleteShippingAddress(); 105 | 106 | $errors = Registry::getSession()->getVariable('Errors'); 107 | $this->assertSame(1, count($errors)); 108 | } 109 | 110 | public function testDeleteShippingAddressWhenAllowed() 111 | { 112 | $_GET['oxaddressid'] = 'address_id2'; 113 | $this->createActiveUser(); 114 | 115 | /** @var \OxidEsales\GeoBlocking\Component\UserComponent $userComponent */ 116 | $userComponent = oxNew(UserComponent::class); 117 | $userComponent->deleteShippingAddress(); 118 | 119 | $errors = Registry::getSession()->getVariable('Errors'); 120 | $this->assertNull($errors); 121 | } 122 | 123 | private function createActiveUser() 124 | { 125 | $user = new User(); 126 | $user->setId('user_id'); 127 | $user->assign([ 128 | 'oxusername' => 'test', 129 | 'oxpassword' => md5('test') 130 | ]); 131 | $user->save(); 132 | Registry::getSession()->setVariable('usr', 'user_id'); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /tests/Integration/Controller/Admin/CountryMainTest.php: -------------------------------------------------------------------------------- 1 | setId('address_id'); 26 | $address->oxaddress__oxuserid = new Field('any'); 27 | $address->oxaddress__oxcountryid = new Field('country_id'); 28 | $address->oxaddress__oxfname = new Field('name'); 29 | $address->save(); 30 | 31 | $address = new Country(); 32 | $address->setId('country_id'); 33 | $address->oxcountry__oxactive = new Field(1); 34 | $address->save(); 35 | 36 | $countryToShop = new CountryToShop(); 37 | $countryToShop->setId('test_model_id'); 38 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 39 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id'); 40 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('address_id'); 41 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 42 | $countryToShop->save(); 43 | } 44 | 45 | public function testSaveWhenEditsExistingAddress() 46 | { 47 | $_POST['editval_gb'] = [ 48 | 'oxaddress_oxid' => 'address_id', 49 | 'oxaddress__oxfname' => 'updated name', 50 | ]; 51 | 52 | /** @var \OxidEsales\GeoBlocking\Controller\Admin\CountryMain $controller */ 53 | $controller = oxNew(CountryMain::class); 54 | $controller->save(); 55 | 56 | $address = new Address(); 57 | $address->load('address_id'); 58 | 59 | $this->assertSame('updated name', $address->oxaddress__oxfname->value); 60 | } 61 | 62 | public function testSaveWhenEditsExistingCountryToShopData() 63 | { 64 | $_POST['editval_gb'] = [ 65 | 'oxaddress_oxid' => 'address_id', 66 | 'oxaddress__oxfname' => 'updated name', 67 | 'country_to_shop__invoice_only' => 0, 68 | ]; 69 | 70 | /** @var \OxidEsales\GeoBlocking\Controller\Admin\CountryMain $controller */ 71 | $controller = oxNew(CountryMain::class); 72 | $controller->save(); 73 | 74 | $countryToShop = new CountryToShop(); 75 | $countryToShop->load('test_model_id'); 76 | 77 | $this->assertSame(0, (int) $countryToShop->getRawFieldData('oegeoblocking_country_to_shop__pickup_address_active')); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/Integration/Controller/OrderControllerTest.php: -------------------------------------------------------------------------------- 1 | setId('address_id'); 27 | $address->oxaddress__oxuserid = new Field('any'); 28 | $address->oxaddress__oxcountryid = new Field('country_id'); 29 | $address->save(); 30 | 31 | $address = new Country(); 32 | $address->setId('country_id'); 33 | $address->oxcountry__oxactive = new Field(1); 34 | $address->save(); 35 | 36 | $countryToShop = new CountryToShop(); 37 | $countryToShop->setId('test_model_id'); 38 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 39 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id'); 40 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('address_id'); 41 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 42 | $countryToShop->save(); 43 | } 44 | 45 | public function testWhenAddressIsBeingChangedViaRequest() 46 | { 47 | $_POST['deladrid'] = 'address_id'; 48 | $userController = oxNew(UserController::class); 49 | $userController->setClassKey('order'); 50 | Registry::getConfig()->setActiveView($userController); 51 | 52 | /** @var OrderController $orderController */ 53 | $orderController = oxNew(OrderController::class); 54 | $this->assertSame('user', $orderController->execute()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/Integration/Core/InputValidatorTest.php: -------------------------------------------------------------------------------- 1 | setId('user_id'); 28 | $user->save(); 29 | $this->user = $user; 30 | 31 | $countryToShop = new CountryToShop(); 32 | $countryToShop->setId('test_model_id'); 33 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 34 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id'); 35 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('address_id'); 36 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 37 | $countryToShop->save(); 38 | 39 | $address = new Country(); 40 | $address->setId('country_id'); 41 | $address->oxcountry__oxactive = new Field(1); 42 | $address->save(); 43 | 44 | $countryToShop2 = new CountryToShop(); 45 | $countryToShop2->setId('test_model_id2'); 46 | $countryToShop2->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 47 | $countryToShop2->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id2'); 48 | $countryToShop2->oegeoblocking_country_to_shop__pickup_addressid = new Field('address_id'); 49 | $countryToShop2->oegeoblocking_country_to_shop__invoice_only = new Field(0); 50 | $countryToShop2->save(); 51 | 52 | $address2 = new Country(); 53 | $address2->setId('country_id2'); 54 | $address2->oxcountry__oxactive = new Field(1); 55 | $address2->save(); 56 | } 57 | 58 | public static function checkoutCountriesProvider() 59 | { 60 | return [ 61 | [['oxuser__oxcountryid' => 'country_id'], ['oxaddress__oxcountryid' => 'country_id']], 62 | [['oxuser__oxcountryid' => ''], ['oxaddress__oxcountryid' => 'country_id']], 63 | [['oxuser__oxcountryid' => 'country_id'], ['oxaddress__oxcountryid' => '']], 64 | ]; 65 | } 66 | 67 | /** 68 | * @dataProvider checkoutCountriesProvider 69 | * @param array $invoiceAddressParameters 70 | * @param array $deliveryAddressParameters 71 | */ 72 | public function testCheckInvoiceOnlyCountries($invoiceAddressParameters, $deliveryAddressParameters) 73 | { 74 | $validator = $this->createInputValidator(); 75 | 76 | $validator->checkCountries($this->user, $invoiceAddressParameters, $deliveryAddressParameters); 77 | 78 | $errors = $validator->getFieldValidationErrors(); 79 | $this->assertSame(1, count($errors)); 80 | $this->assertSame( 81 | Registry::getLang()->translateString('OEGEOBLOCKING_ERROR_MESSAGE_INPUT_COUNTRY_NOT_ALLOWED'), 82 | $errors[''][0]->getMessage() 83 | ); 84 | } 85 | 86 | public function testCheckCountriesWhenNoInvoiceOnlyCountryProvided() 87 | { 88 | $validator = $this->createInputValidator(); 89 | 90 | $invoiceAddressParameters['oxuser__oxcountryid'] = 'country_id2'; 91 | 92 | $validator->checkCountries($this->user, $invoiceAddressParameters, []); 93 | 94 | $errors = $validator->getFieldValidationErrors(); 95 | $this->assertSame(0, count($errors)); 96 | } 97 | 98 | /** 99 | * @return \OxidEsales\GeoBlocking\Core\InputValidator 100 | */ 101 | private function createInputValidator() 102 | { 103 | $userController = oxNew(UserController::class); 104 | $userController->setClassKey('user'); 105 | Registry::getConfig()->setActiveView($userController); 106 | /** @var \OxidEsales\GeoBlocking\Core\InputValidator $validator */ 107 | $validator = oxNew(InputValidator::class); 108 | return $validator; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tests/Integration/Model/AddressTest.php: -------------------------------------------------------------------------------- 1 | setId('test_model_id'); 23 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(1); 24 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('test_country_id'); 25 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('address_id'); 26 | $countryToShop->save(); 27 | 28 | $address = new Address(); 29 | $address->setId('address_id'); 30 | $address->oxaddress__oxlname = new Field('user name'); 31 | $address->save(); 32 | 33 | $address2 = new Address(); 34 | $address2->setId('address_id2'); 35 | $address2->save(); 36 | } 37 | 38 | public function testWhenUserCantChangeAddress() 39 | { 40 | /** @var Address $address */ 41 | $address = oxNew(\OxidEsales\Eshop\Application\Model\Address::class); 42 | $address->load('address_id'); 43 | $this->assertFalse($address->oeGeoBlockingCanFrontendUserChange()); 44 | } 45 | 46 | public function testWhenUserCanChangeAddress() 47 | { 48 | /** @var Address $address */ 49 | $address = oxNew(\OxidEsales\Eshop\Application\Model\Address::class); 50 | $address->load('address_id2'); 51 | $this->assertTrue($address->oeGeoBlockingCanFrontendUserChange()); 52 | } 53 | 54 | public function testIsUserChangingAddressWhenAddressBeingChanged() 55 | { 56 | /** @var Address $address */ 57 | $address = oxNew(\OxidEsales\Eshop\Application\Model\Address::class); 58 | $address->load('address_id'); 59 | $data = [ 60 | 'oxaddress__oxlname' => 'name to change' 61 | ]; 62 | $this->assertTrue($address->oeGeoBlockingIsUserChangingAddress($data)); 63 | } 64 | 65 | public function testIsUserChangingAddressWhenNotBeingChanged() 66 | { 67 | /** @var Address $address */ 68 | $address = oxNew(\OxidEsales\Eshop\Application\Model\Address::class); 69 | $address->load('address_id'); 70 | $data = [ 71 | 'oxaddress__oxlname' => 'user name' 72 | ]; 73 | $this->assertFalse($address->oeGeoBlockingIsUserChangingAddress($data)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/Integration/Model/CountryTest.php: -------------------------------------------------------------------------------- 1 | setId('test_model_id'); 23 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(1); 24 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id'); 25 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 26 | $countryToShop->save(); 27 | 28 | $countryToShop = new CountryToShop(); 29 | $countryToShop->setId('test_model_id2'); 30 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(1); 31 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id2'); 32 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(0); 33 | $countryToShop->save(); 34 | 35 | $address = new Country(); 36 | $address->setId('country_id'); 37 | $address->save(); 38 | 39 | $address2 = new Country(); 40 | $address2->setId('country_id2'); 41 | $address2->save(); 42 | } 43 | 44 | public function testWhenCountryInvoiceOnly() 45 | { 46 | /** @var \OxidEsales\GeoBlocking\Model\Country $country */ 47 | $country = oxNew(Country::class); 48 | $country->load('country_id'); 49 | $this->assertTrue($country->oeGeoBlockingIsInvoiceOnly()); 50 | } 51 | 52 | public function testWhenCountryIsNotInvoiceOnly() 53 | { 54 | /** @var \OxidEsales\GeoBlocking\Model\Country $country */ 55 | $country = oxNew(Country::class); 56 | $country->load('country_id2'); 57 | $this->assertFalse($country->oeGeoBlockingIsInvoiceOnly()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/Integration/Model/UserAddressListTest.php: -------------------------------------------------------------------------------- 1 | setId('user_id'); 27 | $user->assign([ 28 | 'oxusername' => 'test', 29 | 'oxpassword' => md5('test') 30 | ]); 31 | $user->save(); 32 | 33 | $countryToShop = new CountryToShop(); 34 | $countryToShop->setId('test_model_id'); 35 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 36 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('country_id'); 37 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('address_id'); 38 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(0); 39 | $countryToShop->oegeoblocking_country_to_shop__pickup_address_active = new Field(1); 40 | $countryToShop->save(); 41 | 42 | $country = new Country(); 43 | $country->setId('country_id'); 44 | $country->save(); 45 | 46 | $address = new Address(); 47 | $address->setId('address_id'); 48 | $address->oxaddress__oxuserid = new Field('any'); 49 | $address->oxaddress__oxcountryid = new Field('country_id'); 50 | $address->save(); 51 | 52 | $address2 = new Address(); 53 | $address2->setId('address_id2'); 54 | $address2->oxaddress__oxuserid = new Field('user_id'); 55 | $address2->oxaddress__oxcountryid = new Field('country_id'); 56 | $address2->save(); 57 | 58 | $address3 = new Address(); 59 | $address3->setId('address_id3'); 60 | $address3->oxaddress__oxuserid = new Field('any_user'); 61 | $address3->oxaddress__oxcountryid = new Field('country_id'); 62 | $address3->save(); 63 | } 64 | 65 | public function testListLoadingWithExtraPickupAddress() 66 | { 67 | Registry::getConfig()->setAdminMode(false); 68 | 69 | /** @var \OxidEsales\GeoBlocking\Model\UserAddressList $userAddressList */ 70 | $userAddressList = oxNew(UserAddressList::class); 71 | $userAddressList->load('user_id'); 72 | 73 | $this->assertSame(2, count($userAddressList)); 74 | $this->assertSame('address_id2', $userAddressList->current()->getId()); 75 | $userAddressList->next(); 76 | $this->assertSame('address_id', $userAddressList->current()->getId()); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /tests/Integration/Service/CountryToShopServiceTest.php: -------------------------------------------------------------------------------- 1 | setId('test_model_id'); 23 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 24 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 25 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('test_country_id'); 26 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('test_pick_up_address_id'); 27 | $countryToShop->oegeoblocking_country_to_shop__pickup_address_active = new Field(1); 28 | $countryToShop->save(); 29 | } 30 | 31 | public function tearDown(): void 32 | { 33 | parent::tearDown(); 34 | 35 | $countryToShop = new CountryToShop(); 36 | $countryToShop->load('test_model_id'); 37 | $countryToShop->delete(); 38 | } 39 | 40 | public function testGetByCountryId() 41 | { 42 | $service = new \OxidEsales\GeoBlocking\Service\CountryToShopService(); 43 | $invoiceCountry = $service->getByCountryId('test_country_id'); 44 | 45 | $this->assertSame('test_pick_up_address_id', $invoiceCountry->oegeoblocking_country_to_shop__pickup_addressid->value); 46 | } 47 | 48 | public function testGetByCountryIdWhenNonExistingIdProvided() 49 | { 50 | $service = new \OxidEsales\GeoBlocking\Service\CountryToShopService(); 51 | $invoiceCountry = $service->getByCountryId('non_existing'); 52 | 53 | $this->assertSame('non_existing', $invoiceCountry->oegeoblocking_country_to_shop__oxcountryid->value); 54 | } 55 | 56 | public function testGetByAddressId() 57 | { 58 | $service = new \OxidEsales\GeoBlocking\Service\CountryToShopService(); 59 | $invoiceCountry = $service->getByAddressId('test_pick_up_address_id'); 60 | 61 | $this->assertSame('test_model_id', $invoiceCountry->getId()); 62 | } 63 | 64 | public function testGetByAddressIdWhenNonExistingIdProvided() 65 | { 66 | $service = new \OxidEsales\GeoBlocking\Service\CountryToShopService(); 67 | $invoiceCountry = $service->getByAddressId('not_existing'); 68 | 69 | $this->assertSame(null, $invoiceCountry->getId()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/Integration/Service/NotInvoiceOnlyCountryListServiceTest.php: -------------------------------------------------------------------------------- 1 | execute("DELETE FROM oxcountry"); 24 | 25 | $country1 = new Country(); 26 | $country1->setId('test_country_id'); 27 | $country1->oxcountry__oxactive = new Field(1); 28 | $country1->save(); 29 | $country2 = new Country(); 30 | $country2->setId('test_country_id2'); 31 | $country2->oxcountry__oxactive = new Field(1); 32 | $country2->save(); 33 | 34 | $countryToShop = new CountryToShop(); 35 | $countryToShop->setId('test_model_id'); 36 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 37 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(0); 38 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('test_country_id'); 39 | $countryToShop->oegeoblocking_country_to_shop__pickup_address_active = new Field(1); 40 | $countryToShop->save(); 41 | 42 | $countryToShop = new CountryToShop(); 43 | $countryToShop->setId('test_model_id2'); 44 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 45 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 46 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('test_country_id2'); 47 | $countryToShop->oegeoblocking_country_to_shop__pickup_address_active = new Field(1); 48 | $countryToShop->save(); 49 | } 50 | 51 | public function testGetWithSelectedLanguage() 52 | { 53 | $service = new NotInvoiceOnlyCountryListService(); 54 | 55 | $countryList = $service->getWithSelectedLanguage(0); 56 | $this->assertSame(1, count($countryList)); 57 | /** @var Country $country */ 58 | foreach ($countryList as $country) { 59 | $this->assertSame('test_country_id', $country->getId()); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests/Integration/Service/PickupAddressServiceTest.php: -------------------------------------------------------------------------------- 1 | setId('test_pick_up_address_id'); 25 | $address->save(); 26 | 27 | $countryToShop = new CountryToShop(); 28 | $countryToShop->setId('test_model_id'); 29 | $countryToShop->oegeoblocking_country_to_shop__oxshopid = new Field(Registry::getConfig()->getShopId()); 30 | $countryToShop->oegeoblocking_country_to_shop__invoice_only = new Field(1); 31 | $countryToShop->oegeoblocking_country_to_shop__oxcountryid = new Field('test_country_id'); 32 | $countryToShop->oegeoblocking_country_to_shop__pickup_addressid = new Field('test_pick_up_address_id'); 33 | $countryToShop->oegeoblocking_country_to_shop__pickup_address_active = new Field(1); 34 | $countryToShop->save(); 35 | } 36 | 37 | public function tearDown(): void 38 | { 39 | parent::tearDown(); 40 | 41 | $address = new Address(); 42 | $address->load('test_pick_up_address_id'); 43 | $address->delete(); 44 | 45 | $countryToShop = new CountryToShop(); 46 | $countryToShop->load('test_model_id'); 47 | $countryToShop->delete(); 48 | } 49 | 50 | public function testGetByCountryId() 51 | { 52 | $service = new PickupAddressService(); 53 | $address = $service->getByCountryId('test_country_id'); 54 | 55 | $this->assertSame('test_pick_up_address_id', $address->getId()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/PhpMd/standard.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | Standard OXID Ruleset 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/PhpStan/phpstan-bootstrap.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Oxid Coding Standard 4 | 5 | 6 | ../src/ 7 | 12 | ./tests/Codeception/Config 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | ./ 32 | 33 | 34 | 35 | 36 | ./ 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | Integration/ 26 | 27 | 28 | 29 | 30 | ../src 31 | 32 | 33 | -------------------------------------------------------------------------------- /translations/de/oegeoblocking_lang.php: -------------------------------------------------------------------------------- 1 | 'UTF-8', 7 | 8 | 'OEGEOBLOCKING_HINT' => "Leider liefern wir nicht in Ihr Land. Bitte wählen oder erstellen Sie eine gültige Lieferadresse!", 9 | 'OEGEOBLOCKING_PICKUP_ADDRESS' => "Abholadresse", 10 | 'OEGEOBLOCKING_YOUR_ADDRESS' => "Ihre Lieferadresse", 11 | 'OEGEOBLOCKING_ERROR_MESSAGE_INPUT_COUNTRY_NOT_ALLOWED' => 'Leider ist keine Lieferung in das aktuelle Lieferland möglich. Bitte geben Sie eine gültige Lieferadresse an!', 12 | 'OEGEOBLOCKING_ERROR_MESSAGE_INPUT_COUNTRY_INCORRECT' => 'Die übermittelte Abholadresse ist für die Rechnungsadresse nicht gültig. Bitte wählen Sie eine gültige Abholadresse oder geben Sie eine Lieferadresse ein!', 13 | 'OEGEOBLOCKING_INVALID_ADDRESS' => "Ungültige Lieferadresse", 14 | 'OEGEOBLOCKING_INVALID' => "Ungültig", 15 | 'OEGEOBLOCKING_MUST_CHOOSE_DELADDR' => "Sie müssen eine von der Rechnungsadresse abweichende Lieferadresse wählen!", 16 | 'OEGEOBLOCKING_PICKUP_ADDRESS_CHANGE_NOT_ALLOWED' => "Es ist nicht zulässig, diese Lieferadresse zu ändern. Bitte wählen Sie eine Alternative oder fügen eine neue hinzu!", 17 | ]; 18 | -------------------------------------------------------------------------------- /translations/en/oegeoblocking_lang.php: -------------------------------------------------------------------------------- 1 | 'UTF-8', 7 | 8 | 'OEGEOBLOCKING_HINT' => "Unfortunately, we do not deliver to your country. Please choose or register a valid delivery address!", 9 | 'OEGEOBLOCKING_PICKUP_ADDRESS' => "Pickup Address", 10 | 'OEGEOBLOCKING_YOUR_ADDRESS' => "Your shipping address", 11 | 'OEGEOBLOCKING_ERROR_MESSAGE_INPUT_COUNTRY_NOT_ALLOWED' => 'Delivery to this country is not possible. Please select another country in your shipping address!', 12 | 'OEGEOBLOCKING_ERROR_MESSAGE_INPUT_COUNTRY_INCORRECT' => 'The pickup address is invalid. Please select the valid pickup address or enter an alternative shipping address!', 13 | 'OEGEOBLOCKING_INVALID_ADDRESS' => "Invalid shipping address", 14 | 'OEGEOBLOCKING_INVALID' => "Invalid", 15 | 'OEGEOBLOCKING_MUST_CHOOSE_DELADDR' => "You must select a different shipping address than your billing address!", 16 | 'OEGEOBLOCKING_PICKUP_ADDRESS_CHANGE_NOT_ALLOWED' => "It is not allowed to change this shipping address. Please choose an alternative or add a new one!", 17 | ]; 18 | -------------------------------------------------------------------------------- /views/admin_twig/de/oegeoblocking_lang.php: -------------------------------------------------------------------------------- 1 | 'UTF-8', 7 | 8 | 'OEGEOBLOCKING_INVOICEONLY' => 'Land gehört nicht zum Liefergebiet', 9 | 'OEGEOBLOCKING_INVOICEONLY_HELP' => 'Bestellungen aus diesem Land sind möglich, es kann jedoch nicht beliefert werden. Kunden müssen spätestens im Bestellprozess eine Lieferadresse in einem Land angeben, das beliefert wird.', 10 | 'OEGEOBLOCKING_ADMIN_PICKUP_ADDRESS' => 'Abholadresse', 11 | ); 12 | -------------------------------------------------------------------------------- /views/admin_twig/en/oegeoblocking_lang.php: -------------------------------------------------------------------------------- 1 | 'UTF-8', 7 | 8 | 'OEGEOBLOCKING_INVOICEONLY' => 'We\'ll not deliver to this country', 9 | 'OEGEOBLOCKING_INVOICEONLY_HELP' => 'Orders from this country are possible, but cannot be delivered. Customers must specify a delivery address in a country that we deliver to at the latest during checkout.', 10 | 'OEGEOBLOCKING_ADMIN_PICKUP_ADDRESS' => 'Pickup address', 11 | ); 12 | -------------------------------------------------------------------------------- /views/twig/extensions/themes/admin_twig/country_main.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'country_main.html.twig' %} 2 | {% block admin_country_main_form %} 3 | {{ parent() }} 4 | {% block oegeoblocking_admin_country_main %} 5 | 6 | 7 | {{ translate({ ident: "OEGEOBLOCKING_INVOICEONLY" }) }} 8 | 9 | 10 | 11 | 12 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("OEGEOBLOCKING_INVOICEONLY_HELP"), 'sHelpText': help_text("OEGEOBLOCKING_INVOICEONLY_HELP")} %} 13 | 14 | 15 | 16 |
17 | 18 |
19 | {{ translate({ ident: "OEGEOBLOCKING_ADMIN_PICKUP_ADDRESS" }) }} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 34 | 35 | 36 | 39 | 47 | 48 | 49 | 52 | 57 | 58 | 59 | 62 | 66 | 67 | 68 | 71 | 76 | 77 | 78 | 81 | 86 | 87 | 88 | 91 | 95 | 96 | 97 | 100 | 109 | 110 | 111 | 114 | 118 | 119 | 120 | 123 | 127 | 128 |
27 | {{ translate({ ident: "GENERAL_ACTIVE" }) }} 28 | 30 | 31 | 32 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_ACTIVE"), 'sHelpText': help_text("HELP_GENERAL_ACTIVE")} %} 33 |
37 | {{ translate({ ident: "GENERAL_BILLSAL" }) }} 38 | 40 | 45 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_BILLSAL"), 'sHelpText': help_text("HELP_GENERAL_BILLSAL")} %} 46 |
50 | {{ translate({ ident: "USER_MAIN_NAME" }) }} 51 | 53 | 54 | 55 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_USER_MAIN_NAME"), 'sHelpText': help_text("HELP_USER_MAIN_NAME")} %} 56 |
60 | {{ translate({ ident: "GENERAL_COMPANY" }) }} 61 | 63 | 64 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_COMPANY"), 'sHelpText': help_text("HELP_GENERAL_COMPANY")} %} 65 |
69 | {{ translate({ ident: "USER_MAIN_STRNR" }) }} 70 | 72 | 73 | 74 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_USER_MAIN_STRNR"), 'sHelpText': help_text("HELP_USER_MAIN_STRNR")} %} 75 |
79 | {{ translate({ ident: "GENERAL_ZIPCITY" }) }} 80 | 82 | 83 | 84 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_ZIPCITY"), 'sHelpText': help_text("HELP_GENERAL_ZIPCITY")} %} 85 |
89 | {{ translate({ ident: "GENERAL_EXTRAINFO" }) }} 90 | 92 | 93 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_EXTRAINFO"), 'sHelpText': help_text("HELP_GENERAL_EXTRAINFO")} %} 94 |
98 | {{ translate({ ident: "GENERAL_COUNTRY" }) }} 99 | 101 | 107 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_COUNTRY"), 'sHelpText': help_text("HELP_GENERAL_COUNTRY")} %} 108 |
112 | {{ translate({ ident: "GENERAL_TELEPHONE" }) }} 113 | 115 | 116 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_TELEPHONE"), 'sHelpText': help_text("HELP_GENERAL_TELEPHONE")} %} 117 |
121 | {{ translate({ ident: "GENERAL_FAX" }) }} 122 | 124 | 125 | {% include "inputhelp.html.twig" with {'sHelpId': help_id("HELP_GENERAL_FAX"), 'sHelpText': help_text("HELP_GENERAL_FAX")} %} 126 |
129 |
130 | {% endblock %} 131 | 132 |
133 | 134 | 135 | 136 | {% endblock %} 137 | -------------------------------------------------------------------------------- /views/twig/extensions/themes/apex/form/fieldset/user_billing.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'form/fieldset/user_billing.html.twig' %} 2 | {% block form_user_billing_country %} 3 | {{ parent() }} 4 | {% block oegeoblocking_form_user_billing_country %} 5 | {% for country in oViewConf.getCountryList() %} 6 | {% if country.oeGeoBlockingIsInvoiceOnly() %} 7 | 8 | {% set scriptToMarkCountryElement = 'document.querySelector(\'#invCountrySelect option[value="'|cat(country.oxcountry__oxid.value)|cat('"]\').dataset.invoiceonly=\'true\';') %} 9 | {{ script({ add: scriptToMarkCountryElement, dynamic: __oxid_include_dynamic }) }} 10 | 11 | {{ script({ add: ' 12 | var userChangeAddress = document.getElementById(\'userChangeAddress\'); 13 | 14 | if (userChangeAddress) { 15 | userChangeAddress.addEventListener(\'click\', moveMessageElement); 16 | } 17 | 18 | function moveMessageElement(evt) { 19 | var messageElement = document.querySelector("#oegb-hint-message"); 20 | messageElement.parentNode.removeChild(messageElement); 21 | document.querySelector("#invCountrySelect").parentNode.parentNode.appendChild(messageElement); 22 | } 23 | ', dynamic: __oxid_include_dynamic }) }} 24 | {% endif %} 25 | {% endfor %} 26 | {{ script({ include: oViewConf.getModuleUrl('oegeoblocking','out/src/js/oegeoblocking.js'), priority: 11, dynamic: __oxid_include_dynamic }) }} 27 | {% endblock %} 28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /views/twig/extensions/themes/apex/form/fieldset/user_shipping.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'form/fieldset/user_shipping.html.twig' %} 2 | {% block form_user_shipping_country %} 3 | {{ parent() }} 4 | {% block oegeoblocking_form_user_shipping_country %} 5 | {% for country in oViewConf.getCountryList() %} 6 | 7 | {% if country.oeGeoBlockingIsInvoiceOnly() %} 8 | {% set scriptToMarkCountryElement = ' 9 | var countryIndex = document.querySelector(\'#delCountrySelect option[value="'|cat(country.oxcountry__oxid.value)|cat('"]\').index; 10 | document.querySelector(\'#delCountrySelect\').remove(countryIndex); 11 | ') %} 12 | {{ script({ add: scriptToMarkCountryElement, dynamic: __oxid_include_dynamic }) }} 13 | {% endif %} 14 | {% endfor %} 15 | {% endblock %} 16 | {% endblock %} 17 | 18 | {% block form_user_shipping_address_select %} 19 | {{ parent() }} 20 | {% block oegeoblocking_form_user_shipping_address_select %} 21 | 22 | {% for address in aUserAddresses %} 23 | {% if not address.oeGeoBlockingCanFrontendUserChange() %} 24 | {% set scriptToHideDeleteEditButtons = ' 25 | var address = document.querySelector("input[name=\'oxaddressid\'][value=\''|cat(address.getId())|cat('\']"); 26 | if (address.checked) { 27 | var buttons = address.closest(\'.list-group-item\').querySelector(\'.address-info\').querySelectorAll(\'.dd-action\'); 28 | buttons.forEach((button) => button.parentNode.removeChild(button)); 29 | } 30 | ') %} 31 | {{ script({ add: scriptToHideDeleteEditButtons, dynamic: __oxid_include_dynamic }) }} 32 | {% endif %} 33 | {% endfor %} 34 | {% endblock %} 35 | {% endblock %} 36 | -------------------------------------------------------------------------------- /views/twig/extensions/themes/apex/form/user_checkout_change.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'form/user_checkout_change.html.twig' %} 2 | {% block user_checkout_billing_feedback %} 3 | {{ parent() }} 4 | {% block oegeoblocking_user_checkout_billing_feedback %} 5 | 8 | {% endblock %} 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /views/twig/extensions/themes/twig/form/fieldset/user_billing.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'form/fieldset/user_billing.html.twig' %} 2 | {% block form_user_billing_country %} 3 | {{ parent() }} 4 | {% block oegeoblocking_form_user_billing_country %} 5 | {% for country in oViewConf.getCountryList() %} 6 | {% if country.oeGeoBlockingIsInvoiceOnly() %} 7 | 8 | {% set scriptToMarkCountryElement = '$(\'#invCountrySelect option[value="'|cat(country.oxcountry__oxid.value)|cat('"]\').attr(\'data-invoiceonly\', \'true\');') %} 9 | {{ script({ add: scriptToMarkCountryElement, dynamic: __oxid_include_dynamic }) }} 10 | 11 | {{ script({ add: ' 12 | $("#userChangeAddress").click(function(){ 13 | var messageElement = $("#oegb-hint-message").detach(); 14 | $("#invCountrySelect").parent().append(messageElement); 15 | }); 16 | ', dynamic: __oxid_include_dynamic }) }} 17 | {% endif %} 18 | {% endfor %} 19 | {{ script({ include: oViewConf.getModuleUrl('oegeoblocking','out/src/js/oegeoblocking.js'), priority: 11, dynamic: __oxid_include_dynamic }) }} 20 | {% endblock %} 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /views/twig/extensions/themes/twig/form/fieldset/user_shipping.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'form/fieldset/user_shipping.html.twig' %} 2 | {% block form_user_shipping_country %} 3 | {{ parent() }} 4 | {% block oegeoblocking_form_user_shipping_country %} 5 | {% for country in oViewConf.getCountryList() %} 6 | 7 | {% if country.oeGeoBlockingIsInvoiceOnly() %} 8 | {% set scriptToMarkCountryElement = '$(\'#delCountrySelect option[value="'|cat(country.oxcountry__oxid.value)|cat('"]\').remove();') %} 9 | {{ script({ add: scriptToMarkCountryElement, dynamic: __oxid_include_dynamic }) }} 10 | {% endif %} 11 | {% endfor %} 12 | {% endblock %} 13 | {% endblock %} 14 | 15 | {% block form_user_shipping_address_select %} 16 | {{ parent() }} 17 | {% block oegeoblocking_form_user_shipping_address_select %} 18 | 19 | {% for address in aUserAddresses %} 20 | {% if not address.oeGeoBlockingCanFrontendUserChange() %} 21 | {% set scriptToHideDeleteEditButtons = '$("input[name=\'oxaddressid\'][value=\''|cat(address.getId())|cat('\']").parent().parent().parent().find(\'.dd-action\').remove()') %} 22 | {{ script({ add: scriptToHideDeleteEditButtons, dynamic: __oxid_include_dynamic }) }} 23 | {% endif %} 24 | {% endfor %} 25 | {% endblock %} 26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /views/twig/extensions/themes/twig/form/user_checkout_change.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'form/user_checkout_change.html.twig' %} 2 | {% block user_checkout_billing_feedback %} 3 | {{ parent() }} 4 | {% block oegeoblocking_user_checkout_billing_feedback %} 5 |
6 | 11 | 14 |
15 | {% endblock %} 16 | {% endblock %} 17 | --------------------------------------------------------------------------------