Skip to content

Commit 326e7d0

Browse files
Add backup name resolver
1 parent 5f2d67c commit 326e7d0

File tree

8 files changed

+123
-49
lines changed

8 files changed

+123
-49
lines changed

config/backup.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@
4848
// 'time' => '03:00',
4949
],
5050

51+
/**
52+
* The backup name resolver
53+
*
54+
* the resolver handles generating and parsing backup names
55+
*/
56+
'name_resolver' => \Itiden\Backup\GenericBackupNameResolver::class,
57+
5158
/**
5259
* The backup repository
5360
*
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Itiden\Backup\Contracts;
6+
7+
use Carbon\CarbonImmutable;
8+
use Itiden\Backup\DataTransferObjects\ResolvedBackupData;
9+
10+
interface BackupNameResolver
11+
{
12+
/**
13+
* Generate a filename for a backup - should include an identifier and a timestamp
14+
* the .zip extension will be appended automatically
15+
*/
16+
public function generateFilename(CarbonImmutable $createdAt, string $id): string;
17+
18+
/**
19+
* Parse a filename and return the resolved data
20+
*/
21+
public function parseFilename(string $path): ResolvedBackupData;
22+
}

src/DataTransferObjects/BackupDto.php

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Carbon\CarbonImmutable;
88
use Illuminate\Support\Facades\File;
99
use Illuminate\Support\Facades\Storage;
10+
use Itiden\Backup\Contracts\BackupNameResolver;
1011
use Itiden\Backup\Models\Metadata;
1112
use Statamic\Support\Str as StatamicStr;
1213

@@ -18,7 +19,8 @@ public function __construct(
1819
public CarbonImmutable $created_at,
1920
public string $size,
2021
public string $path,
21-
) {}
22+
) {
23+
}
2224

2325
public function getMetadata(): Metadata
2426
{
@@ -30,14 +32,14 @@ public function getMetadata(): Metadata
3032
*/
3133
public static function fromFile(string $path): static
3234
{
33-
[$createtAt, $id, $name] = static::extractValuesFromPath($path);
35+
$values = app(BackupNameResolver::class)->parseFilename($path);
3436

3537
$bytes = Storage::disk(config('backup.destination.disk'))->size($path);
3638

3739
return new static(
38-
id: $id,
39-
name: $name,
40-
created_at: $createtAt,
40+
id: $values->id,
41+
name: $values->name,
42+
created_at: $values->createdAt,
4143
size: StatamicStr::fileSizeForHumans($bytes, 2),
4244
path: $path,
4345
);
@@ -48,33 +50,16 @@ public static function fromFile(string $path): static
4850
*/
4951
public static function fromAbsolutePath(string $path): static
5052
{
51-
[$createdAt, $id, $name] = static::extractValuesFromPath($path);
53+
$values = app(BackupNameResolver::class)->parseFilename($path);
5254

5355
$bytes = File::size($path);
5456

5557
return new static(
56-
id: $id,
57-
name: $name,
58-
created_at: $createdAt,
58+
id: $values->id,
59+
name: $values->name,
60+
created_at: $values->createdAt,
5961
size: StatamicStr::fileSizeForHumans($bytes, 2),
6062
path: $path,
6163
);
6264
}
63-
64-
private static function extractValuesFromPath(string $path): array
65-
{
66-
$timestamp = CarbonImmutable::createFromTimestamp(str(basename($path))
67-
->beforeLast('-')
68-
->afterLast('-')
69-
->toString());
70-
71-
$id = str(basename($path))
72-
->afterLast('-')
73-
->before('.zip')
74-
->toString();
75-
76-
$name = File::name($path);
77-
78-
return [$timestamp, $id, $name];
79-
}
8065
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Itiden\Backup\DataTransferObjects;
6+
7+
use Carbon\CarbonImmutable;
8+
9+
final readonly class ResolvedBackupData
10+
{
11+
public function __construct(
12+
public CarbonImmutable $createdAt,
13+
public string $id,
14+
public string $name,
15+
) {
16+
}
17+
}

src/GenericBackupNameResolver.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Itiden\Backup;
6+
7+
use Carbon\CarbonImmutable;
8+
use Itiden\Backup\Contracts\BackupNameResolver;
9+
use Itiden\Backup\DataTransferObjects\ResolvedBackupData;
10+
11+
final readonly class GenericBackupNameResolver implements BackupNameResolver
12+
{
13+
public function generateFilename(CarbonImmutable $createdAt, string $id): string
14+
{
15+
return implode('', [
16+
str(config('app.name'))->slug(),
17+
'-',
18+
$createdAt->timestamp,
19+
'-',
20+
$id,
21+
]);
22+
}
23+
24+
public function parseFilename(string $path): ResolvedBackupData
25+
{
26+
/** @var string */
27+
$filename = pathinfo($path, PATHINFO_FILENAME);
28+
29+
$createdAt = CarbonImmutable::createFromTimestamp((string) str($filename)
30+
->beforeLast('-')
31+
->afterLast('-'));
32+
33+
$id = (string) str($filename)
34+
->afterLast('-')
35+
->before('.zip');
36+
37+
$name = (string) str($filename)
38+
->remove('-' . $createdAt->timestamp)
39+
->before('.zip');
40+
41+
return new ResolvedBackupData(createdAt: $createdAt, id: $id, name: $name);
42+
}
43+
}

src/Repositories/FileBackupRepository.php

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44

55
namespace Itiden\Backup\Repositories;
66

7-
use Carbon\Carbon;
7+
use Carbon\CarbonImmutable;
88
use Illuminate\Contracts\Filesystem\Filesystem;
99
use Illuminate\Filesystem\FilesystemAdapter;
1010
use Illuminate\Http\File as StreamableFile;
1111
use Illuminate\Support\Collection;
1212
use Illuminate\Support\Facades\Storage;
1313
use Illuminate\Support\Str;
14+
use Itiden\Backup\Contracts\BackupNameResolver;
1415
use Itiden\Backup\Contracts\Repositories\BackupRepository;
1516
use Itiden\Backup\DataTransferObjects\BackupDto;
1617
use Itiden\Backup\Events\BackupDeleted;
@@ -22,42 +23,30 @@ final class FileBackupRepository implements BackupRepository
2223
/** @var FilesystemAdapter */
2324
private Filesystem $filesystem;
2425

25-
public function __construct()
26-
{
26+
public function __construct(
27+
private BackupNameResolver $nameResolver,
28+
) {
2729
$this->path = config('backup.destination.path');
2830
$this->filesystem = Storage::disk(config('backup.destination.disk'));
2931
}
3032

31-
private function makeFilename(string $timestamp, string $id): string
32-
{
33-
return implode('', [
34-
Str::slug(config('app.name')),
35-
'-',
36-
$timestamp,
37-
'-',
38-
$id,
39-
'.zip',
40-
]);
41-
}
42-
4333
public function all(): Collection
4434
{
45-
return collect($this->filesystem->files($this->path))
35+
return collect($this->filesystem->allFiles($this->path))
4636
->map(BackupDto::fromFile(...))
47-
->sortByDesc('created_at');
37+
->sortByDesc(fn(BackupDto $backup) => $backup->created_at);
4838
}
4939

5040
public function add(string $path): BackupDto
5141
{
5242
$this->filesystem->makeDirectory(path: $this->path);
5343

54-
$timestamp = (string) Carbon::now()->unix();
5544
$id = (string) Str::ulid();
5645

5746
$this->filesystem->putFileAs(
5847
path: $this->path,
5948
file: new StreamableFile($path),
60-
name: $this->makeFilename($timestamp, $id),
49+
name: (string) str($this->nameResolver->generateFilename(CarbonImmutable::now(), $id))->finish('.zip'),
6150
);
6251

6352
return $this->find($id);

src/ServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Itiden\Backup\Console\Commands\BackupCommand;
99
use Itiden\Backup\Console\Commands\ClearFilesCommand;
1010
use Itiden\Backup\Console\Commands\RestoreCommand;
11+
use Itiden\Backup\Contracts\BackupNameResolver;
1112
use Itiden\Backup\Contracts\Repositories\BackupRepository;
1213
use Itiden\Backup\Events\BackupDeleted;
1314
use Statamic\Auth\Permissions as PermissionContract;
@@ -69,6 +70,7 @@ public function register(): void
6970
$this->mergeConfigFrom(__DIR__ . '/../config/backup.php', 'backup');
7071

7172
$this->app->bind(BackupRepository::class, config('backup.repository'));
73+
$this->app->bind(BackupNameResolver::class, config('backup.name_resolver'));
7274
}
7375

7476
private function configureCommands(): void

tests/Unit/BackuperTest.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Carbon\Carbon;
66
use Illuminate\Support\Facades\File;
77
use Illuminate\Support\Facades\Storage;
8+
use Itiden\Backup\Contracts\BackupNameResolver;
89
use Itiden\Backup\Contracts\Repositories\BackupRepository;
910
use Itiden\Backup\DataTransferObjects\BackupDto;
1011
use Itiden\Backup\Facades\Backuper;
@@ -18,14 +19,22 @@
1819

1920
describe('backuper', function (): void {
2021
it('can backup', function (): void {
21-
$this->withoutExceptionHandling();
22+
Carbon::setTestNow(Carbon::now());
23+
2224
$backup = Backuper::backup();
2325

26+
$filename = app(BackupNameResolver::class)->generateFilename(Carbon::now()->toImmutable(), $backup->id);
27+
2428
expect($backup)->toBeInstanceOf(BackupDto::class);
2529

26-
expect(Storage::disk(config('backup.destination.disk'))->exists(
27-
config('backup.destination.path') . "/{$backup->name}.zip",
28-
))->toBeTrue();
30+
expect(Storage::disk(config('backup.destination.disk'))->exists(str(
31+
config('backup.destination.path') . "/{$filename}",
32+
)->finish('.zip')))->toBeTrue();
33+
34+
expect(pathinfo(
35+
Storage::disk(config('backup.destination.disk'))->path($backup->path),
36+
PATHINFO_EXTENSION,
37+
))->toBe('zip');
2938
});
3039

3140
it('backups correct files', function (): void {

0 commit comments

Comments
 (0)