Skip to content

Commit 391fb57

Browse files
authored
Added backup restoration support (#76)
1 parent 65e863b commit 391fb57

File tree

20 files changed

+566
-135
lines changed

20 files changed

+566
-135
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,10 @@ on:
1111
jobs:
1212
phpunit:
1313
name: PHPUnit (PHP ${{ matrix.php-version }})
14-
runs-on: ubuntu-20.04
14+
runs-on: ubuntu-22.04
1515
env:
1616
SYMFONY_DEPRECATIONS_HELPER: disabled
1717

18-
services:
19-
mysql:
20-
image: mysql:8.0
21-
env:
22-
MYSQL_ROOT_PASSWORD: root
23-
ports:
24-
- 3307:3306
25-
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
26-
2718
strategy:
2819
matrix:
2920
php-version:
@@ -45,6 +36,9 @@ jobs:
4536
- name: Install Composer dependencies
4637
uses: ramsey/composer-install@v1
4738

39+
- name: Start mariadb
40+
run: docker-compose -f docker-compose.test.yaml up -d mariadb
41+
4842
- name: Start minio
4943
run: docker-compose -f docker-compose.test.yaml up -d minio createbuckets
5044

@@ -69,5 +63,8 @@ jobs:
6963
- name: Stop minio
7064
run: docker-compose -f docker-compose.test.yaml stop minio
7165

66+
- name: Stop mariadb
67+
run: docker-compose -f docker-compose.test.yaml stop mariadb
68+
7269
- name: Upload to Codecov
7370
uses: codecov/codecov-action@v2

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ To access your databases backups, click the `Backups` tab.
126126

127127
![Backup list](docs/images/backup-list.png?raw=true)
128128

129-
You will be able to download or delete a backup.
129+
You will be able to download, restore or delete a backup.
130130

131131
## Update the application <a name="update-app"></a>
132132

composer.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/services.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,11 @@ services:
2929
- '../src/Kernel.php'
3030

3131
# add more service definitions when explicit configuration is needed
32-
# please note that last definitions always *replace* previous ones
32+
# please note that last definitions always *replace* previous ones
33+
34+
when@test:
35+
services:
36+
App\Tests\Fixtures\DataProvider:
37+
public: true
38+
autowire: true
39+
autoconfigure: true

docker-compose.test.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ services:
77
- '3307:3306'
88
environment:
99
MYSQL_ROOT_PASSWORD: root
10+
MYSQL_DATABASE: test_db
11+
volumes:
12+
- ./src/Faker/Provider/fixture.sql:/docker-entrypoint-initdb.d/fixture.sql
13+
- db_data:/var/lib/mysql
1014
minio:
1115
image: minio/minio
1216
environment:
@@ -30,3 +34,6 @@ services:
3034
/usr/bin/mc policy set public myminio/somebucketname;
3135
exit 0;
3236
"
37+
38+
volumes:
39+
db_data:
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20220902073138 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'Change database options';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$this->addSql('ALTER TABLE `database` CHANGE options_reset_auto_increment options_reset_auto_increment TINYINT(1) NOT NULL, CHANGE options_add_drop_database options_add_drop_database TINYINT(1) NOT NULL, CHANGE options_add_drop_table options_add_drop_table TINYINT(1) NOT NULL, CHANGE options_add_drop_trigger options_add_drop_trigger TINYINT(1) NOT NULL, CHANGE options_add_locks options_add_locks TINYINT(1) NOT NULL, CHANGE options_complete_insert options_complete_insert TINYINT(1) NOT NULL');
20+
}
21+
22+
public function down(Schema $schema): void
23+
{
24+
$this->addSql('ALTER TABLE `database` CHANGE options_reset_auto_increment options_reset_auto_increment TINYINT(1) DEFAULT 0 NOT NULL, CHANGE options_add_drop_database options_add_drop_database TINYINT(1) DEFAULT 0 NOT NULL, CHANGE options_add_drop_table options_add_drop_table TINYINT(1) DEFAULT 0 NOT NULL, CHANGE options_add_drop_trigger options_add_drop_trigger TINYINT(1) DEFAULT 1 NOT NULL, CHANGE options_add_locks options_add_locks TINYINT(1) DEFAULT 1 NOT NULL, CHANGE options_complete_insert options_complete_insert TINYINT(1) DEFAULT 0 NOT NULL');
25+
}
26+
27+
public function isTransactional(): bool
28+
{
29+
return false;
30+
}
31+
}

phpstan-baseline.neon

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ parameters:
1818
-
1919
message: "#^Call to an undefined method App\\\\Entity\\\\AdapterConfig\\:\\:setS3BucketName\\(\\)\\.$#"
2020
count: 2
21-
path: tests/Helper/FlysystemHelperTest.php
21+
path: tests/Fixtures/DataProvider.php
2222

2323
-
24-
message: "#^Method App\\\\Tests\\\\Helper\\\\FlysystemHelperTest\\:\\:getLocalS3Adapter\\(\\)\\ should return App\\\\Entity\\\\LocalAdapter but returns App\\\\Entity\\\\AdapterConfig.$#"
24+
message: "#^Method App\\\\Tests\\\\Fixtures\\\\DataProvider\\:\\:getLocalS3Adapter\\(\\)\\ should return App\\\\Entity\\\\LocalAdapter but returns App\\\\Entity\\\\AdapterConfig.$#"
2525
count: 1
26-
path: tests/Helper/FlysystemHelperTest.php
26+
path: tests/Fixtures/DataProvider.php

public/assets/js/confirm-modal.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
document.addEventListener("DOMContentLoaded",(
2+
function() {
3+
document.querySelectorAll(".confirm-action").forEach((function(e){
4+
e.addEventListener("click",(function(t){
5+
t.preventDefault();
6+
document.querySelector("#modal-confirm-button").addEventListener("click",(function(){
7+
location.replace(e.getAttribute("href"));
8+
}));
9+
}));
10+
}));
11+
}
12+
));

src/Controller/Admin/BackupCrudController.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
use App\Entity\Backup;
99
use App\Entity\User;
1010
use App\Helper\FlysystemHelper;
11+
use App\Service\BackupService;
1112
use Doctrine\ORM\EntityManagerInterface;
1213
use Doctrine\ORM\QueryBuilder;
1314
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
1415
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
1516
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
1617
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
18+
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
1719
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
1820
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
1921
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
@@ -28,7 +30,9 @@
2830
use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;
2931
use EasyCorp\Bundle\EasyAdminBundle\Filter\TextFilter;
3032
use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository;
33+
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
3134
use Symfony\Component\HttpFoundation\Response;
35+
use Symfony\Component\Translation\TranslatableMessage;
3236
use Symfony\Contracts\Translation\TranslatorInterface;
3337

3438
/**
@@ -39,6 +43,8 @@ final class BackupCrudController extends AbstractCrudController
3943
public function __construct(
4044
private readonly TranslatorInterface $translator,
4145
private readonly FlysystemHelper $flysystemHelper,
46+
private readonly BackupService $backupService,
47+
private readonly AdminUrlGenerator $adminUrlGenerator,
4248
) {
4349
}
4450

@@ -75,6 +81,25 @@ public function downloadBackupAction(AdminContext $context): Response
7581
return $this->flysystemHelper->download($backup);
7682
}
7783

84+
public function importBackupAction(AdminContext $context): Response
85+
{
86+
/** @var Backup $backup */
87+
$backup = $context->getEntity()->getInstance();
88+
89+
try {
90+
$this->backupService->import($backup);
91+
$this->addFlash('success', new TranslatableMessage('backup.action.import.flash_success'));
92+
} catch (\RuntimeException $e) {
93+
$this->addFlash('danger', new TranslatableMessage('backup.action.import.flash_error', ['%message%' => $e->getMessage()]));
94+
}
95+
96+
$url = $this->adminUrlGenerator->setController(self::class)
97+
->setAction(Action::INDEX)
98+
->generateUrl();
99+
100+
return $this->redirect($url);
101+
}
102+
78103
/**
79104
* @param Backup $entityInstance
80105
*/
@@ -89,8 +114,17 @@ public function configureActions(Actions $actions): Actions
89114
$downloadBackupAction = Action::new('downloadBackup', 'backup.action.download')
90115
->linkToCrudAction('downloadBackupAction');
91116

117+
$importBackupAction = Action::new('importBackup', 'backup.action.import.title')
118+
->linkToCrudAction('importBackupAction')
119+
->addCssClass('confirm-action')
120+
->setHtmlAttributes([
121+
'data-bs-toggle' => 'modal',
122+
'data-bs-target' => '#modal-confirm',
123+
]);
124+
92125
return $actions
93126
->add(Crud::PAGE_INDEX, $downloadBackupAction)
127+
->add(Crud::PAGE_INDEX, $importBackupAction)
94128
->remove(Crud::PAGE_INDEX, Action::NEW)
95129
->remove(Crud::PAGE_INDEX, Action::EDIT)
96130
->disable(Action::NEW, Action::EDIT)
@@ -106,6 +140,13 @@ public function configureCrud(Crud $crud): Crud
106140
;
107141
}
108142

143+
public function configureAssets(Assets $assets): Assets
144+
{
145+
$assets->addJsFile('assets/js/confirm-modal.js');
146+
147+
return parent::configureAssets($assets);
148+
}
149+
109150
public function configureFields(string $pageName): iterable
110151
{
111152
yield DateTimeField::new('createdAt', 'backup.field.created_at')

src/Factory/DatabaseFactory.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use App\Entity\Database;
88
use App\Entity\Embed\BackupTask;
9+
use App\Entity\Embed\Options;
910
use App\Entity\Enum\BackupTaskPeriodicity;
1011
use App\Entity\User;
1112
use App\Repository\DatabaseRepository;
@@ -81,6 +82,10 @@ protected function getDefaults(): array
8182
'startFrom' => new \DateTime('-1 day'),
8283
'nextIteration' => new \DateTime('-1 day'),
8384
]),
85+
'options' => AnonymousFactory::new(Options::class)->create([
86+
'addDropTable' => true,
87+
'addDropDatabase' => true,
88+
]),
8489
];
8590
}
8691

0 commit comments

Comments
 (0)