├── .coveralls.yml ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── Api └── Observer │ └── FuzzyfyrObserverInterface.php ├── Block └── Adminhtml │ └── Backup.php ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Console └── Command │ ├── ExportCommand.php │ └── FuzzyfyrCommand.php ├── Handler ├── Backup │ └── DatabaseHandler.php ├── BackupHandler.php ├── CategoryImageHandler.php └── MediaFileHandler.php ├── LICENSE ├── Model ├── Backup │ └── Factory.php ├── Configuration.php └── ConfigurationFactory.php ├── Observer ├── CategoriesObserver.php ├── CategoryImageObserver.php ├── CmsBlocksObserver.php ├── CmsPagesObserver.php ├── CustomerPasswordsObserver.php ├── CustomersObserver.php ├── FuzzyfyrObserver.php ├── ProductImagesObserver.php ├── ProductsObserver.php └── UsersObserver.php ├── README.md ├── Test └── Unit │ ├── AbstractTest.php │ ├── Console │ └── Command │ │ ├── ExportCommandTest.php │ │ └── FuzzyfyrCommandTest.php │ ├── Handler │ ├── Backup │ │ └── DatabaseHandlerTest.php │ ├── BackupHandlerTest.php │ └── MediaFileHandlerTest.php │ ├── Model │ ├── Backup │ │ └── FactoryTest.php │ ├── ConfigurationFactoryTest.php │ └── ConfigurationTest.php │ ├── Observer │ ├── CategoriesObserverTest.php │ ├── CategoryImageObserverTest.php │ ├── CmsBlocksObserverTest.php │ ├── CmsPagesObserverTest.php │ ├── CustomerPasswordsObserverTest.php │ ├── CustomersObserverTest.php │ ├── FuzzyObserverTest.php │ ├── ProductImagesObserverTest.php │ ├── ProductsObserverTest.php │ └── UsersObserverTest.php │ └── bootstrap.php ├── assets └── dummy_image.png ├── bin ├── bash ├── cache-clean ├── captainhook ├── cli ├── clinotty ├── cliq ├── composer ├── copyfromcontainer ├── copytocontainer ├── cron ├── dev-test-run ├── dev-urn-catalog-generate ├── devconsole ├── download ├── fixowns ├── fixperms ├── githook ├── grunt ├── magento ├── mftf ├── mysql ├── mysqldump ├── n98-magerun2 ├── node ├── npm ├── pwa-studio ├── redis ├── remove ├── removeall ├── removevolumes ├── restart ├── root ├── rootnotty ├── setup ├── setup-composer-auth ├── setup-domain ├── setup-grunt ├── setup-integration-tests ├── setup-pwa-studio ├── setup-ssl ├── setup-ssl-ca ├── start ├── status ├── stop ├── update └── xdebug ├── captainhook.json ├── composer.json ├── docker-compose.dev.yml ├── docker-compose.yml ├── docs ├── UserGuide.docx └── UserGuide.pdf ├── env ├── db.env └── magento.env ├── etc ├── adminhtml │ ├── di.xml │ └── events.xml ├── di.xml └── module.xml ├── i18n ├── de_DE.csv ├── en_GB.csv └── en_US.csv ├── infection.json ├── phpstan.neon ├── phpunit.xml ├── registration.php ├── resources ├── aid-content-fuzzyfyr-export-1.png ├── aid-content-fuzzyfyr-export-2.png ├── aid-content-fuzzyfyr-export-3.png └── aid-content-fuzzyfyr-export-4.png └── validate_m2_package.php /.coveralls.yml: -------------------------------------------------------------------------------- 1 | coverage_clover: clover.xml 2 | json_path: coveralls-upload.json 3 | 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: composer 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | 10 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - "main" 7 | 8 | jobs: 9 | run: 10 | runs-on: ${{ matrix.operating-system }} 11 | strategy: 12 | matrix: 13 | operating-system: ['ubuntu-latest'] 14 | php-versions: ['7.4'] 15 | magento: ['2.3.7-p2', '2.4.0', '2.4.1', '2.4.2', '2.4.3'] 16 | coveralls: [ false ] 17 | include: 18 | - operating-system: 'ubuntu-latest' 19 | php-versions: '8.1' 20 | magento: '2.4.4' 21 | coveralls: true 22 | 23 | steps: 24 | - name: Checkout repo 25 | uses: actions/checkout@v2 26 | 27 | - name: Configure PHP 28 | uses: shivammathur/setup-php@v2 29 | with: 30 | php-version: ${{ matrix.php-versions }} 31 | tools: composer:v2 32 | coverage: xdebug 33 | extensions: bcmath, gd 34 | 35 | - name: Install Composer dependencies 36 | run: composer install 37 | 38 | - name: Install Magento 2.3.7-p2 39 | if: matrix.magento == '2.3.7-p2' 40 | run: composer update --with-dependencies magento/framework:102.0.7-p2 magento/module-catalog:103.0.7-p2 magento/module-cms:103.0.7-p2 magento/module-customer:102.0.7-p2 magento/module-user:101.1.7 infection/infection:0.22.0 41 | 42 | - name: Install Magento 2.4.0 43 | if: matrix.magento == '2.4.0' 44 | run: composer update --with-dependencies magento/framework:103.0.0 magento/module-catalog:104.0.0 magento/module-cms:104.0.0 magento/module-customer:103.0.0 magento/module-user:101.2.0 infection/infection:0.22.0 45 | 46 | - name: Install Magento 2.4.1 47 | if: matrix.magento == '2.4.1' 48 | run: composer update --with-dependencies magento/framework:103.0.1 magento/module-catalog:104.0.1 magento/module-cms:104.0.1 magento/module-customer:103.0.1 magento/module-user:101.2.1 infection/infection:0.22.0 49 | 50 | - name: Install Magento 2.4.2 51 | if: matrix.magento == '2.4.2' 52 | run: composer update --with-dependencies magento/framework:103.0.2 magento/module-catalog:104.0.2 magento/module-cms:104.0.2 magento/module-customer:103.0.2 magento/module-user:101.2.2 53 | 54 | - name: Install Magento 2.4.3 55 | if: matrix.magento == '2.4.3' 56 | run: composer update --with-dependencies magento/framework:103.0.3 magento/module-catalog:104.0.3 magento/module-cms:104.0.3 magento/module-customer:103.0.3 magento/module-user:101.2.3 57 | 58 | - name: Install Magento 2.4.4 59 | if: matrix.magento == '2.4.4' 60 | run: composer update --with-dependencies magento/framework:103.0.4 magento/module-catalog:104.0.4 magento/module-cms:104.0.4 magento/module-customer:103.0.4 magento/module-user:101.2.4 61 | 62 | - name: Codesniffer 63 | run: composer cs-check 64 | 65 | - name: Static code analysis 66 | run: composer analyze 67 | 68 | - name: Unittests 69 | run: composer test 70 | if: matrix.coveralls == false 71 | 72 | - name: Unittests with coverage 73 | if: matrix.coveralls == true 74 | run: composer coverage 75 | 76 | - name: Coveralls report 77 | if: matrix.coveralls == true 78 | env: 79 | COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} 80 | run: | 81 | composer require php-coveralls/php-coveralls 82 | ./vendor/bin/php-coveralls --coverage_clover=clover.xml -v 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.docker 3 | /vendor 4 | /dist 5 | /build 6 | .phpunit.result.cache 7 | clover.xml 8 | composer.lock 9 | composer.phar 10 | infection.log 11 | rootCA.pem 12 | -------------------------------------------------------------------------------- /Api/Observer/FuzzyfyrObserverInterface.php: -------------------------------------------------------------------------------- 1 | getToolbar(); 35 | if ($toolbar instanceof BlockInterface) { 36 | /** @var \Magento\Framework\View\Element\AbstractBlock $toolbar */ 37 | $toolbar->addChild( 38 | 'createGdprConformDatabaseBackupButton', 39 | Button::class, 40 | [ 41 | 'label' => __('GDPR conform Database Backup (Content Fuzzyfyr)'), 42 | 'onclick' => "return backup.backup('" . Factory::TYPE_GDPR_DB . "')", 43 | 'class' => 'task primary aid-content-export' 44 | ] 45 | ); 46 | } 47 | } 48 | //@codeCoverageIgnoreEnd 49 | } 50 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file, in reverse chronological order by release. 4 | 5 | ## 1.9.0 6 | 7 | ### Added 8 | 9 | - [#77](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/77) Make module compatible with Magento 2.4.4 10 | - [#75](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/75) Bump phpstan/phpstan to 1.5 11 | - [#72](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/72) Bump bitexpert/captainhook-infection to 0.6.0 12 | - [#64](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/64) Bump phpunit/phpunit to 9.5.20 13 | - [#60](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/60) Bump guzzlehttp/psr7 to 1.8.5 14 | - [#58](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/58) Bump bitexpert/phpstan-magento to 0.19.0 15 | - [#51](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/51) Bump infection/infection to 0.26.6 16 | - [#49](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/49) Bump captainhook/captainhook to 5.10.8 17 | - [#37](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/37) Bump captainhook/plugin-composer to 5.3.3 18 | - [#20](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/20) Bump squizlabs/php_codesniffer to 3.6.2 19 | - [#17](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/17) Bump magento/magento-coding-standard to 15 20 | 21 | ### Deprecated 22 | 23 | - Nothing. 24 | 25 | ### Removed 26 | 27 | - Nothing. 28 | 29 | ### Fixed 30 | 31 | - Nothing. 32 | 33 | ## 1.8.1 34 | 35 | ### Added 36 | 37 | - Nothing. 38 | 39 | ### Deprecated 40 | 41 | - Nothing. 42 | 43 | ### Removed 44 | 45 | - Nothing. 46 | 47 | ### Fixed 48 | 49 | - [#16](https://github.com/hivecommerce/magento2-content-fuzzyfyr/pull/16) Turn captainhook-infection into dev dependency 50 | 51 | ## 1.8.0 52 | 53 | ### Added 54 | 55 | - Add Mark Shust's Docker setup to simplify local development 56 | 57 | ### Deprecated 58 | 59 | - Nothing. 60 | 61 | ### Removed 62 | 63 | - Nothing. 64 | 65 | ### Fixed 66 | 67 | - Made hivecommerce/magento2-content-fuzzyfyr compatible with Magento 2.4.0 - 2.4.3 68 | - Migrated from allin-data/magento2-content-fuzzyfyr to hivecommerce/magento2-content-fuzzyfyr 69 | 70 | ## 1.7.0 71 | 72 | - Extended customer fuzzyfier to fuzzyfy quote and order addresses. 73 | 74 | ## 1.6.0 75 | 76 | - Extended customer fuzzyfyier to alter customer password. 77 | - Added --force flag to fuzzyfyr command to allow execution in production mode. 78 | 79 | ## 1.5.0 80 | 81 | - Extended backup UI in administration area to allow convenient export of database dump matching GDPR compliance 82 | 83 | ## 1.4.0 84 | 85 | - Added feature to add dummy images for products and categories 86 | 87 | ## 1.3.0 88 | 89 | - Added feature to export database with fuzzyfied content without altering current database content persistently. 90 | 91 | ## 1.2.0 92 | 93 | - Added unit test 94 | - Fixed validation check on products fuzzyfyr 95 | - Added missing folder to development environment and build script 96 | 97 | ## 1.1.0 98 | 99 | - Added default value for URLs 100 | - Added possibility to extend data on configuration model 101 | - Refactored fuzzyfyr structure 102 | - Simplified extension of configuration model 103 | - Added fuzzyfyr for CMS Pages 104 | - Added fuzzyfyr for CMS Blocks 105 | - Extended fuzzyfyr for Customers with address fuzzing 106 | - Changed implementation of fuzzyfyr for Products and Categories to match with EQP of *Magento® 2* 107 | 108 | ## 1.0.1 109 | 110 | - Extended documentation 111 | - Placed DI configuration into global scope 112 | 113 | ## 1.0.0 114 | 115 | - Initial release of the **Content Fuzzyfyr** module for *Magento® 2*. 116 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | ## Resources 4 | 5 | If you wish to contribute to Content Fuzzyfyr Module, please be sure to 6 | read/subscribe to the following resources: 7 | 8 | - [The PSR-2 Coding Standard](http://www.php-fig.org/psr/psr-2/) 9 | 10 | If you are working on new features or refactoring [create a proposal](https://github.com/hivecommerce/magento2-content-fuzzyfyr/issues/new). 11 | 12 | ## Reporting Potential Security Issues 13 | 14 | If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [info@all-in-data.de](mailto:info@all-in-data.de) instead. 15 | We will work with you to verify the vulnerability and patch it as soon as possible. 16 | 17 | When reporting issues, please provide the following information: 18 | 19 | - Component(s) affected 20 | - A description indicating how to reproduce the issue 21 | - A summary of the security vulnerability and impact 22 | 23 | We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure. 24 | This helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. 25 | 26 | For sensitive email communications, please use [our PGP key](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x6DE7F8597CECDF13). 27 | 28 | ## Running Tests 29 | 30 | To run tests: 31 | 32 | 1. Clone the repository: 33 | 34 | ```console 35 | $ git clone git@github.com:allin-data/magento2-content-fuzzyfyr.git 36 | $ cd magento2-content-fuzzyfyr 37 | ``` 38 | 39 | 2. Install dependencies via composer: 40 | 41 | ```console 42 | $ ./composer.phar install 43 | ``` 44 | 45 | If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/download/ 46 | 47 | 3. Run the tests using the "test" command shipped in the `composer.json`: 48 | 49 | ```console 50 | $ composer test 51 | ``` 52 | 53 | You can turn on conditional tests with the `phpunit.xml` file. 54 | To do so: 55 | 56 | - Copy `phpunit.xml.dist` file to `phpunit.xml` 57 | - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. 58 | 59 | ## Running Coding Standards Checks 60 | 61 | First, ensure you've installed dependencies via composer, per the previous section on running tests. 62 | To run CS checks only: 63 | 64 | ```console 65 | $ composer cs-check 66 | ``` 67 | 68 | To attempt to automatically fix common CS issues: 69 | 70 | ```console 71 | $ composer cs-fix 72 | ``` 73 | 74 | If the above fixes any CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. 75 | 76 | ## Recommended Workflow for Contributions 77 | 78 | Your first step is to establish a public repository from which we can pull your work into the master repository. 79 | We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 80 | 81 | 1. Setup a [GitHub account](http://github.com/), if you haven't yet 82 | 2. Fork the repository (http://github.com/hivecommerce/magento2-content-fuzzyfyr) 83 | 3. Clone the canonical repository locally and enter it. 84 | 85 | ```console 86 | $ git clone git://github.com:allin-data/magento2-content-fuzzyfyr.git 87 | $ cd magento2-content-fuzzyfyr 88 | ``` 89 | 90 | 4. Add a remote to your fork; substitute your GitHub username in the command 91 | below. 92 | 93 | ```console 94 | $ git remote add {username} git@github.com:{username}/magento2-content-fuzzyfyr.git 95 | $ git fetch {username} 96 | ``` 97 | 98 | ### Keeping Up-to-Date 99 | 100 | Periodically, you should update your fork or personal repository to match the canonical Content Fuzzyfyr Module repository. 101 | Assuming you have setup your local repository per the instructions above, you can do the following: 102 | 103 | ```console 104 | $ git checkout master 105 | $ git fetch origin 106 | $ git rebase origin/master 107 | # OPTIONALLY, to keep your remote up-to-date - 108 | $ git push {username} master:master 109 | ``` 110 | 111 | If you're tracking other branches you'll want to do the same operations for those branches; simply substitute the branch names for "master". 112 | 113 | ### Working on a patch 114 | 115 | We recommend you do each new feature or bugfix in a new branch. 116 | This simplifies the task of code review as well as the task of merging your changes into the canonical repository. 117 | 118 | A typical workflow will then consist of the following: 119 | 120 | 1. Create a new local branch based off your master branch. 121 | 2. Switch to your new local branch. (This step can be combined with the 122 | previous step with the use of `git checkout -b`.) 123 | 3. Do some work, commit, repeat as necessary. 124 | 4. Push the local branch to your remote repository. 125 | 5. Send a pull request. 126 | 127 | The mechanics of this process are actually quite trivial. 128 | Below, we will create a branch for fixing an issue in the tracker. 129 | 130 | ```console 131 | $ git checkout -b hotfix/9295 132 | Switched to a new branch 'hotfix/9295' 133 | ``` 134 | 135 | ...do some work... 136 | 137 | ```console 138 | $ git commit 139 | ``` 140 | 141 | ...write your log message... 142 | 143 | ```console 144 | $ git push {username} hotfix/9295:hotfix/9295 145 | Counting objects: 38, done. 146 | Delta compression using up to 2 threads. 147 | Compression objects: 100% (18/18), done. 148 | Writing objects: 100% (20/20), 8.19KiB, done. 149 | Total 20 (delta 12), reused 0 (delta 0) 150 | To ssh://git@github.com/{username}/magento2-content-fuzzyfyr.git 151 | b5583aa..4f51698 HEAD -> master 152 | ``` 153 | ### Sending a PR 154 | 155 | Before sending a PR, run `composer.phar validate && composer.phar check`, as the Travis build will also run the command and will fail if the composer.lock file is not up-to-date with the changes in the composer.json file. 156 | 157 | When you’ve done that, and you’re reading to send one, you have two options: 158 | 159 | 1. If using GitHub, you can do the pull request from there. 160 | Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "allin-data" as the recipient. 161 | 162 | 2. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. 163 | 164 | #### What Branch to Issue the Pull Request Against? 165 | 166 | Which branch should you issue a pull request against? 167 | 168 | - For fixes against the stable release, issue the pull request against the latest release branch. 169 | - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "master" branch. 170 | 171 | ### Branch Cleanup 172 | 173 | As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. 174 | Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. 175 | 176 | - Local branch cleanup 177 | 178 | ```console 179 | $ git branch -d 180 | ``` 181 | 182 | - Remote branch removal 183 | 184 | ```console 185 | $ git push {username} : 186 | ``` 187 | -------------------------------------------------------------------------------- /Handler/Backup/DatabaseHandler.php: -------------------------------------------------------------------------------- 1 | eventManager = $eventManager; 60 | $this->configurationFactory = $configurationFactory; 61 | $this->backupHandler = $backupHandler; 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function create() 68 | { 69 | /* 70 | * Processing 71 | */ 72 | $this->backupHandler->beginTransaction(); 73 | 74 | try { 75 | $this->eventManager->dispatch(ExportCommand::EVENT_NAME, [ 76 | 'configuration' => $this->loadConfiguration() 77 | ]); 78 | 79 | if (!parent::create()) { 80 | throw new RuntimeException('Failed to create database backup'); 81 | } 82 | } catch (Exception $e) { 83 | $this->backupHandler->endTransaction(); 84 | return false; 85 | } 86 | 87 | $this->backupHandler->endTransaction(); 88 | return true; 89 | } 90 | 91 | /** 92 | * Add path that should be ignoring when creating or rolling back backup 93 | * 94 | * @param string|array $paths 95 | * @return $this 96 | */ 97 | public function addIgnorePaths($paths) 98 | { 99 | return $this; 100 | } 101 | 102 | /** 103 | * @return Configuration 104 | */ 105 | protected function loadConfiguration() 106 | { 107 | $configuration = $this->configurationFactory->create(); 108 | // --- Flags 109 | $configuration->setApplyToUsers(true); 110 | $configuration->setApplyToCustomers(true); 111 | // --- Options 112 | $configuration->setDummyContentText(ExportCommand::DEFAULT_DUMMY_CONTENT_TEXT); 113 | $configuration->setDummyContentEmail(ExportCommand::DEFAULT_DUMMY_CONTENT_EMAIL); 114 | $configuration->setDummyContentUrl(ExportCommand::DEFAULT_DUMMY_CONTENT_URL); 115 | $configuration->setDummyPhoneNumber(ExportCommand::DEFAULT_DUMMY_CONTENT_PHONE); 116 | 117 | return $configuration; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Handler/BackupHandler.php: -------------------------------------------------------------------------------- 1 | maintenanceMode = $maintenanceMode; 69 | $this->backupRollbackFactory = $backupRollbackFactory; 70 | $this->setup = $setup; 71 | $this->ioFile = $ioFile; 72 | } 73 | 74 | /** 75 | * Begin database transaction 76 | * 77 | * @return void 78 | */ 79 | public function beginTransaction(): void 80 | { 81 | $this->maintenanceModeInitialState = $this->maintenanceMode->isOn(); 82 | $this->maintenanceMode->set(true); 83 | $this->setup->getConnection()->beginTransaction(); 84 | } 85 | 86 | /** 87 | * End database transaction 88 | * 89 | * @return void 90 | */ 91 | public function endTransaction(): void 92 | { 93 | $this->setup->getConnection()->rollBack(); 94 | // disable maintenance only, if it has been disabled in the beginning 95 | if (!$this->maintenanceModeInitialState) { 96 | $this->maintenanceMode->set(false); 97 | 98 | } 99 | } 100 | 101 | /** 102 | * @param OutputInterface $output 103 | * @param string $backupPath 104 | * @return void 105 | * @throws Exception 106 | */ 107 | public function run(OutputInterface $output, string $backupPath): void 108 | { 109 | /* 110 | * Backup path 111 | */ 112 | try { 113 | $backupPath = realpath($backupPath); 114 | if ($backupPath !== false) { 115 | $this->ioFile->checkAndCreateFolder($backupPath, self::BACKUP_DIRECTORY_FILEMODE); 116 | } else { 117 | throw new \RuntimeException('Could not create backup folder'); 118 | } 119 | } catch (LocalizedException $e) { 120 | throw new \RuntimeException( 121 | sprintf( 122 | 'Could not create backup folder: "%s"', 123 | $backupPath 124 | ) 125 | ); 126 | } 127 | 128 | /* 129 | * Backup Handler 130 | */ 131 | $backupHandler = $this->backupRollbackFactory->create($output); 132 | $backupFile = $backupHandler->dbBackup(time()); 133 | 134 | $backupPath .= DIRECTORY_SEPARATOR . basename($backupFile); 135 | $backupPath = str_replace(DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, $backupPath); 136 | if ($backupFile !== $backupPath && 137 | !$this->ioFile->cp($backupFile, $backupPath)) { 138 | throw new \RuntimeException( 139 | sprintf( 140 | 'Failed to copy backup file "%s" to target "%s"', 141 | $backupFile, 142 | $backupPath 143 | ) 144 | ); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /Handler/CategoryImageHandler.php: -------------------------------------------------------------------------------- 1 | mediaConfig = $mediaConfig; 59 | $this->fileSystem = $fileSystem; 60 | $this->ioFile = $ioFile; 61 | } 62 | 63 | /** 64 | * @param string $filePath 65 | * @return string 66 | * @throws FileSystemException 67 | */ 68 | public function getMediaCopyOfFile(string $filePath): string 69 | { 70 | $this->init(); 71 | 72 | $mediaFilePath = $this->mediaDirectory->getAbsolutePath( 73 | sprintf( 74 | '%s/%s', 75 | static::MEDIA_MODULE_BASE_PATH, 76 | basename($filePath) 77 | ) 78 | ); 79 | 80 | // short exit if media file already exists 81 | if ($this->ioFile->fileExists($mediaFilePath, true)) { 82 | return $mediaFilePath; 83 | } 84 | 85 | /* 86 | * Check on requested file 87 | */ 88 | $filePath = $this->ioFile->getCleanPath($filePath); 89 | if (!$this->ioFile->fileExists($filePath, true)) { 90 | throw new \InvalidArgumentException( 91 | sprintf( 92 | 'Could not resolve given image path: "%s"', 93 | $filePath 94 | ) 95 | ); 96 | } 97 | 98 | /* 99 | * Create module media folder 100 | */ 101 | if (!$this->mediaDirectory->create(static::MEDIA_MODULE_BASE_PATH)) { 102 | throw new \RuntimeException( 103 | sprintf( 104 | 'Could not create media folder: "%s"', 105 | static::MEDIA_MODULE_BASE_PATH 106 | ) 107 | ); 108 | } 109 | 110 | /* 111 | * Copy file 112 | */ 113 | if (!$this->ioFile->cp($filePath, $mediaFilePath)) { 114 | throw new \RuntimeException( 115 | sprintf( 116 | 'Could not copy media file to: "%s"', 117 | $mediaFilePath 118 | ) 119 | ); 120 | } 121 | 122 | return $mediaFilePath; 123 | } 124 | 125 | /** 126 | * @return void 127 | * @throws FileSystemException 128 | */ 129 | private function init(): void 130 | { 131 | if ($this->mediaDirectory === null) { 132 | $this->mediaDirectory = $this->fileSystem->getDirectoryWrite(DirectoryList::MEDIA); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /Model/Backup/Factory.php: -------------------------------------------------------------------------------- 1 | _allowedTypes = array_merge($this->_allowedTypes, [ 45 | self::TYPE_GDPR_DB 46 | ]); 47 | 48 | $this->dbBackupHandler = $dbBackupHandler; 49 | } 50 | 51 | /** 52 | * Create new backup instance 53 | * 54 | * @param string $type 55 | * @return BackupInterface 56 | * @throws LocalizedException 57 | */ 58 | public function create($type) 59 | { 60 | switch ($type) { 61 | case self::TYPE_GDPR_DB: 62 | return $this->dbBackupHandler; 63 | } 64 | 65 | return parent::create($type); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Model/Configuration.php: -------------------------------------------------------------------------------- 1 | useOnlyEmpty; 84 | } 85 | 86 | /** 87 | * @param bool $useOnlyEmpty 88 | * @return Configuration 89 | */ 90 | public function setUseOnlyEmpty(bool $useOnlyEmpty): Configuration 91 | { 92 | $this->useOnlyEmpty = $useOnlyEmpty; 93 | return $this; 94 | } 95 | 96 | /** 97 | * @return bool 98 | */ 99 | public function isApplyToCategories(): bool 100 | { 101 | return $this->applyToCategories; 102 | } 103 | 104 | /** 105 | * @param bool $applyToCategories 106 | * @return Configuration 107 | */ 108 | public function setApplyToCategories(bool $applyToCategories): Configuration 109 | { 110 | $this->applyToCategories = $applyToCategories; 111 | return $this; 112 | } 113 | 114 | /** 115 | * @return bool 116 | */ 117 | public function isApplyToCmsBlocks(): bool 118 | { 119 | return $this->applyToCmsBlocks; 120 | } 121 | 122 | /** 123 | * @param bool $applyToCmsBlocks 124 | * @return Configuration 125 | */ 126 | public function setApplyToCmsBlocks(bool $applyToCmsBlocks): Configuration 127 | { 128 | $this->applyToCmsBlocks = $applyToCmsBlocks; 129 | return $this; 130 | } 131 | 132 | /** 133 | * @return bool 134 | */ 135 | public function isApplyToCmsPages(): bool 136 | { 137 | return $this->applyToCmsPages; 138 | } 139 | 140 | /** 141 | * @param bool $applyToCmsPages 142 | * @return Configuration 143 | */ 144 | public function setApplyToCmsPages(bool $applyToCmsPages): Configuration 145 | { 146 | $this->applyToCmsPages = $applyToCmsPages; 147 | return $this; 148 | } 149 | 150 | /** 151 | * @return bool 152 | */ 153 | public function isApplyToCustomers(): bool 154 | { 155 | return $this->applyToCustomers; 156 | } 157 | 158 | /** 159 | * @param bool $applyToCustomers 160 | * @return Configuration 161 | */ 162 | public function setApplyToCustomers(bool $applyToCustomers): Configuration 163 | { 164 | $this->applyToCustomers = $applyToCustomers; 165 | return $this; 166 | } 167 | 168 | /** 169 | * @return bool 170 | */ 171 | public function isApplyToProducts(): bool 172 | { 173 | return $this->applyToProducts; 174 | } 175 | 176 | /** 177 | * @param bool $applyToProducts 178 | * @return Configuration 179 | */ 180 | public function setApplyToProducts(bool $applyToProducts): Configuration 181 | { 182 | $this->applyToProducts = $applyToProducts; 183 | return $this; 184 | } 185 | 186 | /** 187 | * @return bool 188 | */ 189 | public function isApplyToUsers(): bool 190 | { 191 | return $this->applyToUsers; 192 | } 193 | 194 | /** 195 | * @param bool $applyToUsers 196 | * @return Configuration 197 | */ 198 | public function setApplyToUsers(bool $applyToUsers): Configuration 199 | { 200 | $this->applyToUsers = $applyToUsers; 201 | return $this; 202 | } 203 | 204 | /** 205 | * @return string 206 | */ 207 | public function getDummyContentText(): string 208 | { 209 | return $this->dummyContentText; 210 | } 211 | 212 | /** 213 | * @param string $dummyContentText 214 | * @return Configuration 215 | */ 216 | public function setDummyContentText(string $dummyContentText): Configuration 217 | { 218 | $this->dummyContentText = $dummyContentText; 219 | return $this; 220 | } 221 | 222 | /** 223 | * @return string 224 | */ 225 | public function getDummyPassword(): string 226 | { 227 | return $this->dummyPassword; 228 | } 229 | 230 | /** 231 | * @param string $dummyPassword 232 | * @return Configuration 233 | */ 234 | public function setDummyPassword(string $dummyPassword): Configuration 235 | { 236 | $this->dummyPassword = $dummyPassword; 237 | return $this; 238 | } 239 | 240 | /** 241 | * @return string 242 | */ 243 | public function getDummyContentEmail(): string 244 | { 245 | return $this->dummyContentEmail; 246 | } 247 | 248 | /** 249 | * @param string $dummyContentEmail 250 | * @return Configuration 251 | */ 252 | public function setDummyContentEmail(string $dummyContentEmail): Configuration 253 | { 254 | $this->dummyContentEmail = $dummyContentEmail; 255 | return $this; 256 | } 257 | 258 | /** 259 | * @return string 260 | */ 261 | public function getDummyContentUrl(): string 262 | { 263 | return $this->dummyContentUrl; 264 | } 265 | 266 | /** 267 | * @param string $dummyContentUrl 268 | * @return Configuration 269 | */ 270 | public function setDummyContentUrl(string $dummyContentUrl): Configuration 271 | { 272 | $this->dummyContentUrl = $dummyContentUrl; 273 | return $this; 274 | } 275 | 276 | /** 277 | * @return string 278 | */ 279 | public function getDummyPhoneNumber(): string 280 | { 281 | return $this->dummyPhoneNumber; 282 | } 283 | 284 | /** 285 | * @param string $dummyPhoneNumber 286 | * @return Configuration 287 | */ 288 | public function setDummyPhoneNumber(string $dummyPhoneNumber): Configuration 289 | { 290 | $this->dummyPhoneNumber = $dummyPhoneNumber; 291 | return $this; 292 | } 293 | 294 | /** 295 | * @return string 296 | */ 297 | public function getDummyImagePath(): string 298 | { 299 | return $this->dummyImagePath; 300 | } 301 | 302 | /** 303 | * @param string $dummyImagePath 304 | * @return Configuration 305 | */ 306 | public function setDummyImagePath(string $dummyImagePath): Configuration 307 | { 308 | $this->dummyImagePath = $dummyImagePath; 309 | return $this; 310 | } 311 | 312 | /** 313 | * @return array 314 | */ 315 | public function getExtendedData(): array 316 | { 317 | return $this->extendedData; 318 | } 319 | 320 | /** 321 | * @param array $extendedData 322 | * @return Configuration 323 | */ 324 | public function setExtendedData(array $extendedData): Configuration 325 | { 326 | $this->extendedData = $extendedData; 327 | return $this; 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /Model/ConfigurationFactory.php: -------------------------------------------------------------------------------- 1 | _objectManager = $objectManager; 49 | $this->_instanceName = $instanceName; 50 | } 51 | 52 | /** 53 | * Create class instance with specified parameters 54 | * 55 | * @param array $data 56 | * @return Configuration 57 | */ 58 | public function create(array $data = array()) 59 | { 60 | return $this->_objectManager->create($this->_instanceName, $data); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Observer/CategoriesObserver.php: -------------------------------------------------------------------------------- 1 | categoryCollectionFactory = $categoryCollectionFactory; 57 | $this->categoryResourceFactory = $categoryResourceFactory; 58 | $this->urlRewriteCollectionFactory = $urlRewriteCollectionFactory; 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function isValid(Configuration $configuration): bool 65 | { 66 | return $configuration->isApplyToCategories(); 67 | } 68 | 69 | /** 70 | * {@inheritdoc} 71 | */ 72 | protected function run(Configuration $configuration) 73 | { 74 | /** @var CategoryResource $categoryResource */ 75 | $categoryResource = $this->categoryResourceFactory->create(); 76 | 77 | /* 78 | * clear table url_rewrite for entity_type category 79 | */ 80 | /** @var UrlRewriteCollection $urlRewriteCollection */ 81 | $urlRewriteCollection = $this->urlRewriteCollectionFactory->create(); 82 | $urlRewriteCollection 83 | ->addFieldToFilter('entity_type', ['eq' => 'category']) 84 | ->load(); 85 | foreach ($urlRewriteCollection->getItems() as $urlRewrite) { 86 | /** @var UrlRewrite $urlRewrite */ 87 | $urlRewrite->delete(); 88 | } 89 | 90 | /* 91 | * Process 92 | */ 93 | /** @var CategoryCollection $categoryCollection */ 94 | $categoryCollection = $this->categoryCollectionFactory->create(); 95 | $categoryCollection->load(); 96 | foreach ($categoryCollection->getItems() as $category) { 97 | /** @var Category $category */ 98 | if (self::ROOT_CATEGORY_ID === $category->getId()) { 99 | // skip root category 100 | continue; 101 | } 102 | $category->load($category->getId()); 103 | $this->doUpdate($configuration, $category); 104 | $categoryResource->save($category); 105 | } 106 | } 107 | 108 | /** 109 | * @param Configuration $configuration 110 | * @param Category $category 111 | * @return void 112 | */ 113 | protected function doUpdate(Configuration $configuration, Category $category): void 114 | { 115 | $this->updateData($category, 'description', $configuration, $configuration->getDummyContentText()); 116 | $this->updateData($category, 'meta_title', $configuration, $configuration->getDummyContentText()); 117 | $this->updateData($category, 'meta_keywords', $configuration, $configuration->getDummyContentText()); 118 | $this->updateData($category, 'meta_description', $configuration, $configuration->getDummyContentText()); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Observer/CategoryImageObserver.php: -------------------------------------------------------------------------------- 1 | categoryCollectionFactory = $categoryCollectionFactory; 65 | $this->categoryResourceFactory = $categoryResourceFactory; 66 | $this->urlRewriteCollectionFactory = $urlRewriteCollectionFactory; 67 | $this->mediaFileHandler = $mediaFileHandler; 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | */ 73 | public function isValid(Configuration $configuration): bool 74 | { 75 | return $configuration->isApplyToCategories(); 76 | } 77 | 78 | /** 79 | * {@inheritdoc} 80 | */ 81 | protected function run(Configuration $configuration) 82 | { 83 | /** @var CategoryResource $categoryResource */ 84 | $categoryResource = $this->categoryResourceFactory->create(); 85 | 86 | /* 87 | * clear table url_rewrite for entity_type category 88 | */ 89 | /** @var UrlRewriteCollection $urlRewriteCollection */ 90 | $urlRewriteCollection = $this->urlRewriteCollectionFactory->create(); 91 | $urlRewriteCollection 92 | ->addFieldToFilter('entity_type', ['eq' => 'category']) 93 | ->load(); 94 | foreach ($urlRewriteCollection->getItems() as $urlRewrite) { 95 | /** @var UrlRewrite $urlRewrite */ 96 | $urlRewrite->delete(); 97 | } 98 | 99 | /* 100 | * Process 101 | */ 102 | /** @var CategoryCollection $categoryCollection */ 103 | $categoryCollection = $this->categoryCollectionFactory->create(); 104 | $categoryCollection->load(); 105 | foreach ($categoryCollection->getItems() as $category) { 106 | /** @var Category $category */ 107 | if (self::ROOT_CATEGORY_ID === $category->getId()) { 108 | // skip root category 109 | continue; 110 | } 111 | $category->load($category->getId()); 112 | $this->doUpdate($configuration, $category); 113 | $categoryResource->save($category); 114 | } 115 | } 116 | 117 | /** 118 | * @param Configuration $configuration 119 | * @param Category $category 120 | * @return void 121 | * @throws LocalizedException 122 | */ 123 | protected function doUpdate(Configuration $configuration, Category $category): void 124 | { 125 | $imageUrl = $category->getImageUrl(); 126 | if (!is_string($imageUrl)) { 127 | $imageUrl = ''; 128 | } 129 | 130 | if ($configuration->isUseOnlyEmpty() && 131 | 0 !== strlen(trim($imageUrl)) 132 | ) { 133 | return; 134 | } 135 | 136 | $imagePath = $this->mediaFileHandler->getMediaCopyOfFile($configuration->getDummyImagePath()); 137 | $category->setData('image', basename($imagePath)); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Observer/CmsBlocksObserver.php: -------------------------------------------------------------------------------- 1 | blockCollectionFactory = $blockCollectionFactory; 44 | $this->blockResourceFactory = $blockResourceFactory; 45 | } 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function isValid(Configuration $configuration): bool 51 | { 52 | return $configuration->isApplyToCmsBlocks(); 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | protected function run(Configuration $configuration) 59 | { 60 | /** @var BlockResource $blockResource */ 61 | $blockResource = $this->blockResourceFactory->create(); 62 | 63 | /** @var BlockCollection $blockCollection */ 64 | $blockCollection = $this->blockCollectionFactory->create(); 65 | $blockCollection->load(); 66 | foreach ($blockCollection->getItems() as $block) { 67 | /** @var Block $block */ 68 | $this->doUpdate($configuration, $block); 69 | $blockResource->save($block); 70 | } 71 | } 72 | 73 | /** 74 | * @param Configuration $configuration 75 | * @param Block $block 76 | * @return void 77 | */ 78 | protected function doUpdate(Configuration $configuration, Block $block): void 79 | { 80 | $this->updateData($block, 'content', $configuration, $configuration->getDummyContentText()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Observer/CmsPagesObserver.php: -------------------------------------------------------------------------------- 1 | pageCollectionFactory = $pageCollectionFactory; 42 | $this->pageResourceFactory = $pageResourceFactory; 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function isValid(Configuration $configuration): bool 49 | { 50 | return $configuration->isApplyToCmsPages(); 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function run(Configuration $configuration) 57 | { 58 | /** @var PageResource $pageResource */ 59 | $pageResource = $this->pageResourceFactory->create(); 60 | 61 | /** @var PageCollection $pageCollection */ 62 | $pageCollection = $this->pageCollectionFactory->create(); 63 | $pageCollection->load(); 64 | foreach ($pageCollection->getItems() as $page) { 65 | /** @var Page $page */ 66 | $this->doUpdate($configuration, $page); 67 | $pageResource->save($page); 68 | } 69 | } 70 | 71 | /** 72 | * @param Configuration $configuration 73 | * @param Page $page 74 | * @return void 75 | */ 76 | protected function doUpdate(Configuration $configuration, Page $page): void 77 | { 78 | $this->updateData($page, 'content', $configuration, $configuration->getDummyContentText()); 79 | $this->updateData($page, 'content_heading', $configuration, $configuration->getDummyContentText()); 80 | $this->updateData($page, 'meta_title', $configuration, $configuration->getDummyContentText()); 81 | $this->updateData($page, 'meta_keywords', $configuration, $configuration->getDummyContentText()); 82 | $this->updateData($page, 'meta_description', $configuration, $configuration->getDummyContentText()); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Observer/CustomerPasswordsObserver.php: -------------------------------------------------------------------------------- 1 | customerCollectionFactory = $customerCollectionFactory; 43 | $this->customerRepository = $customerRepository; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function isValid(Configuration $configuration): bool 50 | { 51 | return $configuration->isApplyToCustomers(); 52 | } 53 | 54 | 55 | /** 56 | * {@inheritdoc} 57 | */ 58 | protected function run(Configuration $configuration) 59 | { 60 | /** @var CustomerCollection $customerCollection */ 61 | $customerCollection = $this->customerCollectionFactory->create(); 62 | $customerCollection->load(); 63 | foreach ($customerCollection->getItems() as $customer) { 64 | /** @var Customer $customer */ 65 | $customerData = $this->customerRepository->getById($customer->getId()); 66 | $this->customerRepository->save($customerData, $configuration->getDummyPassword()); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Observer/CustomersObserver.php: -------------------------------------------------------------------------------- 1 | customerCollectionFactory = $customerCollectionFactory; 68 | $this->customerRepository = $customerRepository; 69 | $this->quoteRepository = $quoteRepository; 70 | $this->orderAddressRepository = $orderAddressRepository; 71 | $this->searchCriteriaFactory = $searchCriteriaFactory; 72 | } 73 | 74 | /** 75 | * {@inheritdoc} 76 | */ 77 | public function isValid(Configuration $configuration): bool 78 | { 79 | return $configuration->isApplyToCustomers(); 80 | } 81 | 82 | 83 | /** 84 | * {@inheritdoc} 85 | */ 86 | protected function run(Configuration $configuration) 87 | { 88 | /* 89 | * Customer 90 | */ 91 | /** @var CustomerCollection $customerCollection */ 92 | $customerCollection = $this->customerCollectionFactory->create(); 93 | $customerCollection->load(); 94 | foreach ($customerCollection->getItems() as $customer) { 95 | /** @var Customer $customer */ 96 | $customerData = $this->customerRepository->getById($customer->getId()); 97 | $this->doUpdateCustomer($configuration, $customerData); 98 | $this->customerRepository->save($customerData); 99 | } 100 | 101 | $searchCriteria = $this->searchCriteriaFactory->create(); 102 | /* 103 | * Quotes 104 | */ 105 | $quoteCollection = $this->quoteRepository->getList($searchCriteria); 106 | foreach ($quoteCollection->getItems() as $quote) { 107 | $billingAddress = $quote->getBillingAddress(); 108 | if($billingAddress !== null) { 109 | $this->doUpdateQuoteAddress($configuration, $billingAddress); 110 | $this->quoteRepository->save($quote); 111 | } 112 | } 113 | 114 | /* 115 | * Orders 116 | */ 117 | /** @var OrderAddressCollection $orderAddressCollection */ 118 | $orderAddressCollection = $this->orderAddressRepository->getList($searchCriteria); 119 | foreach ($orderAddressCollection->getItems() as $orderAddress) { 120 | /** @var OrderAddressInterface $orderAddress */ 121 | $this->doUpdateOrderAddress($configuration, $orderAddress); 122 | $this->orderAddressRepository->save($orderAddress); 123 | } 124 | } 125 | 126 | /** 127 | * @param Configuration $configuration 128 | * @param CustomerInterface $customer 129 | * @return void 130 | */ 131 | protected function doUpdateCustomer( 132 | Configuration $configuration, 133 | CustomerInterface $customer 134 | ): void { 135 | $customer->setEmail( 136 | sprintf( 137 | $configuration->getDummyContentEmail(), 138 | $customer->getId() 139 | ) 140 | ); 141 | 142 | $customer->setLastname($configuration->getDummyContentText()); 143 | 144 | $addresses = $customer->getAddresses(); 145 | if($addresses === null) { 146 | $addresses = []; 147 | } 148 | 149 | foreach ($addresses as $address) { 150 | /** @var AddressInterface $address */ 151 | $address->setFirstname($configuration->getDummyContentText()); 152 | $address->setMiddlename($configuration->getDummyContentText()); 153 | $address->setLastname($configuration->getDummyContentText()); 154 | $address->setCompany($configuration->getDummyContentText()); 155 | $address->setCity($configuration->getDummyContentText()); 156 | $address->setPostcode($configuration->getDummyContentText()); 157 | $address->setStreet([$configuration->getDummyContentText()]); 158 | $address->setVatId($configuration->getDummyContentText()); 159 | } 160 | $customer->setAddresses($addresses); 161 | } 162 | 163 | /** 164 | * @param Configuration $configuration 165 | * @param \Magento\Quote\Api\Data\AddressInterface $quoteAddress 166 | * @return void 167 | */ 168 | protected function doUpdateQuoteAddress( 169 | Configuration $configuration, 170 | \Magento\Quote\Api\Data\AddressInterface $quoteAddress 171 | ): void { 172 | $quoteAddress->setFirstname($configuration->getDummyContentText()); 173 | $quoteAddress->setMiddlename($configuration->getDummyContentText()); 174 | $quoteAddress->setLastname($configuration->getDummyContentText()); 175 | $quoteAddress->setCompany($configuration->getDummyContentText()); 176 | $quoteAddress->setEmail($configuration->getDummyContentEmail()); 177 | $quoteAddress->setCity($configuration->getDummyContentText()); 178 | $quoteAddress->setPostcode($configuration->getDummyContentText()); 179 | $quoteAddress->setStreet($configuration->getDummyContentText()); 180 | $quoteAddress->setVatId($configuration->getDummyContentText()); 181 | } 182 | 183 | /** 184 | * @param Configuration $configuration 185 | * @param OrderAddressInterface $orderAddress 186 | * @return void 187 | */ 188 | protected function doUpdateOrderAddress( 189 | Configuration $configuration, 190 | OrderAddressInterface $orderAddress 191 | ): void { 192 | $orderAddress->setFirstname($configuration->getDummyContentText()); 193 | $orderAddress->setMiddlename($configuration->getDummyContentText()); 194 | $orderAddress->setLastname($configuration->getDummyContentText()); 195 | $orderAddress->setCompany($configuration->getDummyContentText()); 196 | $orderAddress->setEmail($configuration->getDummyContentEmail()); 197 | $orderAddress->setCity($configuration->getDummyContentText()); 198 | $orderAddress->setPostcode($configuration->getDummyContentText()); 199 | $orderAddress->setStreet($configuration->getDummyContentText()); 200 | $orderAddress->setVatId($configuration->getDummyContentText()); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /Observer/FuzzyfyrObserver.php: -------------------------------------------------------------------------------- 1 | getData('configuration'); 30 | 31 | return $configuration; 32 | } 33 | 34 | /** 35 | * @param Configuration $configuration 36 | * @return bool 37 | */ 38 | protected function isValid(Configuration $configuration): bool 39 | { 40 | return true; 41 | } 42 | 43 | 44 | /** 45 | * {@inheritdoc} 46 | * @return void 47 | */ 48 | public function execute(Observer $observer) 49 | { 50 | /** @var Configuration $configuration */ 51 | $configuration = $this->getConfigurationByEvent($observer); 52 | 53 | if (!$this->isValid($configuration)) { 54 | return; 55 | } 56 | 57 | $this->run($configuration); 58 | } 59 | 60 | /** 61 | * @return void 62 | */ 63 | abstract protected function run(Configuration $configuration); 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | public function updateData( 69 | DataObject $entity, 70 | string $fieldName, 71 | Configuration $configuration, 72 | $value = FuzzyfyrCommand::DEFAULT_DUMMY_CONTENT_TEXT 73 | ): void { 74 | $data = (string) $entity->getData($fieldName); 75 | if (!$configuration->isUseOnlyEmpty() || 76 | ($configuration->isUseOnlyEmpty() && ($data === ''))) { 77 | $entity->setData($fieldName, $value); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Observer/ProductImagesObserver.php: -------------------------------------------------------------------------------- 1 | productCollectionFactory = $productCollectionFactory; 43 | $this->mediaFileHandler = $mediaFileHandler; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function isValid(Configuration $configuration): bool 50 | { 51 | return $configuration->isApplyToProducts(); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function run(Configuration $configuration) 58 | { 59 | /** @var ProductCollection $productCollection */ 60 | $productCollection = $this->productCollectionFactory->create(); 61 | $productCollection->load(); 62 | foreach ($productCollection->getItems() as $product) { 63 | /** @var Product $product */ 64 | $this->doUpdate($configuration, $product); 65 | $product->save(); 66 | } 67 | } 68 | 69 | /** 70 | * @param Configuration $configuration 71 | * @param Product $product 72 | * @return void 73 | * @throws Exception 74 | */ 75 | protected function doUpdate(Configuration $configuration, Product $product): void 76 | { 77 | $mediaGalleryEntries = $product->getMediaGalleryEntries(); 78 | if ($mediaGalleryEntries === null) { 79 | $mediaGalleryEntries = []; 80 | } 81 | 82 | if ($configuration->isUseOnlyEmpty() && (count($mediaGalleryEntries) >0)) { 83 | return; 84 | } 85 | 86 | if (!$configuration->isUseOnlyEmpty()) { 87 | $product->setMediaGalleryEntries([]); 88 | } 89 | 90 | $imagePath = $this->mediaFileHandler->getMediaCopyOfFile($configuration->getDummyImagePath()); 91 | $product->addImageToMediaGallery($imagePath, ['image', 'small_image', 'thumbnail'], false, false); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Observer/ProductsObserver.php: -------------------------------------------------------------------------------- 1 | productCollectionFactory = $productCollectionFactory; 41 | $this->productResourceFactory = $productResourceFactory; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function isValid(Configuration $configuration): bool 48 | { 49 | return $configuration->isApplyToProducts(); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | protected function run(Configuration $configuration) 56 | { 57 | /** @var ProductResource $productResource */ 58 | $productResource = $this->productResourceFactory->create(); 59 | 60 | /** @var ProductCollection $productCollection */ 61 | $productCollection = $this->productCollectionFactory->create(); 62 | $productCollection->load(); 63 | foreach ($productCollection->getItems() as $product) { 64 | /** @var Product $product */ 65 | $this->doUpdate($configuration, $product); 66 | $productResource->save($product); 67 | } 68 | } 69 | 70 | /** 71 | * @param Configuration $configuration 72 | * @param Product $product 73 | * @return void 74 | */ 75 | protected function doUpdate(Configuration $configuration, Product $product): void 76 | { 77 | $this->updateData($product, 'description', $configuration, $configuration->getDummyContentText()); 78 | $this->updateData($product, 'short_description', $configuration, $configuration->getDummyContentText()); 79 | $this->updateData($product, 'meta_title', $configuration, $configuration->getDummyContentText()); 80 | $this->updateData($product, 'meta_keyword', $configuration, $configuration->getDummyContentText()); 81 | $this->updateData($product, 'meta_description', $configuration, $configuration->getDummyContentText()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Observer/UsersObserver.php: -------------------------------------------------------------------------------- 1 | userCollectionFactory = $userCollectionFactory; 41 | $this->userResourceFactory = $userResourceFactory; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function isValid(Configuration $configuration): bool 48 | { 49 | return $configuration->isApplyToUsers(); 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | protected function run(Configuration $configuration) 56 | { 57 | /** @var UserResource $userResource */ 58 | $userResource = $this->userResourceFactory->create(); 59 | 60 | /** @var UserCollection $userCollection */ 61 | $userCollection = $this->userCollectionFactory->create(); 62 | $userCollection->load(); 63 | foreach ($userCollection->getItems() as $user) { 64 | /** @var User $user */ 65 | $this->doUpdate($configuration, $user); 66 | $userResource->save($user); 67 | } 68 | } 69 | 70 | /** 71 | * @param Configuration $configuration 72 | * @param User $user 73 | * @return void 74 | */ 75 | protected function doUpdate(Configuration $configuration, User $user): void 76 | { 77 | $user->setEmail( 78 | sprintf( 79 | $configuration->getDummyContentEmail(), 80 | $user->getId() 81 | ) 82 | ); 83 | 84 | $user->setLastName($configuration->getDummyContentText()); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Content Fuzzyfyr Module for Magento® 2 2 | 3 | [![ci](https://github.com/hivecommerce/magento2-content-fuzzyfyr/actions/workflows/ci.yml/badge.svg)](https://github.com/hivecommerce/magento2-content-fuzzyfyr/actions/workflows/ci.yml) 4 | [![Coverage Status](https://coveralls.io/repos/github/hivecommerce/magento2-content-fuzzyfyr/badge.svg?branch=main)](https://coveralls.io/github/hivecommerce/magento2-content-fuzzyfyr?branch=main) 5 | [![Mastodon Follow](https://img.shields.io/mastodon/follow/109408681246972700?domain=https://rheinneckar.social)](https://rheinneckar.social/@bitexpert) 6 | 7 | The **Content Fuzzyfyr** module for *Magento® 2* fills up empty content fields - and if needed - switches real content with dummy content. 8 | This is for development purposes, e.g. save time to prepare test data and being compliant to GDPR. 9 | 10 | ## Features: 11 | * Fill up empty content and image fields with dummy content - completely automated 12 | * Match GDPR compliance for development, when using production data 13 | * Export your production database already matching GDPR compliance 14 | * Use parameters to control the sections required to be filled up with dummy content 15 | 16 | ## Installation 17 | The preferred way of installing `hivecommerce/magento2-content-fuzzyfyr` is through Composer. 18 | Simply add `hivecommerce/magento2-content-fuzzyfyr` as a dependency: 19 | 20 | ``` 21 | composer.phar require hivecommerce/magento2-content-fuzzyfyr 22 | ``` 23 | 24 | Optional you can download the latest version [here](https://github.com/hivecommerce/magento2-content-fuzzyfyr/releases) 25 | and install the decompressed code in your projects directory under *app/code/HiveCommerce/ContentFuzzyfyr*. 26 | 27 | ## Post-Install 28 | 29 | After the installment of the module source code, the module has to be enabled by the *Magento® 2* CLI. 30 | 31 | ``` 32 | bin/magento module:enable HiveCommerce_ContentFuzzyfyr 33 | ``` 34 | 35 | ## System Upgrade 36 | 37 | After enabling the module, the *Magento® 2* system must be upgraded. 38 | 39 | If the system mode is set to *production*, run the *compile* command first. 40 | This is not necessary for the *developer* mode. 41 | ``` 42 | bin/magento setup:di:compile 43 | ``` 44 | 45 | To upgrade the system, the *upgrade* command must be run. 46 | ``` 47 | bin/magento setup:upgrade 48 | ``` 49 | 50 | # User Guide 51 | Find the complete user guide [here](./docs/UserGuide.pdf "User Guide"). 52 | 53 | ## How to use 54 | 55 | ### CLI 56 | #### Content Fuzzyfyr 57 | 58 | The **Content Fuzzyfyr** Module for *Magento® 2* provides an *Magento® 2* CLI command *dev:content:fuzzyfyr* to modify 59 | existing content (or only empty fields with the *--only-empty* flag) to be switched with some defined default value: 60 | 61 | bin/magento dev:content:fuzzyfyr [options] 62 | 63 | **Note:** Be aware the command only runs in non-production mode to avoid messing up production data on mistake. 64 | 65 | You may want to switch to *default* or *developer* mode to run the command: 66 | 67 | bin/magento deploy:mode:set developer 68 | 69 | #### List of flags 70 | 71 | Option | Description 72 | --- | --- 73 | --only-empty | Use dummy content only if the original data is equal to empty 74 | --force | Allow execution in production mode (not recommended!) 75 | --categories | Apply dummy content to categories (content, meta description) 76 | --cms-blocks | Apply dummy content to CMS Blocks (content) 77 | --cms-pages | Apply dummy content to CMS Pages (content, meta description) 78 | --customers | Apply dummy content to customers (Last name, address, email, password) 79 | --products | Apply dummy content to products (description) 80 | --users | Apply dummy content to users (Last name, email) 81 | 82 | #### List of options 83 | 84 | Option | Value | Description 85 | --- | --- | --- 86 | --dummy-content-text | String | Used as dummy text content. Defaults to 'Lorem ipsum.' 87 | --dummy-content-password | String | Used as dummy text content. Defaults to 'lorem42' 88 | --dummy-content-email | String | Used as dummy email content. Defaults to 'lorem.ipsum.%1$s@test.localhost' 89 | --dummy-content-url | String | Used as dummy url content. Defaults to 'https://lor.emips.um/foo/bar/' 90 | --dummy-content-phone | String | Used as dummy phone content. Defaults to '+49 (0) 600 987 654 32' 91 | --dummy-content-image-path | String | Used as dummy image content. Defaults to './assets/dummy_image.png' 92 | 93 | #### How to apply custom code 94 | 95 | An event is triggered, called *hc_content_fuzzyfyr_event*. Listening to this event, expect the following parameters 96 | in the *Observer* data: 97 | 98 | 'configuration' => \HiveCommerce\ContentFuzzyfyr\Model\Configuration 99 | 100 | 101 | #### Content Export 102 | 103 | The **Content Fuzzyfyr** Module for *Magento® 2* provides an *Magento® 2* CLI command *dev:content:export* to export an 104 | database dump with already fuzzyfied content for existing content (or only empty fields with the *--only-empty* flag) 105 | switched with some defined default value: 106 | 107 | bin/magento dev:content:export [options] 108 | 109 | **Note:** Running the code activates maintenance mode. The maintenance mode will be disabled, if the command has run 110 | successfully or erroneous and the maintenance mode has been disabled in the beginning. But it is recommended to check 111 | manually on production system after running the command. 112 | 113 | #### List of flags 114 | 115 | Option | Description 116 | --- | --- 117 | --only-empty | Use dummy content only if the original data is equal to empty 118 | --categories | Apply dummy content to categories (content, meta description) 119 | --cms-blocks | Apply dummy content to CMS Blocks (content) 120 | --cms-pages | Apply dummy content to CMS Pages (content, meta description) 121 | --customers | Apply dummy content to customers (Last name, address, email, password) 122 | --products | Apply dummy content to products (description) 123 | --users | Apply dummy content to users (Last name, email) 124 | 125 | #### List of options 126 | 127 | Option | Value | Description 128 | --- | --- | --- 129 | --dummy-content-text | String | Used as dummy text content. Defaults to 'Lorem ipsum.' 130 | --dummy-content-password | String | Used as dummy text content. Defaults to 'lorem42' 131 | --dummy-content-email | String | Used as dummy email content. Defaults to 'lorem.ipsum.%1$s@test.localhost' 132 | --dummy-content-url | String | Used as dummy url content. Defaults to 'https://lor.emips.um/foo/bar/' 133 | --dummy-content-phone | String | Used as dummy phone content. Defaults to '+49 (0) 600 987 654 32' 134 | --backup-output | String | Path where the database dump is placed. Defaults to './var/backups/' 135 | 136 | #### How to apply custom code 137 | 138 | An event is triggered, called *hc_content_export_event*. Listening to this event, expect the following parameters 139 | in the *Observer* data: 140 | 141 | 'configuration' => \HiveCommerce\ContentFuzzyfyr\Model\Configuration 142 | 143 | 144 | ### Administration 145 | #### Content Export 146 | 147 | The **Content Fuzzyfyr** Module for *Magento® 2* extends the *Magento® 2* administration backup area with an additional 148 | option to trigger the export of a GDPR compliant database dump. The database dump will have fuzzyfied customers and user 149 | data. 150 | 151 | Navigate through the main navigation and selecting *System > Backup*: 152 | 153 | ![alt text](./resources/aid-content-fuzzyfyr-export-1.png "Dashboard - Menu - Backup") 154 | 155 | The backup area is extended by the new button *GDPR conform Database Backup (Content Fuzzyfyr)*: 156 | 157 | ![alt text](./resources/aid-content-fuzzyfyr-export-2.png "Extended backup area") 158 | 159 | By clicking on this button, a wizard is opened to configure the backup - mainly the name of the backup file: 160 | 161 | ![alt text](./resources/aid-content-fuzzyfyr-export-3.png "Backup wizard") 162 | 163 | If the wizard is confirmed, the GDPR compliant backup will be created and visibile in the existing backup list: 164 | 165 | ![alt text](./resources/aid-content-fuzzyfyr-export-4.png "GDPR compliant backup") 166 | 167 | ## Contribution 168 | Feel free to contribute to this module by reporting issues or create some pull requests for improvements. 169 | 170 | ## License 171 | The **Content Fuzzyfyr** Module for *Magento® 2* is released under the Apache 2.0 license. 172 | -------------------------------------------------------------------------------- /Test/Unit/AbstractTest.php: -------------------------------------------------------------------------------- 1 | $className 27 | * @param array $arguments 28 | * @return T 29 | */ 30 | public function getTestEntity(string $className, array $arguments = []) 31 | { 32 | $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); 33 | return $objectManager->getObject($className, $arguments); 34 | } 35 | 36 | /** 37 | * @param class-string $instanceName 38 | * @param MockObject|null $mock 39 | * @return mixed 40 | */ 41 | public function getFactoryAsMock(string $instanceName, MockObject $mock = null) 42 | { 43 | /** 44 | * @var class-string $factoryFullName 45 | */ 46 | $factoryFullName = $instanceName . 'Factory'; 47 | $parts = explode('\\', $factoryFullName); 48 | 49 | if ($mock === null) { 50 | $mock = $this->getMockBuilder($instanceName) 51 | ->disableOriginalConstructor() 52 | ->getMock(); 53 | } 54 | 55 | $factory = $this->getMockBuilder($factoryFullName) 56 | ->disableOriginalConstructor() 57 | ->setMethods(['create']) 58 | ->getMock(); 59 | 60 | $factory->expects(self::any()) 61 | ->method('create') 62 | ->willReturn($mock); 63 | 64 | return $factory; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Test/Unit/Console/Command/ExportCommandTest.php: -------------------------------------------------------------------------------- 1 | getState(); 38 | 39 | $input = $this->getInput(); 40 | $input->expects(self::any()) 41 | ->method('getOption') 42 | ->willReturnCallback(function ($name): string { 43 | if ($name === ExportCommand::OPTION_DUMP_OUTPUT) { 44 | return ExportCommand::DEFAULT_DUMP_OUTPUT; 45 | } 46 | return ''; 47 | }); 48 | $output = $this->getOutput(); 49 | 50 | $configuration = $this->getMockBuilder(Configuration::class)->getMock(); 51 | $configurationFactory = $this->getConfigurationFactory(); 52 | $configurationFactory->expects(self::once()) 53 | ->method('create') 54 | ->willReturn($configuration); 55 | 56 | $eventManager = $this->getEventManager(); 57 | $eventManager->expects(self::once()) 58 | ->method('dispatch') 59 | ->with(ExportCommand::EVENT_NAME, [ 60 | 'configuration' => $configuration 61 | ]); 62 | 63 | $backupHandler = $this->getBackupHandler(); 64 | $backupHandler->expects(self::once()) 65 | ->method('beginTransaction'); 66 | $backupHandler->expects(self::once()) 67 | ->method('endTransaction'); 68 | $backupHandler->expects(self::once()) 69 | ->method('run') 70 | ->with($output, ExportCommand::DEFAULT_DUMP_OUTPUT); 71 | 72 | $command = new ExportCommand( 73 | $state, 74 | $eventManager, 75 | $configurationFactory, 76 | $backupHandler 77 | ); 78 | 79 | self::assertEquals(ExportCommand::SUCCESS, $command->run($input, $output)); 80 | } 81 | 82 | /** 83 | * @test 84 | */ 85 | public function runFailesRunningBackup(): void 86 | { 87 | $state = $this->getState(); 88 | 89 | $input = $this->getInput(); 90 | $input->expects(self::any()) 91 | ->method('getOption') 92 | ->willReturnCallback(function ($name): string { 93 | if ($name === ExportCommand::OPTION_DUMP_OUTPUT) { 94 | return ExportCommand::DEFAULT_DUMP_OUTPUT; 95 | } 96 | return ''; 97 | }); 98 | $output = $this->getOutput(); 99 | 100 | $configuration = $this->getMockBuilder(Configuration::class)->getMock(); 101 | $configurationFactory = $this->getConfigurationFactory(); 102 | $configurationFactory->expects(self::once()) 103 | ->method('create') 104 | ->willReturn($configuration); 105 | 106 | $eventManager = $this->getEventManager(); 107 | $eventManager->expects(self::once()) 108 | ->method('dispatch') 109 | ->with(ExportCommand::EVENT_NAME, [ 110 | 'configuration' => $configuration 111 | ]); 112 | 113 | $backupHandler = $this->getBackupHandler(); 114 | $backupHandler->expects(self::once()) 115 | ->method('beginTransaction'); 116 | $backupHandler->expects(self::once()) 117 | ->method('endTransaction'); 118 | $backupHandler->expects(self::once()) 119 | ->method('run') 120 | ->with($output, ExportCommand::DEFAULT_DUMP_OUTPUT) 121 | ->willThrowException(new \Exception()); 122 | 123 | $command = new ExportCommand( 124 | $state, 125 | $eventManager, 126 | $configurationFactory, 127 | $backupHandler 128 | ); 129 | 130 | self::assertEquals(ExportCommand::ERROR_EXPORT_FAILED, $command->run($input, $output)); 131 | } 132 | 133 | /** 134 | * @return MockObject&State 135 | */ 136 | private function getState() 137 | { 138 | return $this->getMockBuilder(State::class) 139 | ->disableOriginalConstructor() 140 | ->getMock(); 141 | } 142 | 143 | /** 144 | * @return MockObject&EventManager 145 | */ 146 | private function getEventManager() 147 | { 148 | return $this->getMockBuilder(EventManager::class) 149 | ->disableOriginalConstructor() 150 | ->getMock(); 151 | } 152 | 153 | /** 154 | * @return MockObject&ConfigurationFactory 155 | */ 156 | private function getConfigurationFactory() 157 | { 158 | return $this->getMockBuilder(ConfigurationFactory::class) 159 | ->disableOriginalConstructor() 160 | ->getMock(); 161 | } 162 | 163 | /** 164 | * @return MockObject&BackupHandler 165 | */ 166 | private function getBackupHandler() 167 | { 168 | return $this->getMockBuilder(BackupHandler::class) 169 | ->disableOriginalConstructor() 170 | ->getMock(); 171 | } 172 | 173 | /** 174 | * @return MockObject&InputInterface 175 | */ 176 | private function getInput() 177 | { 178 | return $this->getMockBuilder(InputInterface::class) 179 | ->disableOriginalConstructor() 180 | ->getMock(); 181 | } 182 | 183 | /** 184 | * @return MockObject&OutputInterface 185 | */ 186 | private function getOutput() 187 | { 188 | return $this->getMockBuilder(OutputInterface::class) 189 | ->disableOriginalConstructor() 190 | ->getMock(); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /Test/Unit/Console/Command/FuzzyfyrCommandTest.php: -------------------------------------------------------------------------------- 1 | getState(); 37 | $state->expects(self::any()) 38 | ->method('getMode') 39 | ->willReturn(\Magento\Framework\App\State::MODE_DEFAULT); 40 | 41 | $configuration = $this->getMockBuilder(Configuration::class)->getMock(); 42 | $configurationFactory = $this->getConfigurationFactory(); 43 | $configurationFactory->expects(self::once()) 44 | ->method('create') 45 | ->willReturn($configuration); 46 | 47 | $eventManager = $this->getEventManager(); 48 | $eventManager->expects(self::once()) 49 | ->method('dispatch') 50 | ->with(FuzzyfyrCommand::EVENT_NAME, [ 51 | 'configuration' => $configuration 52 | ]); 53 | 54 | $command = new FuzzyfyrCommand( 55 | $state, 56 | $eventManager, 57 | $configurationFactory 58 | ); 59 | 60 | $input = $this->getInput(); 61 | $output = $this->getOutput(); 62 | 63 | self::assertEquals(FuzzyfyrCommand::SUCCESS, $command->run($input, $output)); 64 | } 65 | 66 | /** 67 | * @test 68 | */ 69 | public function runSuccessfullyInProductionModeWithForceOption(): void 70 | { 71 | $state = $this->getState(); 72 | $state->expects(self::any()) 73 | ->method('getMode') 74 | ->willReturn(\Magento\Framework\App\State::MODE_PRODUCTION); 75 | 76 | $configuration = $this->getMockBuilder(Configuration::class)->getMock(); 77 | $configurationFactory = $this->getConfigurationFactory(); 78 | $configurationFactory->expects(self::once()) 79 | ->method('create') 80 | ->willReturn($configuration); 81 | 82 | $eventManager = $this->getEventManager(); 83 | $eventManager->expects(self::once()) 84 | ->method('dispatch') 85 | ->with(FuzzyfyrCommand::EVENT_NAME, [ 86 | 'configuration' => $configuration 87 | ]); 88 | 89 | $command = new FuzzyfyrCommand( 90 | $state, 91 | $eventManager, 92 | $configurationFactory 93 | ); 94 | 95 | $input = $this->getInput(); 96 | $input->expects(self::any()) 97 | ->method('getOption') 98 | ->willReturnCallback(function ($name) { 99 | switch($name) { 100 | default: return null; 101 | case FuzzyfyrCommand::FLAG_FORCE: return true; 102 | case FuzzyfyrCommand::FLAG_ONLY_EMPTY: return true; 103 | case FuzzyfyrCommand::FLAG_CATEGORIES: return false; 104 | case FuzzyfyrCommand::FLAG_CMS_BLOCKS: return false; 105 | case FuzzyfyrCommand::FLAG_CMS_PAGES: return false; 106 | case FuzzyfyrCommand::FLAG_CUSTOMERS: return false; 107 | case FuzzyfyrCommand::FLAG_PRODUCTS: return false; 108 | case FuzzyfyrCommand::FLAG_USERS: return false; 109 | case FuzzyfyrCommand::OPTION_DUMMY_CONTENT_TEXT: return FuzzyfyrCommand::DEFAULT_DUMMY_CONTENT_TEXT; 110 | case FuzzyfyrCommand::OPTION_DUMMY_CONTENT_PASSWORD: return FuzzyfyrCommand::DEFAULT_DUMMY_CONTENT_PASSWORD; 111 | case FuzzyfyrCommand::OPTION_DUMMY_CONTENT_EMAIL: return FuzzyfyrCommand::DEFAULT_DUMMY_CONTENT_EMAIL; 112 | case FuzzyfyrCommand::OPTION_DUMMY_CONTENT_URL: return FuzzyfyrCommand::DEFAULT_DUMMY_CONTENT_URL; 113 | case FuzzyfyrCommand::OPTION_DUMMY_CONTENT_PHONE: return FuzzyfyrCommand::DEFAULT_DUMMY_CONTENT_PHONE; 114 | case FuzzyfyrCommand::OPTION_DUMMY_CONTENT_IMAGE_PATH: return FuzzyfyrCommand::DEFAULT_DUMMY_CONTENT_IMAGE_PATH; 115 | } 116 | 117 | }); 118 | $output = $this->getOutput(); 119 | 120 | self::assertEquals(FuzzyfyrCommand::SUCCESS, $command->run($input, $output)); 121 | } 122 | 123 | /** 124 | * @test 125 | */ 126 | public function runFailsInProductionMode(): void 127 | { 128 | $state = $this->getState(); 129 | $state->expects(self::any()) 130 | ->method('getMode') 131 | ->willReturn(\Magento\Framework\App\State::MODE_PRODUCTION); 132 | 133 | $eventManager = $this->getEventManager(); 134 | $eventManager->expects(self::never()) 135 | ->method('dispatch'); 136 | 137 | $configurationFactory = $this->getConfigurationFactory(); 138 | $configurationFactory->expects(self::never()) 139 | ->method('create'); 140 | 141 | $command = new FuzzyfyrCommand( 142 | $state, 143 | $eventManager, 144 | $configurationFactory 145 | ); 146 | 147 | $input = $this->getInput(); 148 | $output = $this->getOutput(); 149 | 150 | self::assertEquals(FuzzyfyrCommand::ERROR_PRODUCTION_MODE, $command->run($input, $output)); 151 | } 152 | 153 | /** 154 | * @return MockObject&State 155 | */ 156 | private function getState() 157 | { 158 | return $this->getMockBuilder(State::class) 159 | ->disableOriginalConstructor() 160 | ->getMock(); 161 | } 162 | 163 | /** 164 | * @return MockObject&EventManager 165 | */ 166 | private function getEventManager() 167 | { 168 | return $this->getMockBuilder(EventManager::class) 169 | ->disableOriginalConstructor() 170 | ->getMock(); 171 | } 172 | 173 | /** 174 | * @return MockObject&ConfigurationFactory 175 | */ 176 | private function getConfigurationFactory() 177 | { 178 | return $this->getMockBuilder(ConfigurationFactory::class) 179 | ->disableOriginalConstructor() 180 | ->getMock(); 181 | } 182 | 183 | /** 184 | * @return MockObject&InputInterface 185 | */ 186 | private function getInput() 187 | { 188 | return $this->getMockBuilder(InputInterface::class) 189 | ->disableOriginalConstructor() 190 | ->getMock(); 191 | } 192 | 193 | /** 194 | * @return MockObject&OutputInterface 195 | */ 196 | private function getOutput() 197 | { 198 | return $this->getMockBuilder(OutputInterface::class) 199 | ->disableOriginalConstructor() 200 | ->getMock(); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /Test/Unit/Handler/Backup/DatabaseHandlerTest.php: -------------------------------------------------------------------------------- 1 | getMockBuilder(Configuration::class) 39 | ->disableOriginalConstructor() 40 | ->getMock(); 41 | $configuration->expects(self::once()) 42 | ->method('setApplyToUsers') 43 | ->with(true); 44 | $configuration->expects(self::once()) 45 | ->method('setApplyToCustomers') 46 | ->with(true); 47 | $configurationFactory = $this->getConfigurationFactory(); 48 | $configurationFactory->expects(self::once()) 49 | ->method('create') 50 | ->willReturn($configuration); 51 | 52 | $eventManager = $this->getEventManager(); 53 | $eventManager->expects(self::once()) 54 | ->method('dispatch') 55 | ->with(ExportCommand::EVENT_NAME, [ 56 | 'configuration' => $configuration 57 | ]); 58 | 59 | $backupHandler = $this->getBackupHandler(); 60 | $backupHandler->expects(self::once()) 61 | ->method('beginTransaction'); 62 | $backupHandler->expects(self::once()) 63 | ->method('endTransaction'); 64 | 65 | $backupEntity = $this->createMock(BackupInterface::class); 66 | $backupEntity->expects(self::once()) 67 | ->method('setTime') 68 | ->willReturn($backupEntity); 69 | $backupEntity->expects(self::once()) 70 | ->method('setType') 71 | ->willReturn($backupEntity); 72 | $backupEntity->expects(self::once()) 73 | ->method('setPath') 74 | ->willReturn($backupEntity); 75 | $backupEntity->expects(self::once()) 76 | ->method('setName') 77 | ->willReturn($backupEntity); 78 | $backupDbEntity = $this->createMock(BackupDbInterface::class); 79 | $backupDbEntity->expects(self::once()) 80 | ->method('createBackup') 81 | ->with($backupEntity); 82 | $backupFactory = $this->getBackupFactory(); 83 | $backupFactory->expects(self::once()) 84 | ->method('createBackupModel') 85 | ->willReturn($backupEntity); 86 | $backupFactory->expects(self::once()) 87 | ->method('createBackupDbModel') 88 | ->willReturn($backupDbEntity); 89 | 90 | $databaseHandler = new DatabaseHandler( 91 | $backupFactory, 92 | $eventManager, 93 | $configurationFactory, 94 | $backupHandler 95 | ); 96 | 97 | self::assertEquals($databaseHandler, $databaseHandler->addIgnorePaths([])); 98 | self::assertTrue($databaseHandler->create()); 99 | } 100 | 101 | /** 102 | * @test 103 | */ 104 | public function runFailsDueToBackupTaskIssues(): void 105 | { 106 | $configuration = $this->getMockBuilder(Configuration::class) 107 | ->disableOriginalConstructor() 108 | ->getMock(); 109 | $configuration->expects(self::once()) 110 | ->method('setApplyToUsers') 111 | ->with(true); 112 | $configuration->expects(self::once()) 113 | ->method('setApplyToCustomers') 114 | ->with(true); 115 | $configurationFactory = $this->getConfigurationFactory(); 116 | $configurationFactory->expects(self::once()) 117 | ->method('create') 118 | ->willReturn($configuration); 119 | 120 | $eventManager = $this->getEventManager(); 121 | $eventManager->expects(self::once()) 122 | ->method('dispatch') 123 | ->with(ExportCommand::EVENT_NAME, [ 124 | 'configuration' => $configuration 125 | ]); 126 | 127 | $backupHandler = $this->getBackupHandler(); 128 | $backupHandler->expects(self::once()) 129 | ->method('beginTransaction'); 130 | $backupHandler->expects(self::once()) 131 | ->method('endTransaction'); 132 | 133 | $backupEntity = $this->createMock(BackupInterface::class); 134 | $backupEntity->expects(self::once()) 135 | ->method('setTime') 136 | ->willReturn($backupEntity); 137 | $backupEntity->expects(self::once()) 138 | ->method('setType') 139 | ->willReturn($backupEntity); 140 | $backupEntity->expects(self::once()) 141 | ->method('setPath') 142 | ->willReturn($backupEntity); 143 | $backupEntity->expects(self::once()) 144 | ->method('setName') 145 | ->willReturn($backupEntity); 146 | $backupDbEntity = $this->createMock(BackupDbInterface::class); 147 | $backupDbEntity->expects(self::once()) 148 | ->method('createBackup') 149 | ->with($backupEntity) 150 | ->willThrowException(new \Exception()); 151 | $backupFactory = $this->getBackupFactory(); 152 | $backupFactory->expects(self::once()) 153 | ->method('createBackupModel') 154 | ->willReturn($backupEntity); 155 | $backupFactory->expects(self::once()) 156 | ->method('createBackupDbModel') 157 | ->willReturn($backupDbEntity); 158 | 159 | $databaseHandler = new DatabaseHandler( 160 | $backupFactory, 161 | $eventManager, 162 | $configurationFactory, 163 | $backupHandler 164 | ); 165 | 166 | self::assertEquals(false, $databaseHandler->create()); 167 | } 168 | 169 | /** 170 | * @return MockObject&EventManager 171 | */ 172 | private function getEventManager() 173 | { 174 | return $this->getMockBuilder(EventManager::class) 175 | ->disableOriginalConstructor() 176 | ->getMock(); 177 | } 178 | 179 | /** 180 | * @return MockObject&ConfigurationFactory 181 | */ 182 | private function getConfigurationFactory() 183 | { 184 | return $this->getMockBuilder(ConfigurationFactory::class) 185 | ->disableOriginalConstructor() 186 | ->getMock(); 187 | } 188 | 189 | /** 190 | * @return MockObject&BackupHandler 191 | */ 192 | private function getBackupHandler() 193 | { 194 | return $this->getMockBuilder(BackupHandler::class) 195 | ->disableOriginalConstructor() 196 | ->getMock(); 197 | } 198 | 199 | /** 200 | * @return MockObject&BackupFactory 201 | */ 202 | private function getBackupFactory() 203 | { 204 | return $this->getMockBuilder(BackupFactory::class) 205 | ->disableOriginalConstructor() 206 | ->getMock(); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Test/Unit/Handler/BackupHandlerTest.php: -------------------------------------------------------------------------------- 1 | getOutput(); 42 | 43 | $maintenanceMode = $this->getMaintenanceMode(); 44 | $maintenanceMode->expects(self::once()) 45 | ->method('isOn') 46 | ->willReturn(false); 47 | 48 | $backupRollback = $this->getMockBuilder(BackupRollback::class) 49 | ->disableOriginalConstructor() 50 | ->getMock(); 51 | $backupRollback->expects(self::once()) 52 | ->method('dbBackup') 53 | ->willReturn('/mybackup.bak'); 54 | $backupRollbackFactory = $this->getBackupRollbackFactory(); 55 | $backupRollbackFactory->expects(self::once()) 56 | ->method('create') 57 | ->with($output) 58 | ->willReturn($backupRollback); 59 | 60 | $connection = $this->createMock(AdapterInterface::class); 61 | $connection->expects(self::once()) 62 | ->method('beginTransaction'); 63 | $connection->expects(self::once()) 64 | ->method('rollBack'); 65 | $setup = $this->getModuleDataSetup(); 66 | $setup->expects(self::exactly(2)) 67 | ->method('getConnection') 68 | ->willReturn($connection); 69 | 70 | $ioFile = $this->getFile(); 71 | $ioFile->expects(self::once()) 72 | ->method('checkAndCreateFolder') 73 | ->with($expectedBackupPath, BackupHandler::BACKUP_DIRECTORY_FILEMODE) 74 | ->willReturn(true); 75 | $ioFile->expects(self::once()) 76 | ->method('cp') 77 | ->willReturn(true); 78 | 79 | $backupHandler = new BackupHandler( 80 | $maintenanceMode, 81 | $backupRollbackFactory, 82 | $setup, 83 | $ioFile 84 | ); 85 | 86 | $backupHandler->beginTransaction(); 87 | $backupHandler->run($output, $expectedBackupPath); 88 | $backupHandler->endTransaction(); 89 | } 90 | 91 | /** 92 | * @test 93 | */ 94 | public function runFailsOnCopyingDumpFile(): void 95 | { 96 | $this->expectException(\RuntimeException::class); 97 | 98 | $expectedBackupPath = sys_get_temp_dir(); 99 | 100 | $output = $this->getOutput(); 101 | 102 | $maintenanceMode = $this->getMaintenanceMode(); 103 | $maintenanceMode->expects(self::once()) 104 | ->method('isOn') 105 | ->willReturn(false); 106 | $maintenanceMode->expects(self::once()) 107 | ->method('set') 108 | ->with(true); 109 | 110 | $backupRollback = $this->getMockBuilder(BackupRollback::class) 111 | ->disableOriginalConstructor() 112 | ->getMock(); 113 | $backupRollback->expects(self::once()) 114 | ->method('dbBackup') 115 | ->willReturn('/mybackup.bak'); 116 | $backupRollbackFactory = $this->getBackupRollbackFactory(); 117 | $backupRollbackFactory->expects(self::once()) 118 | ->method('create') 119 | ->with($output) 120 | ->willReturn($backupRollback); 121 | 122 | $connection = $this->createMock(AdapterInterface::class); 123 | $connection->expects(self::once()) 124 | ->method('beginTransaction'); 125 | $setup = $this->getModuleDataSetup(); 126 | $setup->expects(self::exactly(1)) 127 | ->method('getConnection') 128 | ->willReturn($connection); 129 | 130 | $ioFile = $this->getFile(); 131 | $ioFile->expects(self::once()) 132 | ->method('checkAndCreateFolder') 133 | ->with($expectedBackupPath, BackupHandler::BACKUP_DIRECTORY_FILEMODE) 134 | ->willReturn(true); 135 | $ioFile->expects(self::once()) 136 | ->method('cp') 137 | ->willReturn(false); 138 | 139 | $backupHandler = new BackupHandler( 140 | $maintenanceMode, 141 | $backupRollbackFactory, 142 | $setup, 143 | $ioFile 144 | ); 145 | 146 | $backupHandler->beginTransaction(); 147 | $backupHandler->run($output, $expectedBackupPath); 148 | } 149 | 150 | /** 151 | * @test 152 | */ 153 | public function runFailsOnCreatingBackupFolder(): void 154 | { 155 | $this->expectException(\RuntimeException::class); 156 | $this->expectExceptionMessage('Could not create backup folder: "/tmp"'); 157 | 158 | $expectedBackupPath = sys_get_temp_dir(); 159 | 160 | $output = $this->getOutput(); 161 | 162 | $maintenanceMode = $this->getMaintenanceMode(); 163 | $maintenanceMode->expects(self::once()) 164 | ->method('isOn') 165 | ->willReturn(false); 166 | $maintenanceMode->expects(self::once()) 167 | ->method('set') 168 | ->with(true); 169 | 170 | $backupRollbackFactory = $this->getBackupRollbackFactory(); 171 | 172 | $connection = $this->createMock(AdapterInterface::class); 173 | $connection->expects(self::once()) 174 | ->method('beginTransaction'); 175 | $setup = $this->getModuleDataSetup(); 176 | $setup->expects(self::exactly(1)) 177 | ->method('getConnection') 178 | ->willReturn($connection); 179 | 180 | $ioFile = $this->getFile(); 181 | $ioFile->expects(self::once()) 182 | ->method('checkAndCreateFolder') 183 | ->with($expectedBackupPath, BackupHandler::BACKUP_DIRECTORY_FILEMODE) 184 | ->willThrowException(new LocalizedException( 185 | new Phrase("Unable to create directory '.$expectedBackupPath.'. Access forbidden."))); 186 | 187 | $backupHandler = new BackupHandler( 188 | $maintenanceMode, 189 | $backupRollbackFactory, 190 | $setup, 191 | $ioFile 192 | ); 193 | 194 | $backupHandler->beginTransaction(); 195 | $backupHandler->run($output, $expectedBackupPath); 196 | } 197 | 198 | /** 199 | * @return MockObject&MaintenanceMode 200 | */ 201 | private function getMaintenanceMode() 202 | { 203 | return $this->getMockBuilder(MaintenanceMode::class) 204 | ->disableOriginalConstructor() 205 | ->getMock(); 206 | } 207 | 208 | /** 209 | * @return MockObject&BackupRollbackFactory 210 | */ 211 | private function getBackupRollbackFactory() 212 | { 213 | return $this->getMockBuilder(BackupRollbackFactory::class) 214 | ->disableOriginalConstructor() 215 | ->getMock(); 216 | } 217 | 218 | /** 219 | * @return MockObject&ModuleDataSetupInterface 220 | */ 221 | private function getModuleDataSetup() 222 | { 223 | return $this->getMockBuilder(ModuleDataSetupInterface::class) 224 | ->disableOriginalConstructor() 225 | ->getMock(); 226 | } 227 | 228 | /** 229 | * @return MockObject&File 230 | */ 231 | private function getFile() 232 | { 233 | return $this->getMockBuilder(File::class) 234 | ->disableOriginalConstructor() 235 | ->getMock(); 236 | } 237 | 238 | /** 239 | * @return MockObject&OutputInterface 240 | */ 241 | private function getOutput() 242 | { 243 | return $this->getMockBuilder(OutputInterface::class) 244 | ->disableOriginalConstructor() 245 | ->getMock(); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /Test/Unit/Model/Backup/FactoryTest.php: -------------------------------------------------------------------------------- 1 | getDatabaseHandler(); 34 | $backupEntity = $this->createMock(BackupInterface::class); 35 | 36 | $om = $this->getObjectManager(); 37 | $om->expects(self::once()) 38 | ->method('create') 39 | ->with('Magento\Framework\Backup\Filesystem') 40 | ->willReturn($backupEntity); 41 | 42 | $factory = new Factory($om, $databaseHandler); 43 | 44 | self::assertEquals($databaseHandler, $factory->create(Factory::TYPE_GDPR_DB)); 45 | self::assertEquals($backupEntity, $factory->create(Factory::TYPE_FILESYSTEM)); 46 | } 47 | 48 | /** 49 | * @return MockObject&ObjectManagerInterface 50 | */ 51 | private function getObjectManager() 52 | { 53 | return $this->createMock(ObjectManagerInterface::class); 54 | } 55 | 56 | /** 57 | * @return MockObject&DatabaseHandler 58 | */ 59 | private function getDatabaseHandler() 60 | { 61 | return $this->getMockBuilder(DatabaseHandler::class) 62 | ->disableOriginalConstructor() 63 | ->getMock(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Test/Unit/Model/ConfigurationFactoryTest.php: -------------------------------------------------------------------------------- 1 | createMock(Configuration::class); 33 | 34 | $om = $this->getObjectManager(); 35 | $om->expects(self::once()) 36 | ->method('create') 37 | ->with(Configuration::class, ['foo' => 'bar']) 38 | ->willReturn($expectedEntity); 39 | 40 | $factory = new ConfigurationFactory($om); 41 | 42 | self::assertEquals($expectedEntity, $factory->create(['foo' => 'bar'])); 43 | } 44 | 45 | /** 46 | * @return MockObject&ObjectManagerInterface 47 | */ 48 | private function getObjectManager() 49 | { 50 | return $this->createMock(ObjectManagerInterface::class); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Test/Unit/Model/ConfigurationTest.php: -------------------------------------------------------------------------------- 1 | setUseOnlyEmpty(true); 33 | self::assertTrue($configuration->isUseOnlyEmpty()); 34 | $configuration->setUseOnlyEmpty(false); 35 | self::assertFalse($configuration->isUseOnlyEmpty()); 36 | $configuration->setApplyToCategories(true); 37 | self::assertTrue($configuration->isApplyToCategories()); 38 | $configuration->setApplyToCategories(false); 39 | self::assertFalse($configuration->isApplyToCategories()); 40 | $configuration->setApplyToCmsBlocks(true); 41 | self::assertTrue($configuration->isApplyToCmsBlocks()); 42 | $configuration->setApplyToCmsBlocks(false); 43 | self::assertFalse($configuration->isApplyToCmsBlocks()); 44 | $configuration->setApplyToCmsPages(true); 45 | self::assertTrue($configuration->isApplyToCmsPages()); 46 | $configuration->setApplyToCmsPages(false); 47 | self::assertFalse($configuration->isApplyToCmsPages()); 48 | $configuration->setApplyToCustomers(true); 49 | self::assertTrue($configuration->isApplyToCustomers()); 50 | $configuration->setApplyToCustomers(false); 51 | self::assertFalse($configuration->isApplyToCustomers()); 52 | $configuration->setApplyToProducts(true); 53 | self::assertTrue($configuration->isApplyToProducts()); 54 | $configuration->setApplyToProducts(false); 55 | self::assertFalse($configuration->isApplyToProducts()); 56 | $configuration->setApplyToUsers(true); 57 | self::assertTrue($configuration->isApplyToUsers()); 58 | $configuration->setApplyToUsers(false); 59 | self::assertFalse($configuration->isApplyToUsers()); 60 | 61 | // --- Options 62 | $configuration->setDummyContentText('OPTION_DUMMY_CONTENT_TEXT'); 63 | self::assertEquals('OPTION_DUMMY_CONTENT_TEXT', $configuration->getDummyContentText()); 64 | $configuration->setDummyPassword('OPTION_DUMMY_PASSWORD'); 65 | self::assertEquals('OPTION_DUMMY_PASSWORD', $configuration->getDummyPassword()); 66 | $configuration->setDummyContentEmail('OPTION_DUMMY_CONTENT_EMAIL'); 67 | self::assertEquals('OPTION_DUMMY_CONTENT_EMAIL', $configuration->getDummyContentEmail()); 68 | $configuration->setDummyContentUrl('OPTION_DUMMY_CONTENT_URL'); 69 | self::assertEquals('OPTION_DUMMY_CONTENT_URL', $configuration->getDummyContentUrl()); 70 | $configuration->setDummyPhoneNumber('OPTION_DUMMY_CONTENT_PHONE'); 71 | self::assertEquals('OPTION_DUMMY_CONTENT_PHONE', $configuration->getDummyPhoneNumber()); 72 | $configuration->setDummyImagePath('OPTION_DUMMY_CONTENT_IMAGE'); 73 | self::assertEquals('OPTION_DUMMY_CONTENT_IMAGE', $configuration->getDummyImagePath()); 74 | 75 | // --- Extended data 76 | $extendedData = [ 77 | 'foo' => 'bar' 78 | ]; 79 | $configuration->setExtendedData($extendedData); 80 | self::assertEquals($extendedData, $configuration->getExtendedData()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Test/Unit/Observer/CategoriesObserverTest.php: -------------------------------------------------------------------------------- 1 | getUrlRewriteCollectionFactory(); 38 | $urlRewriteCollectionFactory->expects(self::never()) 39 | ->method('create'); 40 | 41 | $categoryResourceFactory = $this->getCategoryResourceFactory(); 42 | $categoryResourceFactory->expects(self::never()) 43 | ->method('create'); 44 | 45 | $categoryCollectionFactory = $this->getCategoryCollectionFactory(); 46 | $categoryCollectionFactory->expects(self::never()) 47 | ->method('create'); 48 | 49 | $configuration = $this->getConfiguration(); 50 | $configuration->expects(self::once()) 51 | ->method('isApplyToCategories') 52 | ->willReturn(false); 53 | 54 | $eventObserver = $this->getObserver(); 55 | $eventObserver->expects(self::once()) 56 | ->method('getData') 57 | ->with('configuration') 58 | ->willReturn($configuration); 59 | 60 | $observer = new CategoriesObserver($categoryCollectionFactory, $categoryResourceFactory, $urlRewriteCollectionFactory); 61 | 62 | $observer->execute($eventObserver); 63 | } 64 | 65 | /** 66 | * @test 67 | */ 68 | public function runSuccessfully(): void 69 | { 70 | $urlRewrite = $this->getMockBuilder(\Magento\UrlRewrite\Model\UrlRewrite::class) 71 | ->disableOriginalConstructor() 72 | ->getMock(); 73 | $urlRewrite->expects(self::once()) 74 | ->method('delete'); 75 | 76 | $urlRewriteCollection = $this->getMockBuilder(UrlRewriteCollection::class) 77 | ->disableOriginalConstructor() 78 | ->getMock(); 79 | $urlRewriteCollection->expects(self::once()) 80 | ->method('addFieldToFilter') 81 | ->with('entity_type', ['eq' => 'category']) 82 | ->willReturnSelf(); 83 | $urlRewriteCollection->expects(self::once()) 84 | ->method('load'); 85 | $urlRewriteCollection->expects(self::once()) 86 | ->method('getItems') 87 | ->willReturn([$urlRewrite]); 88 | 89 | $urlRewriteCollectionFactory = $this->getUrlRewriteCollectionFactory($urlRewriteCollection); 90 | 91 | $rootCategory = $this->getMockBuilder(Category::class) 92 | ->disableOriginalConstructor() 93 | ->getMock(); 94 | $rootCategory->expects(self::once()) 95 | ->method('getId') 96 | ->willReturn(CategoriesObserver::ROOT_CATEGORY_ID); 97 | 98 | $category = $this->getMockBuilder(Category::class) 99 | ->disableOriginalConstructor() 100 | ->getMock(); 101 | 102 | $categoryResource = $this->getMockBuilder(CategoryResource::class) 103 | ->disableOriginalConstructor() 104 | ->getMock(); 105 | $categoryResource->expects(self::once()) 106 | ->method('save') 107 | ->with($category); 108 | $categoryResourceFactory = $this->getCategoryResourceFactory($categoryResource); 109 | 110 | $categoryCollection = $this->getMockBuilder(CategoryCollection::class) 111 | ->disableOriginalConstructor() 112 | ->getMock(); 113 | $categoryCollection->expects(self::once()) 114 | ->method('load'); 115 | $categoryCollection->expects(self::once()) 116 | ->method('getItems') 117 | ->willReturn([$rootCategory, $category]); 118 | $categoryCollectionFactory = $this->getCategoryCollectionFactory($categoryCollection); 119 | 120 | $configuration = $this->getConfiguration(); 121 | $configuration->expects(self::once()) 122 | ->method('isApplyToCategories') 123 | ->willReturn(true); 124 | $configuration->expects(self::any()) 125 | ->method('isUseOnlyEmpty') 126 | ->willReturn(true); 127 | $configuration->expects(self::any()) 128 | ->method('getDummyContentText') 129 | ->willReturn('dummy-text'); 130 | $configuration->expects(self::any()) 131 | ->method('getDummyContentEmail') 132 | ->willReturn('dummy-email'); 133 | 134 | $eventObserver = $this->getObserver(); 135 | $eventObserver->expects(self::once()) 136 | ->method('getData') 137 | ->with('configuration') 138 | ->willReturn($configuration); 139 | 140 | 141 | $observer = new CategoriesObserver($categoryCollectionFactory, $categoryResourceFactory, $urlRewriteCollectionFactory); 142 | 143 | $observer->execute($eventObserver); 144 | } 145 | 146 | /** 147 | * @return MockObject&Observer 148 | */ 149 | private function getObserver() 150 | { 151 | return $this->createMock(Observer::class); 152 | } 153 | 154 | /** 155 | * @return MockObject&Configuration 156 | */ 157 | private function getConfiguration() 158 | { 159 | return $this->createMock(Configuration::class); 160 | } 161 | 162 | /** 163 | * @param MockObject $instance 164 | * @return MockObject&\Magento\Catalog\Model\ResourceModel\CategoryFactory 165 | */ 166 | private function getCategoryResourceFactory(MockObject $instance = null) 167 | { 168 | return $this->getFactoryAsMock('\Magento\Catalog\Model\ResourceModel\Category', $instance); 169 | } 170 | 171 | /** 172 | * @param MockObject $instance 173 | * @return MockObject&\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory 174 | */ 175 | private function getCategoryCollectionFactory(MockObject $instance = null) 176 | { 177 | return $this->getFactoryAsMock('\Magento\Catalog\Model\ResourceModel\Category\Collection', $instance); 178 | } 179 | 180 | /** 181 | * @param MockObject $instance 182 | * @return MockObject&\Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollectionFactory; 183 | */ 184 | private function getUrlRewriteCollectionFactory(MockObject $instance = null) 185 | { 186 | return $this->getFactoryAsMock('\Magento\UrlRewrite\Model\ResourceModel\UrlRewriteCollection', $instance); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /Test/Unit/Observer/CmsBlocksObserverTest.php: -------------------------------------------------------------------------------- 1 | getBlockResourceFactory(); 36 | $blockResourceFactory->expects(self::never()) 37 | ->method('create'); 38 | 39 | $blockCollectionFactory = $this->getBlockCollectionFactory(); 40 | $blockCollectionFactory->expects(self::never()) 41 | ->method('create'); 42 | 43 | $configuration = $this->getConfiguration(); 44 | $configuration->expects(self::once()) 45 | ->method('isApplyToCmsBlocks') 46 | ->willReturn(false); 47 | 48 | $eventObserver = $this->getObserver(); 49 | $eventObserver->expects(self::once()) 50 | ->method('getData') 51 | ->with('configuration') 52 | ->willReturn($configuration); 53 | 54 | $observer = new CmsBlocksObserver($blockCollectionFactory, $blockResourceFactory); 55 | 56 | $observer->execute($eventObserver); 57 | } 58 | 59 | /** 60 | * @test 61 | */ 62 | public function runSuccessfully(): void 63 | { 64 | $block = $this->getMockBuilder(Block::class) 65 | ->disableOriginalConstructor() 66 | ->getMock(); 67 | $block->expects(self::once()) 68 | ->method('getData') 69 | ->with('content') 70 | ->willReturn(null); 71 | $block->expects(self::once()) 72 | ->method('setData') 73 | ->with('content', 'dummy-text'); 74 | 75 | $blockResource = $this->getMockBuilder(BlockResource::class) 76 | ->disableOriginalConstructor() 77 | ->getMock(); 78 | $blockResource->expects(self::once()) 79 | ->method('save') 80 | ->with($block); 81 | $blockResourceFactory = $this->getBlockResourceFactory($blockResource); 82 | 83 | $blockCollection = $this->getMockBuilder(BlockCollection::class) 84 | ->disableOriginalConstructor() 85 | ->getMock(); 86 | $blockCollection->expects(self::once()) 87 | ->method('load'); 88 | $blockCollection->expects(self::once()) 89 | ->method('getItems') 90 | ->willReturn([$block]); 91 | $blockCollectionFactory = $this->getBlockCollectionFactory($blockCollection); 92 | 93 | $configuration = $this->getConfiguration(); 94 | $configuration->expects(self::once()) 95 | ->method('isApplyToCmsBlocks') 96 | ->willReturn(true); 97 | $configuration->expects(self::any()) 98 | ->method('isUseOnlyEmpty') 99 | ->willReturn(true); 100 | $configuration->expects(self::any()) 101 | ->method('getDummyContentText') 102 | ->willReturn('dummy-text'); 103 | $configuration->expects(self::any()) 104 | ->method('getDummyContentEmail') 105 | ->willReturn('dummy-email'); 106 | 107 | $eventObserver = $this->getObserver(); 108 | $eventObserver->expects(self::once()) 109 | ->method('getData') 110 | ->with('configuration') 111 | ->willReturn($configuration); 112 | 113 | 114 | $observer = new CmsBlocksObserver($blockCollectionFactory, $blockResourceFactory); 115 | 116 | $observer->execute($eventObserver); 117 | } 118 | 119 | /** 120 | * @return MockObject&Observer 121 | */ 122 | private function getObserver() 123 | { 124 | return $this->createMock(Observer::class); 125 | } 126 | 127 | /** 128 | * @return MockObject&Configuration 129 | */ 130 | private function getConfiguration() 131 | { 132 | return $this->createMock(Configuration::class); 133 | } 134 | 135 | /** 136 | * @param MockObject $instance 137 | * @return MockObject&\Magento\Cms\Model\ResourceModel\BlockFactory 138 | */ 139 | private function getBlockResourceFactory(MockObject $instance = null) 140 | { 141 | return $this->getFactoryAsMock('\Magento\Cms\Model\ResourceModel\Block', $instance); 142 | } 143 | 144 | /** 145 | * @param MockObject $instance 146 | * @return MockObject&\Magento\Cms\Model\ResourceModel\Block\CollectionFactory 147 | */ 148 | private function getBlockCollectionFactory(MockObject $instance = null) 149 | { 150 | return $this->getFactoryAsMock('\Magento\Cms\Model\ResourceModel\Block\Collection', $instance); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /Test/Unit/Observer/CmsPagesObserverTest.php: -------------------------------------------------------------------------------- 1 | getPageResourceFactory(); 36 | $pageResourceFactory->expects(self::never()) 37 | ->method('create'); 38 | 39 | $pageCollectionFactory = $this->getPageCollectionFactory(); 40 | $pageCollectionFactory->expects(self::never()) 41 | ->method('create'); 42 | 43 | $configuration = $this->getConfiguration(); 44 | $configuration->expects(self::once()) 45 | ->method('isApplyToCmsPages') 46 | ->willReturn(false); 47 | 48 | $eventObserver = $this->getObserver(); 49 | $eventObserver->expects(self::once()) 50 | ->method('getData') 51 | ->with('configuration') 52 | ->willReturn($configuration); 53 | 54 | $observer = new CmsPagesObserver($pageCollectionFactory, $pageResourceFactory); 55 | 56 | $observer->execute($eventObserver); 57 | } 58 | 59 | /** 60 | * @test 61 | */ 62 | public function runSuccessfully(): void 63 | { 64 | $page = $this->getMockBuilder(Page::class) 65 | ->disableOriginalConstructor() 66 | ->getMock(); 67 | 68 | $pageResource = $this->getMockBuilder(PageResource::class) 69 | ->disableOriginalConstructor() 70 | ->getMock(); 71 | $pageResource->expects(self::once()) 72 | ->method('save') 73 | ->with($page); 74 | $pageResourceFactory = $this->getPageResourceFactory($pageResource); 75 | 76 | $pageCollection = $this->getMockBuilder(PageCollection::class) 77 | ->disableOriginalConstructor() 78 | ->getMock(); 79 | $pageCollection->expects(self::once()) 80 | ->method('load'); 81 | $pageCollection->expects(self::once()) 82 | ->method('getItems') 83 | ->willReturn([$page]); 84 | $pageCollectionFactory = $this->getPageCollectionFactory($pageCollection); 85 | 86 | $configuration = $this->getConfiguration(); 87 | $configuration->expects(self::once()) 88 | ->method('isApplyToCmsPages') 89 | ->willReturn(true); 90 | $configuration->expects(self::any()) 91 | ->method('isUseOnlyEmpty') 92 | ->willReturn(true); 93 | $configuration->expects(self::any()) 94 | ->method('getDummyContentText') 95 | ->willReturn('dummy-text'); 96 | $configuration->expects(self::any()) 97 | ->method('getDummyContentEmail') 98 | ->willReturn('dummy-email'); 99 | 100 | $eventObserver = $this->getObserver(); 101 | $eventObserver->expects(self::once()) 102 | ->method('getData') 103 | ->with('configuration') 104 | ->willReturn($configuration); 105 | 106 | 107 | $observer = new CmsPagesObserver($pageCollectionFactory, $pageResourceFactory); 108 | 109 | $observer->execute($eventObserver); 110 | } 111 | 112 | /** 113 | * @return MockObject&Observer 114 | */ 115 | private function getObserver() 116 | { 117 | return $this->createMock(Observer::class); 118 | } 119 | 120 | /** 121 | * @return MockObject&Configuration 122 | */ 123 | private function getConfiguration() 124 | { 125 | return $this->createMock(Configuration::class); 126 | } 127 | 128 | /** 129 | * @param MockObject $instance 130 | * @return MockObject&\Magento\Cms\Model\ResourceModel\PageFactory 131 | */ 132 | private function getPageResourceFactory(MockObject $instance = null) 133 | { 134 | return $this->getFactoryAsMock('\Magento\Cms\Model\ResourceModel\Page', $instance); 135 | } 136 | 137 | /** 138 | * @param MockObject $instance 139 | * @return MockObject&\Magento\Cms\Model\ResourceModel\Page\CollectionFactory 140 | */ 141 | private function getPageCollectionFactory(MockObject $instance = null) 142 | { 143 | return $this->getFactoryAsMock('\Magento\Cms\Model\ResourceModel\Page\Collection', $instance); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /Test/Unit/Observer/CustomerPasswordsObserverTest.php: -------------------------------------------------------------------------------- 1 | getCustomerRepository(); 37 | $customerRepository->expects(self::never()) 38 | ->method('getById'); 39 | 40 | $customerCollectionFactory = $this->getCustomerCollectionFactory(); 41 | $customerCollectionFactory->expects(self::never()) 42 | ->method('create'); 43 | 44 | $configuration = $this->getConfiguration(); 45 | $configuration->expects(self::once()) 46 | ->method('isApplyToCustomers') 47 | ->willReturn(false); 48 | 49 | $eventObserver = $this->getObserver(); 50 | $eventObserver->expects(self::once()) 51 | ->method('getData') 52 | ->with('configuration') 53 | ->willReturn($configuration); 54 | 55 | $observer = new CustomerPasswordsObserver($customerCollectionFactory, $customerRepository); 56 | 57 | $observer->execute($eventObserver); 58 | } 59 | 60 | /** 61 | * @test 62 | */ 63 | public function runSuccessfully(): void 64 | { 65 | $customer = $this->getMockBuilder(Customer::class) 66 | ->disableOriginalConstructor() 67 | ->getMock(); 68 | $customer->expects(self::once()) 69 | ->method('getId') 70 | ->willReturn(42); 71 | $customerData = $this->getMockBuilder(CustomerInterface::class) 72 | ->setMethods([ 73 | 'setPassword', 74 | 'getId', 75 | 'setId', 76 | 'getGroupId', 77 | 'setGroupId', 78 | 'getDefaultBilling', 79 | 'setDefaultBilling', 80 | 'getDefaultShipping', 81 | 'setDefaultShipping', 82 | 'getConfirmation', 83 | 'setConfirmation', 84 | 'getCreatedAt', 85 | 'setCreatedAt', 86 | 'getUpdatedAt', 87 | 'setUpdatedAt', 88 | 'getCreatedIn', 89 | 'setCreatedIn', 90 | 'getDob', 91 | 'setDob', 92 | 'getEmail', 93 | 'setEmail', 94 | 'getFirstname', 95 | 'setFirstname', 96 | 'getLastname', 97 | 'setLastname', 98 | 'getMiddlename', 99 | 'setMiddlename', 100 | 'getPrefix', 101 | 'setPrefix', 102 | 'getSuffix', 103 | 'setSuffix', 104 | 'getGender', 105 | 'setGender', 106 | 'getStoreId', 107 | 'setStoreId', 108 | 'getTaxvat', 109 | 'setTaxvat', 110 | 'getWebsiteId', 111 | 'setWebsiteId', 112 | 'getAddresses', 113 | 'setAddresses', 114 | 'getDisableAutoGroupChange', 115 | 'setDisableAutoGroupChange', 116 | 'getExtensionAttributes', 117 | 'setExtensionAttributes', 118 | 'getCustomAttribute', 119 | 'setCustomAttribute', 120 | 'getCustomAttributes', 121 | 'setCustomAttributes' 122 | ]) 123 | ->getMock(); 124 | 125 | $customerRepository = $this->getCustomerRepository(); 126 | $customerRepository->expects(self::once()) 127 | ->method('getById') 128 | ->with(42) 129 | ->willReturn($customerData); 130 | $customerRepository->expects(self::once()) 131 | ->method('save') 132 | ->with($customerData); 133 | 134 | $customerCollection = $this->getMockBuilder(CustomerCollection::class) 135 | ->disableOriginalConstructor() 136 | ->getMock(); 137 | $customerCollection->expects(self::once()) 138 | ->method('load'); 139 | $customerCollection->expects(self::once()) 140 | ->method('getItems') 141 | ->willReturn([$customer]); 142 | $customerCollectionFactory = $this->getCustomerCollectionFactory($customerCollection); 143 | 144 | $configuration = $this->getConfiguration(); 145 | $configuration->expects(self::once()) 146 | ->method('isApplyToCustomers') 147 | ->willReturn(true); 148 | $configuration->expects(self::any()) 149 | ->method('getDummyPassword') 150 | ->willReturn('password'); 151 | 152 | $eventObserver = $this->getObserver(); 153 | $eventObserver->expects(self::once()) 154 | ->method('getData') 155 | ->with('configuration') 156 | ->willReturn($configuration); 157 | 158 | 159 | $observer = new CustomerPasswordsObserver($customerCollectionFactory, $customerRepository); 160 | 161 | $observer->execute($eventObserver); 162 | } 163 | 164 | /** 165 | * @return MockObject&Observer 166 | */ 167 | private function getObserver() 168 | { 169 | return $this->createMock(Observer::class); 170 | } 171 | 172 | /** 173 | * @return MockObject&Configuration 174 | */ 175 | private function getConfiguration() 176 | { 177 | return $this->createMock(Configuration::class); 178 | } 179 | 180 | /** 181 | * @return MockObject&CustomerRepositoryInterface 182 | */ 183 | private function getCustomerRepository() 184 | { 185 | return $this->createMock(CustomerRepositoryInterface::class); 186 | } 187 | 188 | /** 189 | * @param MockObject $instance 190 | * @return MockObject&\Magento\Customer\Model\ResourceModel\Customer\CollectionFactory 191 | */ 192 | private function getCustomerCollectionFactory(MockObject $instance = null) 193 | { 194 | return $this->getFactoryAsMock('\Magento\Customer\Model\ResourceModel\Customer\Collection', $instance); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /Test/Unit/Observer/FuzzyObserverTest.php: -------------------------------------------------------------------------------- 1 | createMock(Configuration::class); 32 | 33 | /** @var FuzzyfyrObserver|MockObject $observer */ 34 | $observer = $this->getMockForAbstractClass(FuzzyfyrObserver::class); 35 | $class = new \ReflectionClass(FuzzyfyrObserver::class); 36 | $method = $class->getMethod('isValid'); 37 | $method->setAccessible(true); 38 | self::assertTrue($method->invokeArgs($observer, [$configuration])); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Test/Unit/Observer/ProductsObserverTest.php: -------------------------------------------------------------------------------- 1 | getProductResourceFactory(); 36 | $productResourceFactory->expects(self::never()) 37 | ->method('create'); 38 | 39 | $productCollection = $this->getMockBuilder(ProductCollection::class) 40 | ->disableOriginalConstructor() 41 | ->getMock(); 42 | $productCollectionFactory = $this->getProductCollectionFactory($productCollection); 43 | $productCollectionFactory->expects(self::never()) 44 | ->method('create'); 45 | 46 | $configuration = $this->getConfiguration(); 47 | $configuration->expects(self::once()) 48 | ->method('isApplyToProducts') 49 | ->willReturn(false); 50 | 51 | $eventObserver = $this->getObserver(); 52 | $eventObserver->expects(self::once()) 53 | ->method('getData') 54 | ->with('configuration') 55 | ->willReturn($configuration); 56 | 57 | $observer = new ProductsObserver($productCollectionFactory, $productResourceFactory); 58 | 59 | $observer->execute($eventObserver); 60 | } 61 | 62 | /** 63 | * @test 64 | */ 65 | public function runSuccessfully(): void 66 | { 67 | $product = $this->getMockBuilder(Product::class) 68 | ->disableOriginalConstructor() 69 | ->getMock(); 70 | 71 | $productResource = $this->getMockBuilder(ProductResource::class) 72 | ->disableOriginalConstructor() 73 | ->getMock(); 74 | $productResource->expects(self::once()) 75 | ->method('save') 76 | ->with($product); 77 | $productResourceFactory = $this->getProductResourceFactory($productResource); 78 | 79 | $productCollection = $this->getMockBuilder(ProductCollection::class) 80 | ->disableOriginalConstructor() 81 | ->getMock(); 82 | $productCollection->expects(self::once()) 83 | ->method('load'); 84 | $productCollection->expects(self::once()) 85 | ->method('getItems') 86 | ->willReturn([$product]); 87 | $productCollectionFactory = $this->getProductCollectionFactory($productCollection); 88 | 89 | $configuration = $this->getConfiguration(); 90 | $configuration->expects(self::once()) 91 | ->method('isApplyToProducts') 92 | ->willReturn(true); 93 | $configuration->expects(self::any()) 94 | ->method('isUseOnlyEmpty') 95 | ->willReturn(true); 96 | $configuration->expects(self::any()) 97 | ->method('getDummyContentText') 98 | ->willReturn('dummy-text'); 99 | $configuration->expects(self::any()) 100 | ->method('getDummyContentEmail') 101 | ->willReturn('dummy-email'); 102 | 103 | $eventObserver = $this->getObserver(); 104 | $eventObserver->expects(self::once()) 105 | ->method('getData') 106 | ->with('configuration') 107 | ->willReturn($configuration); 108 | 109 | 110 | $observer = new ProductsObserver($productCollectionFactory, $productResourceFactory); 111 | 112 | $observer->execute($eventObserver); 113 | } 114 | 115 | /** 116 | * @return MockObject&Observer 117 | */ 118 | private function getObserver() 119 | { 120 | return $this->createMock(Observer::class); 121 | } 122 | 123 | /** 124 | * @return MockObject&Configuration 125 | */ 126 | private function getConfiguration() 127 | { 128 | return $this->createMock(Configuration::class); 129 | } 130 | 131 | /** 132 | * @param MockObject $instance 133 | * @return MockObject&\Magento\Catalog\Model\ResourceModel\ProductFactory 134 | */ 135 | private function getProductResourceFactory(MockObject $instance = null) 136 | { 137 | return $this->getFactoryAsMock('\Magento\Catalog\Model\ResourceModel\Product', $instance); 138 | } 139 | 140 | /** 141 | * @param MockObject $instance 142 | * @return MockObject&\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory 143 | */ 144 | private function getProductCollectionFactory(MockObject $instance = null) 145 | { 146 | return $this->getFactoryAsMock('\Magento\Catalog\Model\ResourceModel\Product\Collection', $instance); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Test/Unit/Observer/UsersObserverTest.php: -------------------------------------------------------------------------------- 1 | getUserResourceFactory(); 36 | $userResourceFactory->expects(self::never()) 37 | ->method('create'); 38 | 39 | $userCollectionFactory = $this->getUserCollectionFactory(); 40 | $userCollectionFactory->expects(self::never()) 41 | ->method('create'); 42 | 43 | $configuration = $this->getConfiguration(); 44 | $configuration->expects(self::once()) 45 | ->method('isApplyToUsers') 46 | ->willReturn(false); 47 | 48 | $eventObserver = $this->getObserver(); 49 | $eventObserver->expects(self::once()) 50 | ->method('getData') 51 | ->with('configuration') 52 | ->willReturn($configuration); 53 | 54 | $observer = new UsersObserver($userCollectionFactory, $userResourceFactory); 55 | 56 | $observer->execute($eventObserver); 57 | } 58 | 59 | /** 60 | * @test 61 | */ 62 | public function runSuccessfully(): void 63 | { 64 | $user = $this->getMockBuilder(User::class) 65 | ->disableOriginalConstructor() 66 | ->getMock(); 67 | $user->expects(self::once()) 68 | ->method('setEmail') 69 | ->with('dummy-email'); 70 | $user->expects(self::once()) 71 | ->method('setLastname') 72 | ->with('dummy-text'); 73 | 74 | $userResource = $this->getMockBuilder(UserResource::class) 75 | ->disableOriginalConstructor() 76 | ->getMock(); 77 | $userResource->expects(self::once()) 78 | ->method('save') 79 | ->with($user); 80 | $userResourceFactory = $this->getUserResourceFactory($userResource); 81 | 82 | $userCollection = $this->getMockBuilder(UserCollection::class) 83 | ->disableOriginalConstructor() 84 | ->getMock(); 85 | $userCollection->expects(self::once()) 86 | ->method('load'); 87 | $userCollection->expects(self::once()) 88 | ->method('getItems') 89 | ->willReturn([$user]); 90 | $userCollectionFactory = $this->getUserCollectionFactory($userCollection); 91 | 92 | $configuration = $this->getConfiguration(); 93 | $configuration->expects(self::once()) 94 | ->method('isApplyToUsers') 95 | ->willReturn(true); 96 | $configuration->expects(self::any()) 97 | ->method('getDummyContentText') 98 | ->willReturn('dummy-text'); 99 | $configuration->expects(self::any()) 100 | ->method('getDummyContentEmail') 101 | ->willReturn('dummy-email'); 102 | 103 | $eventObserver = $this->getObserver(); 104 | $eventObserver->expects(self::once()) 105 | ->method('getData') 106 | ->with('configuration') 107 | ->willReturn($configuration); 108 | 109 | 110 | $observer = new UsersObserver($userCollectionFactory, $userResourceFactory); 111 | 112 | $observer->execute($eventObserver); 113 | } 114 | 115 | /** 116 | * @return MockObject&Observer 117 | */ 118 | private function getObserver() 119 | { 120 | return $this->createMock(Observer::class); 121 | } 122 | 123 | /** 124 | * @return MockObject&Configuration 125 | */ 126 | private function getConfiguration() 127 | { 128 | return $this->createMock(Configuration::class); 129 | } 130 | 131 | /** 132 | * @param MockObject $instance 133 | * @return MockObject&\Magento\User\Model\ResourceModel\UserFactory 134 | */ 135 | private function getUserResourceFactory(MockObject $instance = null) 136 | { 137 | return $this->getFactoryAsMock('\Magento\User\Model\ResourceModel\User', $instance); 138 | } 139 | 140 | /** 141 | * @param MockObject $instance 142 | * @return MockObject&\Magento\User\Model\ResourceModel\User\CollectionFactory 143 | */ 144 | private function getUserCollectionFactory(MockObject $instance = null) 145 | { 146 | return $this->getFactoryAsMock('\Magento\User\Model\ResourceModel\User\Collection', $instance); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /Test/Unit/bootstrap.php: -------------------------------------------------------------------------------- 1 | /dev/null 2>&1 5 | -------------------------------------------------------------------------------- /bin/composer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/cli composer "$@" 3 | -------------------------------------------------------------------------------- /bin/copyfromcontainer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ -z "$1" ] && echo "Please specify a directory or file to copy from container (ex. vendor, --all)" && exit 3 | 4 | REAL_SRC=$(cd -P "src" && pwd) 5 | if [ "$1" == "--all" ]; then 6 | docker cp "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/./ "$REAL_SRC/" 7 | echo "Completed copying all files from container to host" 8 | else 9 | if [ -f "$1" ] ; then 10 | docker cp "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$1" "$REAL_SRC/$1" 11 | else 12 | docker cp "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$1" "$REAL_SRC/$(dirname "$1")" 13 | fi 14 | echo "Completed copying $1 from container to host" 15 | fi 16 | -------------------------------------------------------------------------------- /bin/copytocontainer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ -z "$1" ] && echo "Please specify a directory or file to copy to container (ex. vendor, --all)" && exit 3 | 4 | REAL_SRC=$(cd -P "src" && pwd) 5 | if [ "$1" == "--all" ]; then 6 | docker cp "$REAL_SRC/./" "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/ 7 | echo "Completed copying all files from host to container" 8 | bin/fixowns 9 | bin/fixperms 10 | else 11 | if [ -f "$REAL_SRC/$1" ]; then 12 | docker cp "$REAL_SRC/${1}" "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$1" 13 | else 14 | docker cp "$REAL_SRC/${1}" "$(docker-compose ps -q phpfpm|awk '{print $1}')":/var/www/html/"$(dirname "$1")" 15 | fi 16 | echo "Completed copying $1 from host to container" 17 | bin/fixowns "$1" 18 | bin/fixperms "$1" 19 | fi 20 | -------------------------------------------------------------------------------- /bin/cron: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ -z "$1" ] && echo "Please specify a CLI command (ex. ls)" && exit 3 | bin/root service cron "$@" 4 | bin/root touch /var/www/html/var/.setup_cronjob_status /var/www/html/var/.update_cronjob_status 5 | bin/root chown app:app /var/www/html/var/.setup_cronjob_status /var/www/html/var/.update_cronjob_status 6 | -------------------------------------------------------------------------------- /bin/dev-test-run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -z "$1" ] && echo "Please specify test type (ex. integration)" && exit 4 | 5 | TEST_TYPE="$1" 6 | shift 7 | bin/clinotty bash -c "cd dev/tests/${TEST_TYPE} && ../../../vendor/bin/phpunit -c phpunit.xml.dist $*" 8 | -------------------------------------------------------------------------------- /bin/dev-urn-catalog-generate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/magento dev:urn-catalog:generate misc.xml 3 | bin/copyfromcontainer misc.xml 4 | mv src/misc.xml src/.idea/misc.xml 5 | 6 | echo "URN's have been generated, you may now restart PHPStorm" 7 | -------------------------------------------------------------------------------- /bin/devconsole: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/cli bin/n98-magerun2.phar dev:console 3 | -------------------------------------------------------------------------------- /bin/download: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | 4 | VERSION=${1:-2.4.4} 5 | EDITION=${2:-community} 6 | 7 | bin/stop 8 | docker-compose -f docker-compose.yml up -d 9 | [ $? != 0 ] && echo "Failed to start Docker services" && exit 10 | 11 | bin/setup-composer-auth 12 | 13 | bin/clinotty composer create-project --repository=https://repo.magento.com/ magento/project-"${EDITION}"-edition="${VERSION}" . 14 | 15 | bin/clinotty cp /var/www/html/nginx.conf.sample /var/www/html/nginx.conf 16 | -------------------------------------------------------------------------------- /bin/fixowns: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Fixing filesystem ownerships..." 3 | 4 | if [ -z "$1" ]; then 5 | bin/rootnotty chown -R app:app /var/www/ 6 | else 7 | bin/rootnotty chown -R app:app /var/www/html/"$1" 8 | fi 9 | 10 | echo "Filesystem ownerships fixed." 11 | -------------------------------------------------------------------------------- /bin/fixperms: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Fixing filesystem permissions..." 3 | 4 | if [ -z "$1" ]; then 5 | bin/clinotty find var vendor pub/static pub/media app/etc \( -type f -or -type d \) -exec chmod u+w {} +; 6 | bin/clinotty chmod u+x bin/magento 7 | else 8 | bin/clinotty find "$1" \( -type f -or -type d \) -exec chmod u+w {} +; 9 | fi 10 | 11 | echo "Filesystem permissions fixed." 12 | -------------------------------------------------------------------------------- /bin/githook: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script will be called from the Git Hooks on the host and redirect the CaptainHookPHP commands into the phpfpm 3 | # container. For some odd reason it was needed to change the working directory so that CaptainHookPHP can resolve paths 4 | # properly 5 | [ -z "$1" ] && echo "Please specify a CLI command (ex. ls)" && exit 6 | # make sure the phpfpm container is running before trying to execute the git hook 7 | docker-compose up --no-recreate -d phpfpm 8 | docker-compose exec -w /var/www/html/HiveCommerce/ContentFuzzyfyr/ -T phpfpm "$@" 9 | 10 | -------------------------------------------------------------------------------- /bin/grunt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/cli grunt "$@" 3 | -------------------------------------------------------------------------------- /bin/magento: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/cli bin/magento "$@" 3 | -------------------------------------------------------------------------------- /bin/mftf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/clinotty vendor/bin/mftf "$@" -------------------------------------------------------------------------------- /bin/mysql: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck source=../env/db.env 4 | source env/db.env 5 | if [ -t 0 ]; then 6 | # Need tty to run mysql shell 7 | bin/cli mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" "$@" 8 | else 9 | # Read from stdin, ex: bin/mysql < dbdump.sql 10 | bin/clinotty mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" -p"${MYSQL_PASSWORD}" "${MYSQL_DATABASE}" "$@" 11 | fi 12 | -------------------------------------------------------------------------------- /bin/mysqldump: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/n98-magerun2 db:dump --stdout "$@" 3 | -------------------------------------------------------------------------------- /bin/n98-magerun2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if ! bin/cliq ls bin/n98-magerun2.phar; then 3 | echo "Downloading n98-magerun2.phar, just a moment..." 4 | bin/clinotty curl -sS -O https://files.magerun.net/n98-magerun2.phar 5 | bin/clinotty curl -sS -o n98-magerun2.phar.sha256 https://files.magerun.net/sha256.php?file=n98-magerun2.phar 6 | bin/clinotty shasum -a 256 -c n98-magerun2.phar.sha256 7 | [ $? != 0 ] && echo "sha256 checksum do not match!" && exit 8 | 9 | bin/cliq chmod +x n98-magerun2.phar 10 | bin/cliq mkdir -p bin 11 | bin/cliq mv n98-magerun2.phar bin 12 | fi 13 | 14 | S=$(bin/cli cat /usr/local/etc/php/php.ini | grep -iGc 'xdebug.mode = off'); 15 | 16 | if [[ $S == 1 ]]; then 17 | bin/cli bin/n98-magerun2.phar "$@" 18 | else 19 | bin/cli php -dxdebug.mode=debug -dxdebug.start_with_request=yes bin/n98-magerun2.phar "$@" 20 | fi 21 | -------------------------------------------------------------------------------- /bin/node: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/cli node "$@" 3 | -------------------------------------------------------------------------------- /bin/npm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/cli npm "$@" 3 | -------------------------------------------------------------------------------- /bin/pwa-studio: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | 4 | if [ ! -d pwa-studio ]; then 5 | echo "PWA studio must first be installed by running bin/setup-pwa-studio" 6 | exit 7 | fi 8 | 9 | cd pwa-studio 10 | NODE_TLS_REJECT_UNAUTHORIZED=0 yarn run watch:all 11 | -------------------------------------------------------------------------------- /bin/redis: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker-compose exec redis "$@" 3 | -------------------------------------------------------------------------------- /bin/remove: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker-compose -f docker-compose.yml -f docker-compose.dev.yml rm 3 | -------------------------------------------------------------------------------- /bin/removeall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/remove 3 | bin/removevolumes 4 | -------------------------------------------------------------------------------- /bin/removevolumes: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | current_folder=${PWD##*/} 3 | volume_prefix=$(echo "$current_folder" | awk '{print tolower($0)}' | sed 's/\.//g') 4 | docker volume rm "${volume_prefix}"_appdata 5 | docker volume rm "${volume_prefix}"_dbdata 6 | docker volume rm "${volume_prefix}"_rabbitmqdata 7 | docker volume rm "${volume_prefix}"_sockdata 8 | docker volume rm "${volume_prefix}"_ssldata 9 | -------------------------------------------------------------------------------- /bin/restart: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bin/stop "$@" 3 | bin/start "$@" 4 | -------------------------------------------------------------------------------- /bin/root: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ -z "$1" ] && echo "Please specify a CLI command (ex. ls)" && exit 3 | docker-compose exec -u root phpfpm "$@" 4 | -------------------------------------------------------------------------------- /bin/rootnotty: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ -z "$1" ] && echo "Please specify a CLI command (ex. ls)" && exit 3 | docker-compose exec -u root -T phpfpm "$@" 4 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | 4 | # shellcheck source=../env/db.env 5 | source env/db.env 6 | # shellcheck source=../env/magento.env 7 | source env/magento.env 8 | 9 | DOMAIN=${1:-magento.test} 10 | ES_HOST=elasticsearch 11 | ES_PORT=9200 12 | 13 | bin/download 14 | 15 | bin/stop 16 | 17 | docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d 18 | [ $? != 0 ] && echo "Failed to start Docker services" && exit 19 | 20 | bin/clinotty chmod u+x bin/magento 21 | 22 | echo "Waiting for connection to Elasticsearch..." 23 | bin/clinotty timeout 100 bash -c " 24 | until curl --silent --output /dev/null http://$ES_HOST:$ES_PORT/_cat/health?h=st; do 25 | printf '.' 26 | sleep 2 27 | done" 28 | [ $? != 0 ] && echo "Failed to connect to Elasticsearch" && exit 29 | 30 | sleep 2 31 | 32 | bin/clinotty bin/magento setup:install \ 33 | --db-host="$MYSQL_HOST" \ 34 | --db-name="$MYSQL_DATABASE" \ 35 | --db-user="$MYSQL_USER" \ 36 | --db-password="$MYSQL_PASSWORD" \ 37 | --base-url=https://"$DOMAIN"/ \ 38 | --base-url-secure=https://"$DOMAIN"/ \ 39 | --backend-frontname="$MAGENTO_ADMIN_FRONTNAME" \ 40 | --admin-firstname="$MAGENTO_ADMIN_FIRST_NAME" \ 41 | --admin-lastname="$MAGENTO_ADMIN_LAST_NAME" \ 42 | --admin-email="$MAGENTO_ADMIN_EMAIL" \ 43 | --admin-user="$MAGENTO_ADMIN_USER" \ 44 | --admin-password="$MAGENTO_ADMIN_PASSWORD" \ 45 | --language="$MAGENTO_LOCALE" \ 46 | --currency="$MAGENTO_CURRENCY" \ 47 | --timezone="$MAGENTO_TIMEZONE" \ 48 | --amqp-host=rabbitmq \ 49 | --amqp-port=5672 \ 50 | --amqp-user=guest \ 51 | --amqp-password=guest \ 52 | --amqp-virtualhost=/ \ 53 | --cache-backend=redis \ 54 | --cache-backend-redis-server=redis \ 55 | --cache-backend-redis-db=0 \ 56 | --page-cache=redis \ 57 | --page-cache-redis-server=redis \ 58 | --page-cache-redis-db=1 \ 59 | --session-save=redis \ 60 | --session-save-redis-host=redis \ 61 | --session-save-redis-log-level=4 \ 62 | --session-save-redis-db=2 \ 63 | --search-engine=elasticsearch7 \ 64 | --elasticsearch-host=$ES_HOST \ 65 | --elasticsearch-port=$ES_PORT \ 66 | --use-rewrites=1 67 | 68 | echo "Disable Magento 2FAuth module..." 69 | bin/magento module:disable Magento_TwoFactorAuth 70 | 71 | echo "Installing ContentFuzzyfyr Composer module..." 72 | bin/rootnotty chmod +x /var/www/html/HiveCommerce/ContentFuzzyfyr/validate_m2_package.php 73 | bin/rootnotty chown -R app.app /dist 74 | bin/clinotty composer config minimum-stability dev 75 | bin/clinotty composer config "repositories.hivecommerce/magento2-content-fuzzyfyr" '{"type": "path", "url": "/var/www/html/HiveCommerce/ContentFuzzyfyr/", "options": {"symlink": true}}' 76 | bin/clinotty composer require hivecommerce/magento2-content-fuzzyfyr:* 77 | 78 | echo "Enabling Force Login module..." 79 | bin/clinotty bin/magento module:enable HiveCommerce_ContentFuzzyfyr 80 | bin/clinotty bin/magento setup:upgrade 81 | 82 | echo "Forcing deploy of static content to speed up initial requests..." 83 | bin/clinotty bin/magento setup:static-content:deploy -f 84 | 85 | echo "Re-indexing with Elasticsearch..." 86 | bin/clinotty bin/magento indexer:reindex 87 | 88 | echo "Setting basic URL and generating SSL certificate..." 89 | bin/setup-domain "${DOMAIN}" 90 | 91 | echo "Clearing the cache to apply updates..." 92 | bin/clinotty bin/magento cache:flush 93 | 94 | echo "Turning on developer mode.." 95 | bin/clinotty bin/magento deploy:mode:set developer 96 | 97 | echo "Docker development environment setup complete." 98 | echo "You may now access your Magento instance at https://${DOMAIN}/" 99 | -------------------------------------------------------------------------------- /bin/setup-composer-auth: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | MAGENTO_USERNAME_PROP="http-basic.repo.magento.com.username" 3 | MAGENTO_PASSWORD_PROP="http-basic.repo.magento.com.password" 4 | hash composer 2>/dev/null && IS_COMPOSER_ON_HOST=true 5 | 6 | if [ $IS_COMPOSER_ON_HOST ]; then 7 | PUBLIC_KEY="$(composer config --global $MAGENTO_USERNAME_PROP 2>/dev/null)" 8 | PRIVATE_KEY="$(composer config --global $MAGENTO_PASSWORD_PROP 2>/dev/null)" 9 | fi 10 | 11 | if [ -z "$PUBLIC_KEY" ] || [ -z "$PRIVATE_KEY" ]; then 12 | exec < /dev/tty 13 | echo 14 | echo "Composer authentication required (repo.magento.com public and private keys):" 15 | read -r -p " Username: " PUBLIC_KEY 16 | read -r -p " Password: " PRIVATE_KEY 17 | echo 18 | exec <&- 19 | fi 20 | 21 | if [ -z "$PUBLIC_KEY" ] || [ -z "$PRIVATE_KEY" ]; then 22 | echo "Please setup Composer auth for repo.magento.com to continue." && exit 1 23 | fi 24 | 25 | # Output must be piped otherwise file descriptor errors occur. Carriage returns? 26 | echo "composer config --global http-basic.repo.magento.com ${PUBLIC_KEY} ${PRIVATE_KEY}" | bin/clinotty bash - 27 | 28 | # Also make sure alternate auth.json is setup (Magento uses this internally) 29 | bin/clinotty [ -d "./var/composer_home" ] && cp /var/www/.composer/auth.json ./var/composer_home/auth.json 30 | 31 | echo "Composer auth has been setup." 32 | -------------------------------------------------------------------------------- /bin/setup-domain: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | 4 | [ -z "$1" ] && echo "Please specify a domain name (ex. magento.test)" && exit 5 | 6 | DOMAIN=$1 7 | 8 | echo "Set https://${DOMAIN}/ to web/secure/base_url and web/secure/base_url" 9 | bin/magento config:set web/secure/base_url https://"$DOMAIN"/ 10 | bin/magento config:set web/unsecure/base_url https://"$DOMAIN"/ 11 | 12 | echo "Generating SSL certificate..." 13 | bin/setup-ssl "$DOMAIN" 14 | -------------------------------------------------------------------------------- /bin/setup-grunt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DEFAULT_THEME_ID="select value from core_config_data where path = 'design/theme/theme_id'" 3 | THEME_PATH="select theme_path from theme where theme_id in ($DEFAULT_THEME_ID);" 4 | VENDOR_THEME=$(bin/n98-magerun2 db:query "$THEME_PATH" | sed -n 2p | cut -d$'\r' -f1) 5 | THEME=$(echo "$VENDOR_THEME" | cut -d'/' -f2) 6 | LOCALE_CODE=$(bin/magento config:show general/locale/code | cut -d$'\r' -f1 | sed 's/ *$//g') 7 | 8 | # Generate local-theme.js for custom theme 9 | read -r -d '' GEN_THEME_JS << EOM 10 | var fs = require('fs'); 11 | var util = require('util'); 12 | var theme = require('./dev/tools/grunt/configs/themes'); 13 | 14 | theme['$THEME'] = { 15 | area: 'frontend', 16 | name: '$VENDOR_THEME', 17 | locale: '$LOCALE_CODE', 18 | files: [ 19 | 'css/styles-m', 20 | 'css/styles-l' 21 | ], 22 | dsl: 'less' 23 | }; 24 | fs.writeFileSync('./dev/tools/grunt/configs/local-themes.js', '"use strict"; module.exports = ' + util.inspect(theme), 'utf-8'); 25 | EOM 26 | 27 | if [ -z "$VENDOR_THEME" ] || [ -z "$THEME" ]; then 28 | echo "Using Magento/luma theme for grunt config" 29 | THEME=luma 30 | bin/clinotty cp ./dev/tools/grunt/configs/themes.js ./dev/tools/grunt/configs/local-themes.js 31 | else 32 | echo "Using $VENDOR_THEME theme for grunt config" 33 | bin/node -e "$GEN_THEME_JS" 34 | fi 35 | 36 | bin/clinotty cp package.json.sample package.json 37 | bin/clinotty cp Gruntfile.js.sample Gruntfile.js 38 | bin/clinotty cp grunt-config.json.sample grunt-config.json 39 | bin/npm install ajv@^5.0.0 --save 40 | bin/npm install 41 | bin/magento cache:clean 42 | bin/grunt clean 43 | bin/grunt exec:$THEME 44 | bin/grunt less:$THEME 45 | -------------------------------------------------------------------------------- /bin/setup-integration-tests: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shellcheck source=../env/db.env 4 | source env/db.env 5 | 6 | MYSQL_INTEGRATION_CONFIG=dev/tests/integration/etc/install-config-mysql.php 7 | 8 | # If database doesn't exist, create it and add user permissions 9 | bin/clinotty mysql -h"${MYSQL_INTEGRATION_HOST}" -uroot -p"${MYSQL_ROOT_PASSWORD}" "${MYSQL_INTEGRATION_DATABASE}" -e exit &> /dev/null || 10 | bin/clinotty mysqladmin -h"${MYSQL_INTEGRATION_HOST}" -uroot -p"${MYSQL_ROOT_PASSWORD}" create "${MYSQL_INTEGRATION_DATABASE}" && 11 | echo "Database ${MYSQL_INTEGRATION_DATABASE} created." && 12 | bin/cli mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" -h"${MYSQL_INTEGRATION_HOST}" \ 13 | -e "GRANT ALL PRIVILEGES ON ${MYSQL_INTEGRATION_DATABASE}.* TO '${MYSQL_INTEGRATION_USER}'@'%';FLUSH PRIVILEGES;" 14 | 15 | if [[ ! -f "src/${MYSQL_INTEGRATION_CONFIG}" ]]; then 16 | MAGENTO_VERSION=$(bin/magento --version --no-ansi | cut -d" " -f 3) 17 | IFS=. read -r -a MAGENTO_VERSION_SEGMENTS <<< "${MAGENTO_VERSION}" 18 | MAGENTO_MAJOR="${MAGENTO_VERSION_SEGMENTS[0]}.${MAGENTO_VERSION_SEGMENTS[1]}" 19 | cp template/"${MYSQL_INTEGRATION_CONFIG}"."${MAGENTO_MAJOR}".dist src/${MYSQL_INTEGRATION_CONFIG} 20 | fi 21 | 22 | bin/copytocontainer ${MYSQL_INTEGRATION_CONFIG} 23 | -------------------------------------------------------------------------------- /bin/setup-pwa-studio: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | echo "Install NodeJS and Yarn on host machine, otherwise setup will fail" 4 | 5 | BASE_URL=${1:-master-7rqtwti-mfwmkrjfqvbjk.us-4.magentosite.cloud} 6 | git clone https://github.com/magento/pwa-studio.git 7 | cd pwa-studio 8 | yarn install 9 | yarn buildpack create-custom-origin packages/venia-concept 10 | MAGENTO_BACKEND_URL="https://$BASE_URL/" yarn buildpack create-env-file packages/venia-concept 11 | -------------------------------------------------------------------------------- /bin/setup-ssl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | [ -z "$1" ] && echo "Please specify a domain (ex. mydomain.test)" && exit 3 | 4 | # Generate certificate authority if not already setup 5 | if ! docker-compose exec -T -u root app cat /root/.local/share/mkcert/rootCA.pem | grep -q 'BEGIN CERTIFICATE'; then 6 | bin/setup-ssl-ca 7 | fi 8 | 9 | # Generate the certificate for the specified domain 10 | docker-compose exec -T -u root app mkcert -key-file nginx.key -cert-file nginx.crt "$@" 11 | echo "Moving key and cert to /etc/nginx/certs/..." 12 | docker-compose exec -T -u root app chown app:app nginx.key nginx.crt 13 | docker-compose exec -T -u root app mv nginx.key nginx.crt /etc/nginx/certs/ 14 | 15 | # Restart nginx to apply the updates 16 | echo "Restarting containers to apply updates..." 17 | bin/restart 18 | -------------------------------------------------------------------------------- /bin/setup-ssl-ca: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | # Generate a new local CA "/root/.local/share/mkcert" 4 | docker-compose exec -T -u root app mkcert -install 5 | 6 | docker cp "$(docker-compose ps -q app|awk '{print $1}')":/root/.local/share/mkcert/rootCA.pem . 7 | echo "System password requested to install certificate authority on host..." 8 | 9 | if [ "$(uname)" == "Darwin" ]; then 10 | sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.pem 11 | 12 | ### Check if Firefox is installed 13 | FFoxBin="/Applications/Firefox.app/Contents/MacOS/firefox-bin" 14 | if [ -f "$FFoxBin" ]; then 15 | sudo echo "{\"policies\": {\"Certificates\": {\"ImportEnterpriseRoots\": true}}}" > policies.json 16 | 17 | ### Check if distribution directory exists 18 | DistDirectory="/Applications/Firefox.app/Contents/Resources/distribution" 19 | if [ ! -d "$DistDirectory" ]; then 20 | sudo mkdir "$DistDirectory" 21 | fi 22 | ### Move the newly created policies.json to the Certificates directory 23 | sudo mv policies.json "$DistDirectory"/policies.json 24 | 25 | ### Check if Certificates directory exists 26 | CertDirectory="/Library/Application Support/Mozilla/Certificates" 27 | if [ ! -d "$CertDirectory" ]; then 28 | sudo mkdir "$CertDirectory" 29 | fi 30 | 31 | ### Move the newly created .pem to the Certificates directory 32 | sudo mv rootCA.pem "$CertDirectory"/rootCA.pem 33 | else 34 | sudo rm rootCA.pem 35 | fi 36 | 37 | else 38 | 39 | ### Requirement: apt install libnss3-tools 40 | REQUIRED_PKG="libnss3-tools" 41 | PKG_OK=$(dpkg-query -W --showformat='${Status}\n' $REQUIRED_PKG|grep "install ok installed") 42 | echo Checking for $REQUIRED_PKG: $PKG_OK 43 | if [ "" = "$PKG_OK" ]; then 44 | echo "No $REQUIRED_PKG found. Setting up $REQUIRED_PKG." 45 | sudo apt-get --yes install $REQUIRED_PKG 46 | fi 47 | 48 | ### CA file to install (CUSTOMIZE!) 49 | certfile="rootCA.pem" 50 | certname="Root CA" 51 | 52 | ### For cert8 (legacy - DBM) 53 | for certDB in $(find ~/ -name "cert8.db") 54 | do 55 | certdir=$(dirname ${certDB}); 56 | certutil -D -n "${certname}" -i ${certfile} -d dbm:${certdir} 57 | certutil -A -n "${certname}" -t "TCu,Cu,Tu" -i ${certfile} -d dbm:${certdir} 58 | done 59 | 60 | ### For cert9 (SQL) 61 | for certDB in $(find ~/ -name "cert9.db") 62 | do 63 | certdir=$(dirname ${certDB}); 64 | certutil -D -n "${certname}" -i ${certfile} -d sql:${certdir} 65 | certutil -A -n "${certname}" -t "TCu,Cu,Tu" -i ${certfile} -d sql:${certdir} 66 | done 67 | 68 | sudo mv rootCA.pem /usr/local/share/ca-certificates/rootCA.crt 69 | sudo update-ca-certificates 70 | fi 71 | -------------------------------------------------------------------------------- /bin/start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit 3 | 4 | # Ref: https://stackoverflow.com/a/51789677/9821321 5 | function parseYaml { 6 | local s 7 | local w 8 | local fs 9 | s='[[:space:]]*' 10 | w='[a-zA-Z0-9_]*' 11 | fs=$(echo @|tr @ '\034') 12 | sed -ne "s|,$s\]$s\$|]|" \ 13 | -e "s|^\($s\)\($w\)$s:$s\[$s\(.*\)$s\]|\1\2:\n\1 - \3|;p" "$1" | \ 14 | sed -ne "s|,$s}$s\$|}|" \ 15 | -e "s|^\($s\)-$s{$s\(.*\)$s}|\1-\n\1 \2|;p" | \ 16 | sed -ne "s|^\($s\):|\1|" \ 17 | -e "s|^\($s\)-$s{[\"']\(.*\)[\"']}$s\$|\1$fs$fs\2|p" \ 18 | -e "s|^\($s\)-$s\(.*\)$s\$|\1$fs$fs\2|p" \ 19 | -e "s|^\($s\)\($w\)$s:$s{[\"']\(.*\)[\"']}$s\$|\1$fs\2$fs\3|p" \ 20 | -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" | \ 21 | awk -F"$fs" '{ 22 | indent = length($1)/2; 23 | vname[indent] = $2; 24 | for (i in vname) {if (i > indent) {delete vname[i]; idx[i]=0}} 25 | if (length($2) == 0) {vname[indent] = ++idx[indent] }; 26 | if (length($3) > 0) { 27 | vn=""; for (i=0; i 2 | 12 | 14 | 15 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /etc/adminhtml/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 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 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 14 | 15 | 16 | 17 | 18 | HiveCommerce\ContentFuzzyfyr\Console\Command\FuzzyfyrCommand 19 | HiveCommerce\ContentFuzzyfyr\Console\Command\ExportCommand 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /i18n/de_DE.csv: -------------------------------------------------------------------------------- 1 | "GDPR conform Database Backup (Content Fuzzyfyr)","DSGVO-konformes Datenbank-Backup (Content Fuzzyfyr)" 2 | -------------------------------------------------------------------------------- /i18n/en_GB.csv: -------------------------------------------------------------------------------- 1 | "GDPR conform Database Backup (Content Fuzzyfyr)","GDPR conform Database Backup (Content Fuzzyfyr)" 2 | -------------------------------------------------------------------------------- /i18n/en_US.csv: -------------------------------------------------------------------------------- 1 | "GDPR conform Database Backup (Content Fuzzyfyr)","GDPR conform Database Backup (Content Fuzzyfyr)" 2 | -------------------------------------------------------------------------------- /infection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "vendor/infection/infection/resources/schema.json", 3 | "logs": { 4 | "text": "infection.log", 5 | "stryker": { 6 | "badge": "main" 7 | } 8 | }, 9 | "source": { 10 | "directories": [ 11 | "Api", 12 | "Block", 13 | "Console", 14 | "Handler", 15 | "Model", 16 | "Observer" 17 | ] 18 | }, 19 | "mutators": { 20 | "@default": true 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 7 3 | checkMissingIterableValueType: false 4 | magento: 5 | checkServiceContracts: false 6 | fileExtensions: 7 | - php 8 | paths: 9 | - Api 10 | - Block 11 | - Console 12 | - Handler 13 | - Model 14 | - Observer 15 | - Test 16 | ignoreErrors: 17 | - 18 | message: '~is never read, only written~' 19 | path: Handler/MediaFileHandler.php 20 | - 21 | message: '~Left side of && is always true~' 22 | path: Observer/FuzzyfyrObserver.php 23 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./ 16 | 17 | 18 | dist 19 | vendor 20 | Test 21 | registration.php 22 | validate_m2_package.php 23 | 24 | 25 | 26 | 27 | ./Test/Unit 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 |