feat(attachment): implement deletion of cropped attachments alongside original and update README
This commit is contained in:
@@ -108,13 +108,23 @@ class AttachmentService
|
|||||||
|
|
||||||
public function delete(Attachment $attachment): void
|
public function delete(Attachment $attachment): void
|
||||||
{
|
{
|
||||||
$deleted = Storage::disk('s3')->delete($attachment->path);
|
$croppedAttachment = $attachment->croppedAttachment;
|
||||||
|
$paths = array_values(array_filter([
|
||||||
|
$attachment->path,
|
||||||
|
$croppedAttachment?->path,
|
||||||
|
]));
|
||||||
|
$deleted = Storage::disk('s3')->delete(
|
||||||
|
count($paths) === 1 ? $paths[0] : $paths
|
||||||
|
);
|
||||||
|
|
||||||
if (! $deleted) {
|
if (! $deleted) {
|
||||||
throw new AttachmentStorageException('No se pudo eliminar el archivo del disco s3.');
|
throw new AttachmentStorageException('No se pudieron eliminar los archivos del disco s3.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$attachment->delete();
|
DB::transaction(function () use ($attachment, $croppedAttachment): void {
|
||||||
|
$attachment->delete();
|
||||||
|
$croppedAttachment?->delete();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function copy(Attachment $source, string $path): Attachment
|
public function copy(Attachment $source, string $path): Attachment
|
||||||
|
|||||||
@@ -27,5 +27,6 @@ No expone rutas HTTP propias. Lo consumen otros dominios, especialmente `Catalog
|
|||||||
- El directorio no puede quedar vacío después de normalizarlo.
|
- El directorio no puede quedar vacío después de normalizarlo.
|
||||||
- Los porcentajes de inicio del crop deben estar en el rango `[0, 100)`; el recorte se extiende desde ese punto hasta los bordes derecho e inferior.
|
- Los porcentajes de inicio del crop deben estar en el rango `[0, 100)`; el recorte se extiende desde ese punto hasta los bordes derecho e inferior.
|
||||||
- El attachment original guarda los porcentajes y la relación `croppedAttachment` con la versión procesada.
|
- El attachment original guarda los porcentajes y la relación `croppedAttachment` con la versión procesada.
|
||||||
|
- Al eliminar el original mediante el servicio también se elimina su versión recortada.
|
||||||
- La eliminación se considera fallida si S3 no confirma el borrado.
|
- La eliminación se considera fallida si S3 no confirma el borrado.
|
||||||
- Las URL generadas son temporales; el vencimiento predeterminado es de 10 minutos.
|
- Las URL generadas son temporales; el vencimiento predeterminado es de 10 minutos.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"keywords": ["laravel", "framework"],
|
"keywords": ["laravel", "framework"],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
|
"ext-gd": "*",
|
||||||
"php": "^8.3",
|
"php": "^8.3",
|
||||||
"barryvdh/laravel-dompdf": "^3.1",
|
"barryvdh/laravel-dompdf": "^3.1",
|
||||||
"endroid/qr-code": "^6.1",
|
"endroid/qr-code": "^6.1",
|
||||||
|
|||||||
3
composer.lock
generated
3
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "aa7e98d017dd610946c62579b20c501f",
|
"content-hash": "ce185c60c617846be30ae694f0cf6e9c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-crt-php",
|
"name": "aws/aws-crt-php",
|
||||||
@@ -9838,6 +9838,7 @@
|
|||||||
"prefer-stable": true,
|
"prefer-stable": true,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
|
"ext-gd": "*",
|
||||||
"php": "^8.3"
|
"php": "^8.3"
|
||||||
},
|
},
|
||||||
"platform-dev": {},
|
"platform-dev": {},
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ return new class extends Migration
|
|||||||
$table->decimal('crop_vertical_start_percent', 7, 4)->nullable()->after('crop_horizontal_start_percent');
|
$table->decimal('crop_vertical_start_percent', 7, 4)->nullable()->after('crop_horizontal_start_percent');
|
||||||
$table->foreignId('cropped_attachment_id')
|
$table->foreignId('cropped_attachment_id')
|
||||||
->nullable()
|
->nullable()
|
||||||
|
->unique()
|
||||||
->after('crop_vertical_start_percent')
|
->after('crop_vertical_start_percent')
|
||||||
->constrained('attachments')
|
->constrained('attachments')
|
||||||
->nullOnDelete();
|
->nullOnDelete();
|
||||||
|
|||||||
@@ -140,6 +140,25 @@ class AttachmentTest extends TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_it_deletes_the_crop_together_with_its_original(): void
|
||||||
|
{
|
||||||
|
Storage::fake('s3');
|
||||||
|
|
||||||
|
$original = app(AttachmentService::class)->storeCroppedImage(
|
||||||
|
UploadedFile::fake()->image('product.png'),
|
||||||
|
'attachments/acme',
|
||||||
|
10,
|
||||||
|
10,
|
||||||
|
);
|
||||||
|
$cropped = $original->croppedAttachment;
|
||||||
|
|
||||||
|
app(AttachmentService::class)->delete($original);
|
||||||
|
|
||||||
|
$this->assertDatabaseCount('attachments', 0);
|
||||||
|
Storage::disk('s3')->assertMissing($original->path);
|
||||||
|
Storage::disk('s3')->assertMissing($cropped->path);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_it_deletes_from_s3_before_removing_the_database_record(): void
|
public function test_it_deletes_from_s3_before_removing_the_database_record(): void
|
||||||
{
|
{
|
||||||
Storage::fake('s3');
|
Storage::fake('s3');
|
||||||
|
|||||||
Reference in New Issue
Block a user