Skip to content

Commit a48b5a7

Browse files
Merge pull request #30 from itiden/feature/improve-commands
Feature/improve commands
2 parents 3e3ffa8 + 4532607 commit a48b5a7

File tree

10 files changed

+122
-29
lines changed

10 files changed

+122
-29
lines changed

docs/pages/.vitepress/config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ export default defineConfig({
1212
sidebar: [
1313
{
1414
text: "Introduction",
15-
items: [{ text: "Getting started", link: "/getting-started.md" }],
15+
items: [
16+
{ text: "Getting started", link: "/getting-started.md" },
17+
{ text: "Commands", link: "/commands.md" },
18+
],
1619
},
1720
{
1821
text: "Configuration",
@@ -26,6 +29,7 @@ export default defineConfig({
2629
items: [
2730
{ text: "Pipeline", link: "/pipeline.md" },
2831
{ text: "Notifications", link: "/notifications.md" },
32+
{ text: "Metadata", link: "/metadata.md" },
2933
],
3034
},
3135
],

docs/pages/commands.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Commands
2+
3+
Statamic backup comes with a few commands to help you manage backups from a cli.
4+
5+
| Command | Description |
6+
| ---------------------------------------- | ------------------------------------------------------------ |
7+
| `php artisan statamic:backup` | Run the backup process |
8+
| `php artisan statamic:backup:temp-clean` | Clean up leftover temporary backup files, like upload chunks |
9+
| `php artisan statamic:backup:restore` | Restore your site to chosen backup |

phpunit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<php>
1919
<env name="APP_ENV" value="testing"/>
2020
<env name="DB_CONNECTION" value="testing"/>
21+
<env name="APP_ENV" value="testing"/>
2122
<env name="APP_KEY" value="base64:2fl+Ktvkfl+Fuz4Qp/A75G2RTiWVA/ZoKZvp6fiiM10="/>
2223
</php>
2324
</phpunit>

src/Console/Commands/BackupCommand.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@
77
use Illuminate\Console\Command;
88
use Itiden\Backup\Facades\Backuper;
99

10+
use function Laravel\Prompts\{info, spin};
11+
1012
/**
1113
* Backup site
1214
*/
1315
class BackupCommand extends Command
1416
{
1517
protected $signature = 'statamic:backup';
1618

17-
protected $description = 'Backup your stuff';
19+
protected $description = 'Run the backup pipeline';
1820

1921
public function handle()
2022
{
21-
$this->components->info('Backing up content');
22-
23-
$backup_location = Backuper::backup();
23+
$backup = spin(fn () => Backuper::backup(), 'Backing up...');
2424

25-
$this->components->info('Backup saved to ' . $backup_location->path);
25+
info('Backup saved to ' . $backup->path);
2626
}
2727
}

src/Console/Commands/ClearFilesCommand.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,27 @@
77
use Illuminate\Console\Command;
88
use Illuminate\Support\Facades\File;
99

10+
use function Laravel\Prompts\info;
11+
1012
/**
1113
* Clear the backup temp directory
1214
*/
1315
class ClearFilesCommand extends Command
1416
{
15-
protected $signature = 'statamic:backup:clear';
17+
protected $signature = 'statamic:backup:temp-clear';
1618

17-
protected $description = 'Empty the temp directory';
19+
protected $description = 'Clear the backup temp directory';
1820

1921
public function handle()
2022
{
21-
if (! File::exists(config('backup.temp_path'))) {
22-
$this->components->info('Backup temp directory does not exist, no need to clear it.');
23+
if (!File::exists(config('backup.temp_path'))) {
24+
info('Backup temp directory does not exist, no need to clear it.');
2325

2426
return;
2527
}
2628

2729
File::cleanDirectory(config('backup.temp_path'));
2830

29-
$this->components->info('Backup temp directory cleared successfully');
31+
info('Backup temp directory cleared successfully');
3032
}
3133
}

src/Console/Commands/RestoreCommand.php

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,47 @@
55
namespace Itiden\Backup\Console\Commands;
66

77
use Illuminate\Console\Command;
8-
use Illuminate\Contracts\Console\PromptsForMissingInput;
8+
use Itiden\Backup\Contracts\Repositories\BackupRepository;
99
use Itiden\Backup\DataTransferObjects\BackupDto;
1010
use Itiden\Backup\Facades\Restorer;
1111

12+
use function Laravel\Prompts\{confirm, spin, info, select};
13+
1214
/**
1315
* Restore content from a directory / backup
1416
*/
15-
class RestoreCommand extends Command implements PromptsForMissingInput
17+
final class RestoreCommand extends Command
1618
{
17-
protected $signature = 'statamic:backup:restore {path} {--force}';
19+
protected $signature = 'statamic:backup:restore {--path=} {--force}';
1820

1921
protected $description = 'Reset or restore content from a directory / backup';
2022

21-
protected function promptForMissingArgumentsUsing()
23+
public function handle(BackupRepository $repo)
2224
{
23-
return [
24-
'path' => 'Which filepath does your backup have?',
25-
];
26-
}
25+
/* @var BackupDto $backup */
26+
$backup = match (true) {
27+
(bool) $this->option('path') => BackupDto::fromAbsolutePath($this->option('path')),
28+
default => BackupDto::fromFile(select(
29+
label: 'Which backup do you want to restore to?',
30+
scroll: 10,
31+
options: $repo->all()->flatMap(
32+
fn (BackupDto $backup) => [$backup->path => $backup->path]
33+
),
34+
required: true
35+
)),
36+
};
2737

28-
public function handle()
29-
{
30-
if ($this->option('force') || $this->confirm('Are you sure you want to restore your content?')) {
31-
Restorer::restore(BackupDto::fromAbsolutePath($this->argument('path')));
38+
if (
39+
$this->option('force')
40+
|| confirm(
41+
label: "Are you sure you want to restore your content?",
42+
hint: "This will overwrite your current content with state from {$backup->created_at->format('Y-m-d H:i:s')}",
43+
required: true
44+
)
45+
) {
46+
spin(fn () => Restorer::restore($backup), 'Restoring backup');
47+
48+
info('Backup restored!');
3249
}
3350
}
3451
}

tests/Feature/ClearTempTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
File::deleteDirectory($temp_path);
1111

12-
$this->artisan('statamic:backup:clear')->assertExitCode(0);
12+
$this->artisan('statamic:backup:temp-clear')->assertExitCode(0);
1313
});
1414

1515
it("will clear temp path when running backup clear command", function () {
@@ -21,7 +21,7 @@
2121

2222
expect(File::allFiles($temp_path))->toHaveCount(1);
2323

24-
$this->artisan('statamic:backup:clear');
24+
$this->artisan('statamic:backup:temp-clear');
2525

2626
expect(File::allFiles($temp_path))->toHaveCount(0);
2727
});

tests/Feature/RestoreBackupTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,19 +75,19 @@
7575

7676
File::cleanDirectory(config('backup.content_path'));
7777

78-
$this->artisan('statamic:backup:restore', ['path' => Storage::path($backup->path)])
78+
$this->artisan('statamic:backup:restore', ['--path' => Storage::path($backup->path)])
7979
->expectsConfirmation('Are you sure you want to restore your content?', 'no');
8080

8181
expect(File::isEmptyDirectory(config('backup.content_path')))->toBeTrue();
8282

83-
$this->artisan('statamic:backup:restore', ['path' => Storage::path($backup->path), '--force' => true])
83+
$this->artisan('statamic:backup:restore', ['--path' => Storage::path($backup->path), '--force' => true])
8484
->assertExitCode(0);
8585
});
8686

8787
it('can restore from path command', function () {
8888
$backup = Backuper::backup();
8989

90-
$this->artisan('statamic:backup:restore', ['path' => Storage::path($backup->path), '--force' => true])
90+
$this->artisan('statamic:backup:restore', ['--path' => Storage::path($backup->path), '--force' => true])
9191
->assertExitCode(0);
9292

9393
expect(File::isEmptyDirectory(config('backup.content_path')))->toBeFalse();
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Storage;
4+
use Itiden\Backup\Contracts\Repositories\BackupRepository;
5+
use Itiden\Backup\Facades\Backuper;
6+
7+
use function Pest\Laravel\artisan;
8+
9+
uses()->group('restore-command');
10+
11+
it('shows all available backups', function () {
12+
app(BackupRepository::class)->empty();
13+
14+
Backuper::backup();
15+
16+
$backups = app(BackupRepository::class)->all();
17+
18+
artisan('statamic:backup:restore')
19+
->expectsQuestion(
20+
question: 'Which backup do you want to restore to?',
21+
answer: $backups->first()->path
22+
)
23+
->expectsConfirmation('Are you sure you want to restore your content?')
24+
->assertFailed();
25+
});
26+
27+
it('can restore from a specific path', function () {
28+
app(BackupRepository::class)->empty();
29+
30+
$backup = Backuper::backup();
31+
32+
artisan('statamic:backup:restore', ['--path' => Storage::disk(config('backup.destination.disk'))->path($backup->path)])
33+
->expectsConfirmation('Are you sure you want to restore your content?')
34+
->assertFailed();
35+
});

tests/Unit/PipeTest.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
Assets::class,
4444
]);
4545

46-
test('can skip a pipe', function () {
46+
test('can skip a pipe with users', function () {
4747
/** @var Users::class $pipe */
4848
$pipe = app()->make(Users::class);
4949

@@ -63,3 +63,28 @@
6363

6464
$zipper->close();
6565
});
66+
67+
test('can skip a pipe with content', function () {
68+
/** @var Users::class $pipe */
69+
$pipe = app()->make(Content::class);
70+
71+
$callable = function ($z) {
72+
return $z;
73+
};
74+
75+
File::copyDirectory(config('backup.content_path'), config('backup.content_path') . '_backup');
76+
File::deleteDirectory(config('backup.content_path'));
77+
78+
$zipper = Zipper::open(config('backup.temp_path') . '/backup.zip');
79+
80+
$pipe->backup(zip: $zipper, next: $callable);
81+
82+
83+
expect($zipper->getMeta())->toHaveKey(Content::class);
84+
expect($zipper->getMeta()[Content::class])->toHaveKey('skipped', 'Content directory didn\'t exist, is it configured correctly?');
85+
86+
$zipper->close();
87+
88+
File::copyDirectory(config('backup.content_path') . '_backup', config('backup.content_path'));
89+
File::deleteDirectory(config('backup.content_path') . '_backup');
90+
});

0 commit comments

Comments
 (0)