Skip to content
This repository was archived by the owner on Nov 6, 2021. It is now read-only.

Commit aeffe4e

Browse files
author
Florian Horn
committed
Added feature to export database with fuzzyfied content without altering current database content persistently.
1 parent 5ef3880 commit aeffe4e

File tree

7 files changed

+460
-32
lines changed

7 files changed

+460
-32
lines changed

Console/Command/ExportCommand.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ class ExportCommand extends Command
3030
* Codes
3131
*/
3232
const SUCCESS = 0;
33-
const ERROR_BACKUP_PATH_NOT_RESOLVABLE = 127;
34-
const ERROR_EXPORT_FAILED = 156;
33+
const ERROR_EXPORT_FAILED = 127;
34+
const EVENT_NAME = 'aid_content_export_event';
3535

3636
/**
3737
* Flags
@@ -60,7 +60,7 @@ class ExportCommand extends Command
6060
const DEFAULT_DUMMY_CONTENT_EMAIL = 'lorem.ipsum.%1$s@test.localhost';
6161
const DEFAULT_DUMMY_CONTENT_URL = 'https://lor.emips.um/foo/bar/';
6262
const DEFAULT_DUMMY_CONTENT_PHONE = '+49 (0) 600 987 654 32';
63-
const DEFAULT_DUMP_OUTPUT = './var/backup/';
63+
const DEFAULT_DUMP_OUTPUT = './var/backups/';
6464

6565
/**
6666
* @var State
@@ -212,11 +212,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
212212
$this->backupHandler->beginTransaction();
213213

214214
try {
215-
$this->eventManager->dispatch('aid_content_export_event', [
215+
$this->eventManager->dispatch(self::EVENT_NAME, [
216216
'configuration' => $configuration
217217
]);
218218

219219
$this->backupHandler->run(
220+
$output,
220221
$input->getOption(self::OPTION_DUMP_OUTPUT)
221222
);
222223
} catch (\Exception $e) {

Console/Command/FuzzyfyrCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class FuzzyfyrCommand extends Command
3030
*/
3131
const SUCCESS = 0;
3232
const ERROR_PRODUCTION_MODE = 127;
33+
const EVENT_NAME = 'aid_content_fuzzyfyr_event';
3334

3435
/**
3536
* Flags
@@ -197,7 +198,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
197198
/*
198199
* Processing
199200
*/
200-
$this->eventManager->dispatch('aid_content_fuzzyfyr_event', ['configuration' => $configuration]);
201+
$this->eventManager->dispatch(self::EVENT_NAME, ['configuration' => $configuration]);
201202

202203
$output->writeln('Finished content fuzzyfy');
203204

Handler/BackupHandler.php

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
namespace AllInData\ContentFuzzyfyr\Handler;
1212

13-
use Magento\Framework\App\DeploymentConfig;
1413
use Magento\Framework\App\MaintenanceMode;
1514
use Magento\Framework\Setup\BackupRollbackFactory;
1615
use Magento\Framework\Setup\ModuleDataSetupInterface;
1716
use Magento\Framework\Filesystem\Io\File;
17+
use Symfony\Component\Console\Output\OutputInterface;
1818

1919
/**
2020
* Class BackupHandler
@@ -35,10 +35,6 @@ class BackupHandler
3535
* @var BackupRollbackFactory
3636
*/
3737
private $backupRollbackFactory;
38-
/**
39-
* @var DeploymentConfig
40-
*/
41-
private $deploymentConfig;
4238
/**
4339
* @var bool
4440
*/
@@ -56,30 +52,27 @@ class BackupHandler
5652
* BackupHandler constructor.
5753
* @param MaintenanceMode $maintenanceMode
5854
* @param BackupRollbackFactory $backupRollbackFactory
59-
* @param DeploymentConfig $deploymentConfig
6055
* @param ModuleDataSetupInterface $setup
6156
* @param File $ioFile
6257
*/
6358
public function __construct(
6459
MaintenanceMode $maintenanceMode,
6560
BackupRollbackFactory $backupRollbackFactory,
66-
DeploymentConfig $deploymentConfig,
6761
ModuleDataSetupInterface $setup,
6862
File $ioFile
6963
) {
7064
$this->maintenanceMode = $maintenanceMode;
7165
$this->backupRollbackFactory = $backupRollbackFactory;
72-
$this->deploymentConfig = $deploymentConfig;
7366
$this->setup = $setup;
7467
$this->ioFile = $ioFile;
75-
$this->maintenanceModeInitialState = $this->maintenanceMode->isOn();
7668
}
7769

7870
/**
7971
* Begin database transaction
8072
*/
8173
public function beginTransaction()
8274
{
75+
$this->maintenanceModeInitialState = $this->maintenanceMode->isOn();
8376
$this->maintenanceMode->set(true);
8477
$this->setup->getConnection()->beginTransaction();
8578
}
@@ -90,28 +83,25 @@ public function beginTransaction()
9083
public function endTransaction()
9184
{
9285
$this->setup->getConnection()->rollBack();
93-
$this->maintenanceMode->set(false);
86+
// disable maintenance only, if it has been disabled in the beginning
87+
if (!$this->maintenanceModeInitialState) {
88+
$this->maintenanceMode->set(false);
89+
90+
}
9491
}
9592

9693
/**
94+
* @param OutputInterface $output
9795
* @param string $backupPath
96+
* @throws \Exception
9897
*/
99-
public function run($backupPath)
98+
public function run(OutputInterface $output, $backupPath)
10099
{
101100
/*
102101
* Backup path
103102
*/
104103
$backupPath = realpath($backupPath);
105-
if (!$backupPath) {
106-
throw new \InvalidArgumentException(
107-
sprintf(
108-
'Could not resolve backup path: "%s"',
109-
$backupPath
110-
)
111-
);
112-
}
113-
114-
if (!$this->ioFile->mkdir($backupPath, self::BACKUP_DIRECTORY_FILEMODE, true)) {
104+
if (!$this->ioFile->checkAndCreateFolder($backupPath, self::BACKUP_DIRECTORY_FILEMODE)) {
115105
throw new \RuntimeException(
116106
sprintf(
117107
'Could not create backup folder: "%s"',
@@ -123,12 +113,13 @@ public function run($backupPath)
123113
/*
124114
* Backup Handler
125115
*/
126-
$backupHandler = $this->backupRollbackFactory->create();
116+
$backupHandler = $this->backupRollbackFactory->create($output);
127117
$backupFile = $backupHandler->dbBackup(time());
128118

129119
$backupPath .= DIRECTORY_SEPARATOR . basename($backupFile);
130120
$backupPath = str_replace(DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, $backupPath);
131-
if (!$this->ioFile->cp($backupFile, $backupPath)) {
121+
if ($backupFile !== $backupPath &&
122+
!$this->ioFile->cp($backupFile, $backupPath)) {
132123
throw new \RuntimeException(
133124
sprintf(
134125
'Failed to copy backup file "%s" to target "%s"',

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ switched with some defined default value:
100100
bin/magento aid:content:export [options]
101101

102102
**Note:** Running the code activates maintenance mode. The maintenance mode will be disabled, if the command has run
103-
successfully or erroneous, but it is recommended to check manually on production system.
103+
successfully or erroneous and the maintenance mode has been disabled in the beginning. But it is recommended to check
104+
manually on production system after running the command.
104105

105106
#### List of flags
106107

@@ -122,7 +123,7 @@ Option | Value | Description
122123
--dummy-content-email | String | Used as dummy email content. Defaults to 'lorem.ipsum.%1$s@test.localhost'
123124
--dummy-content-url | String | Used as dummy url content. Defaults to 'https://lor.emips.um/foo/bar/'
124125
--dummy-content-phone | String | Used as dummy phone content. Defaults to '+49 (0) 600 987 654 32'
125-
--backup-output | String | Path where the database dump is placed. Defaults to './var/backup/'
126+
--backup-output | String | Path where the database dump is placed. Defaults to './var/backups/'
126127

127128
#### How to apply custom code
128129

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
<?php
2+
/**
3+
* This file is part of the Content Fuzzyfyr module for Magento2.
4+
*
5+
* (c) All.In Data GmbH
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace AllInData\ContentFuzzyfyr\Test\Unit\Console\Command;
12+
13+
use AllInData\ContentFuzzyfyr\Handler\BackupHandler;
14+
use AllInData\ContentFuzzyfyr\Model\Configuration;
15+
use AllInData\ContentFuzzyfyr\Test\Unit\AbstractTest;
16+
use Magento\Framework\App\State;
17+
use Magento\Framework\EntityManager\EventManager;
18+
use AllInData\ContentFuzzyfyr\Model\ConfigurationFactory;
19+
use AllInData\ContentFuzzyfyr\Console\Command\ExportCommand;
20+
use PHPUnit\Framework\MockObject\MockObject;
21+
use Symfony\Component\Console\Input\InputInterface;
22+
use Symfony\Component\Console\Output\OutputInterface;
23+
24+
/**
25+
* Class ExportCommandTest
26+
* @package AllInData\ContentFuzzyfyr\Test\Unit\Console\Command
27+
*/
28+
class ExportCommandTest extends AbstractTest
29+
{
30+
/**
31+
* @test
32+
*/
33+
public function runSuccessfully()
34+
{
35+
$state = $this->getState();
36+
37+
$input = $this->getInput();
38+
$input->expects($this->at(15))
39+
->method('getOption')
40+
->with(ExportCommand::OPTION_DUMP_OUTPUT)
41+
->willReturn(ExportCommand::DEFAULT_DUMP_OUTPUT);
42+
$output = $this->getOutput();
43+
44+
$configuration = $this->getMockBuilder(Configuration::class)->getMock();
45+
$configurationFactory = $this->getConfigurationFactory();
46+
$configurationFactory->expects($this->once())
47+
->method('create')
48+
->willReturn($configuration);
49+
50+
$eventManager = $this->getEventManager();
51+
$eventManager->expects($this->once())
52+
->method('dispatch')
53+
->with(ExportCommand::EVENT_NAME, [
54+
'configuration' => $configuration
55+
]);
56+
57+
$backupHandler = $this->getBackupHandler();
58+
$backupHandler->expects($this->once())
59+
->method('beginTransaction');
60+
$backupHandler->expects($this->once())
61+
->method('endTransaction');
62+
$backupHandler->expects($this->once())
63+
->method('run')
64+
->with($output, ExportCommand::DEFAULT_DUMP_OUTPUT);
65+
66+
$command = new ExportCommand(
67+
$state,
68+
$eventManager,
69+
$configurationFactory,
70+
$backupHandler
71+
);
72+
73+
$this->assertEquals(ExportCommand::SUCCESS, $command->run($input, $output));
74+
}
75+
76+
/**
77+
* @test
78+
*/
79+
public function runFailesRunningBackup()
80+
{
81+
$state = $this->getState();
82+
83+
$input = $this->getInput();
84+
$input->expects($this->at(15))
85+
->method('getOption')
86+
->with(ExportCommand::OPTION_DUMP_OUTPUT)
87+
->willReturn(ExportCommand::DEFAULT_DUMP_OUTPUT);
88+
$output = $this->getOutput();
89+
90+
$configuration = $this->getMockBuilder(Configuration::class)->getMock();
91+
$configurationFactory = $this->getConfigurationFactory();
92+
$configurationFactory->expects($this->once())
93+
->method('create')
94+
->willReturn($configuration);
95+
96+
$eventManager = $this->getEventManager();
97+
$eventManager->expects($this->once())
98+
->method('dispatch')
99+
->with(ExportCommand::EVENT_NAME, [
100+
'configuration' => $configuration
101+
]);
102+
103+
$backupHandler = $this->getBackupHandler();
104+
$backupHandler->expects($this->once())
105+
->method('beginTransaction');
106+
$backupHandler->expects($this->once())
107+
->method('endTransaction');
108+
$backupHandler->expects($this->once())
109+
->method('run')
110+
->with($output, ExportCommand::DEFAULT_DUMP_OUTPUT)
111+
->willThrowException(new \Exception());
112+
113+
$command = new ExportCommand(
114+
$state,
115+
$eventManager,
116+
$configurationFactory,
117+
$backupHandler
118+
);
119+
120+
$this->assertEquals(ExportCommand::ERROR_EXPORT_FAILED, $command->run($input, $output));
121+
}
122+
123+
/**
124+
* @return MockObject|State
125+
*/
126+
private function getState()
127+
{
128+
return $this->getMockBuilder(State::class)
129+
->disableOriginalConstructor()
130+
->getMock();
131+
}
132+
133+
/**
134+
* @return MockObject|EventManager
135+
*/
136+
private function getEventManager()
137+
{
138+
return $this->getMockBuilder(EventManager::class)
139+
->disableOriginalConstructor()
140+
->getMock();
141+
}
142+
143+
/**
144+
* @return MockObject|ConfigurationFactory
145+
*/
146+
private function getConfigurationFactory()
147+
{
148+
return $this->getMockBuilder(ConfigurationFactory::class)
149+
->disableOriginalConstructor()
150+
->getMock();
151+
}
152+
153+
/**
154+
* @return MockObject|BackupHandler
155+
*/
156+
private function getBackupHandler()
157+
{
158+
return $this->getMockBuilder(BackupHandler::class)
159+
->disableOriginalConstructor()
160+
->getMock();
161+
}
162+
163+
/**
164+
* @return MockObject|InputInterface
165+
*/
166+
private function getInput()
167+
{
168+
return $this->getMockBuilder(InputInterface::class)
169+
->disableOriginalConstructor()
170+
->getMock();
171+
}
172+
173+
/**
174+
* @return MockObject|OutputInterface
175+
*/
176+
private function getOutput()
177+
{
178+
return $this->getMockBuilder(OutputInterface::class)
179+
->disableOriginalConstructor()
180+
->getMock();
181+
}
182+
}

0 commit comments

Comments
 (0)