Skip to content

Commit 8ba5a09

Browse files
committed
- Added regenerate attachments command
1 parent 3a9b1ee commit 8ba5a09

4 files changed

Lines changed: 316 additions & 1 deletion

File tree

src/Commands/AttachmentsRegenerateCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class AttachmentsRegenerateCommand extends Command
1818

1919
protected $signature = 'mediapicker:regenerate {modelType?} {--ids=*}
2020
{--only=* : Regenerate specific conversions}
21-
{--starting-from-id= : Regenerate media with an id equal to or higher than the provided value}
21+
{--starting-from-id= : Regenerate attachment with an id equal to or higher than the provided value}
2222
{--X|exclude-starting-id : Exclude the provided id when regenerating from a specific id}
2323
{--only-missing : Regenerate only missing conversions}
2424
{--force : Force the operation to run when in production}
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Tests\Feature\Commands;
4+
5+
use Illuminate\Foundation\Testing\RefreshDatabase;
6+
use Illuminate\Support\Facades\DB;
7+
use Illuminate\Support\Facades\File;
8+
use Javaabu\Mediapicker\Tests\TestCase;
9+
use PHPUnit\Framework\Attributes\Test;
10+
11+
class AttachmentsRegenerateCommandTest extends TestCase
12+
{
13+
use RefreshDatabase;
14+
15+
#[Test]
16+
public function it_can_regenerate_missing_attachment_conversions(): void
17+
{
18+
$model = $this->getModelWithConversions();
19+
$media = $this->getMedia();
20+
21+
$attachment = $model->addAttachment($media)
22+
->toAttachmentCollection();
23+
24+
$path = $model->getFirstAttachmentPath(conversionName: 'test');
25+
26+
$this->assertEquals($this->getMediaDirectory($media->getKey() . '/conversions/test-test.jpg'), $path);
27+
28+
File::delete($path);
29+
$this->assertFileDoesNotExist($path);
30+
31+
$this->assertDatabaseHas('attachments', [
32+
'id' => $attachment->id,
33+
]);
34+
35+
$this->artisan('mediapicker:regenerate')
36+
->assertSuccessful();
37+
38+
$this->assertDatabaseHas('attachments', [
39+
'id' => $attachment->id,
40+
]);
41+
42+
$this->assertFileExists($path);
43+
}
44+
45+
#[Test]
46+
public function it_can_regenerate_only_specific_attachment_conversions(): void
47+
{
48+
$model = $this->getModelWithMultipleConversions();
49+
$media = $this->getMedia();
50+
51+
$attachment = $model->addAttachment($media)
52+
->toAttachmentCollection();
53+
54+
$path_1 = $model->getFirstAttachmentPath(conversionName: 'test');
55+
$path_2 = $model->getFirstAttachmentPath(conversionName: 'test2');
56+
57+
$this->assertEquals($this->getMediaDirectory($media->getKey() . '/conversions/test-test.jpg'), $path_1);
58+
$this->assertEquals($this->getMediaDirectory($media->getKey() . '/conversions/test-test2.jpg'), $path_2);
59+
60+
File::delete($path_1);
61+
File::delete($path_2);
62+
63+
$this->assertFileDoesNotExist($path_1);
64+
$this->assertFileDoesNotExist($path_2);
65+
66+
$this->assertDatabaseHas('attachments', [
67+
'id' => $attachment->id,
68+
]);
69+
70+
$this->artisan('mediapicker:regenerate', ['--only' => 'test'])
71+
->assertSuccessful();
72+
73+
$this->assertDatabaseHas('attachments', [
74+
'id' => $attachment->id,
75+
]);
76+
77+
$this->assertFileExists($path_1);
78+
$this->assertFileDoesNotExist($path_2);
79+
}
80+
81+
#[Test]
82+
public function it_can_regenerate_by_model_type(): void
83+
{
84+
// Create two different model types
85+
$model1 = $this->getModelWithConversions();
86+
$model2 = $this->getModelWithMultipleConversions();
87+
88+
$media1 = $this->getMedia();
89+
$media2 = $this->getMedia();
90+
91+
$attachment1 = $model1->addAttachment($media1)->toAttachmentCollection();
92+
$attachment2 = $model2->addAttachment($media2)->toAttachmentCollection();
93+
94+
$path1 = $model1->getFirstAttachmentPath(conversionName: 'test');
95+
$path2 = $model2->getFirstAttachmentPath(conversionName: 'test');
96+
97+
File::delete($path1);
98+
File::delete($path2);
99+
100+
$this->assertFileDoesNotExist($path1);
101+
$this->assertFileDoesNotExist($path2);
102+
103+
// Only regenerate first model type
104+
$this->artisan('mediapicker:regenerate', [
105+
'modelType' => $model1->getMorphClass(),
106+
])->assertSuccessful();
107+
108+
$this->assertFileExists($path1);
109+
$this->assertFileDoesNotExist($path2);
110+
}
111+
112+
#[Test]
113+
public function it_can_regenerate_by_ids(): void
114+
{
115+
$model = $this->getModelWithConversions();
116+
117+
$media1 = $this->getMedia();
118+
$media2 = $this->getMedia();
119+
120+
$attachment1 = $model->addAttachment($media1)->toAttachmentCollection();
121+
$attachment2 = $model->addAttachment($media2)->toAttachmentCollection();
122+
123+
$path1 = $attachment1->getPath('test');
124+
$path2 = $attachment2->getPath('test');
125+
126+
File::delete($path1);
127+
File::delete($path2);
128+
129+
$this->assertFileDoesNotExist($path1);
130+
$this->assertFileDoesNotExist($path2);
131+
132+
// Only regenerate first attachment
133+
$this->artisan('mediapicker:regenerate', [
134+
'--ids' => [$attachment1->id]
135+
])->assertSuccessful();
136+
137+
$this->assertFileExists($path1);
138+
$this->assertFileDoesNotExist($path2);
139+
}
140+
141+
#[Test]
142+
public function it_can_regenerate_starting_from_id(): void
143+
{
144+
$model = $this->getModelWithConversions();
145+
146+
$media1 = $this->getMedia();
147+
$media2 = $this->getMedia();
148+
$media3 = $this->getMedia();
149+
150+
$attachment1 = $model->addAttachment($media1)->toAttachmentCollection();
151+
$attachment2 = $model->addAttachment($media2)->toAttachmentCollection();
152+
$attachment3 = $model->addAttachment($media3)->toAttachmentCollection();
153+
154+
$path1 = $attachment1->getPath('test');
155+
$path2 = $attachment2->getPath('test');
156+
$path3 = $attachment3->getPath('test');
157+
158+
File::delete($path1);
159+
File::delete($path2);
160+
File::delete($path3);
161+
162+
$this->assertFileDoesNotExist($path1);
163+
$this->assertFileDoesNotExist($path2);
164+
$this->assertFileDoesNotExist($path3);
165+
166+
// Regenerate from attachment2 onwards
167+
$this->artisan('mediapicker:regenerate', [
168+
'--starting-from-id' => $attachment2->id
169+
])->assertSuccessful();
170+
171+
$this->assertFileDoesNotExist($path1);
172+
$this->assertFileExists($path2);
173+
$this->assertFileExists($path3);
174+
}
175+
176+
#[Test]
177+
public function it_can_exclude_starting_id_when_regenerating(): void
178+
{
179+
$model = $this->getModelWithConversions();
180+
181+
$media1 = $this->getMedia();
182+
$media2 = $this->getMedia();
183+
$media3 = $this->getMedia();
184+
185+
$attachment1 = $model->addAttachment($media1)->toAttachmentCollection();
186+
$attachment2 = $model->addAttachment($media2)->toAttachmentCollection();
187+
$attachment3 = $model->addAttachment($media3)->toAttachmentCollection();
188+
189+
$path1 = $attachment1->getPath('test');
190+
$path2 = $attachment2->getPath('test');
191+
$path3 = $attachment3->getPath('test');
192+
193+
File::delete($path1);
194+
File::delete($path2);
195+
File::delete($path3);
196+
197+
$this->assertFileDoesNotExist($path1);
198+
$this->assertFileDoesNotExist($path2);
199+
$this->assertFileDoesNotExist($path3);
200+
201+
// Regenerate from attachment2 onwards but exclude attachment2
202+
$this->artisan('mediapicker:regenerate', [
203+
'--starting-from-id' => $attachment2->id,
204+
'--exclude-starting-id' => true
205+
])->assertSuccessful();
206+
207+
$this->assertFileDoesNotExist($path1);
208+
$this->assertFileDoesNotExist($path2);
209+
$this->assertFileExists($path3);
210+
}
211+
212+
#[Test]
213+
public function it_can_regenerate_only_missing_conversions(): void
214+
{
215+
$model = $this->getModelWithMultipleConversions();
216+
$media = $this->getMedia();
217+
$attachment = $model->addAttachment($media)->toAttachmentCollection();
218+
219+
$path1 = $attachment->getPath('test');
220+
$path2 = $attachment->getPath('test2');
221+
222+
// Only delete the first conversion
223+
File::delete($path1);
224+
225+
$this->assertFileDoesNotExist($path1);
226+
$this->assertFileExists($path2);
227+
228+
// Get last modified time of path2 before regeneration
229+
$lastModified = File::lastModified($path2);
230+
231+
// Wait a moment to ensure the timestamps would be different if regenerated
232+
sleep(1);
233+
234+
$this->artisan('mediapicker:regenerate', [
235+
'--only-missing' => true
236+
])->assertSuccessful();
237+
238+
$this->assertFileExists($path1);
239+
$this->assertFileExists($path2);
240+
241+
// Verify that path2 wasn't regenerated (last modified time shouldn't change)
242+
$this->assertEquals($lastModified, File::lastModified($path2));
243+
}
244+
245+
#[Test]
246+
public function it_can_combine_options_model_type_and_starting_from_id(): void
247+
{
248+
// Create models of different types
249+
$model1 = $this->getModelWithConversions();
250+
$model2 = $this->getModelWithMultipleConversions();
251+
252+
// Create attachments for each model
253+
$media1 = $this->getMedia();
254+
$media2 = $this->getMedia();
255+
$media3 = $this->getMedia();
256+
257+
$attachment1 = $model1->addAttachment($media1)->toAttachmentCollection();
258+
$attachment2 = $model1->addAttachment($media2)->toAttachmentCollection();
259+
$attachment3 = $model2->addAttachment($media3)->toAttachmentCollection();
260+
261+
$path1 = $attachment1->getPath('test');
262+
$path2 = $attachment2->getPath('test');
263+
$path3 = $attachment3->getPath('test');
264+
265+
File::delete($path1);
266+
File::delete($path2);
267+
File::delete($path3);
268+
269+
$this->assertFileDoesNotExist($path1);
270+
$this->assertFileDoesNotExist($path2);
271+
$this->assertFileDoesNotExist($path3);
272+
273+
// Regenerate only model1 attachments with id >= attachment2
274+
$this->artisan('mediapicker:regenerate', [
275+
'modelType' => $model1->getMorphClass(),
276+
'--starting-from-id' => $attachment2->id
277+
])->assertSuccessful();
278+
279+
$this->assertFileDoesNotExist($path1);
280+
$this->assertFileExists($path2);
281+
$this->assertFileDoesNotExist($path3);
282+
}
283+
}

tests/TestCase.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Javaabu\Helpers\HelpersServiceProvider;
1111
use Javaabu\Mediapicker\Models\Attachment;
1212
use Javaabu\Mediapicker\Tests\TestSupport\Models\ModelWithConversions;
13+
use Javaabu\Mediapicker\Tests\TestSupport\Models\ModelWithMultipleConversions;
1314
use Javaabu\Mediapicker\Tests\TestSupport\Models\ModelWithSameConversions;
1415
use Javaabu\Mediapicker\Tests\TestSupport\Models\ModelWithSingleFile;
1516
use Javaabu\Mediapicker\Tests\TestSupport\Models\ModelWithUnacceptedFile;
@@ -120,6 +121,11 @@ protected function getModelWithSameConversions(): ModelWithSameConversions
120121
return ModelWithSameConversions::factory()->create();
121122
}
122123

124+
protected function getModelWithMultipleConversions(): ModelWithMultipleConversions
125+
{
126+
return ModelWithMultipleConversions::factory()->create();
127+
}
128+
123129
protected function getModelWithConversions(): ModelWithConversions
124130
{
125131
return ModelWithConversions::factory()->create();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Tests\TestSupport\Models;
4+
use Illuminate\Database\Eloquent\Factories\HasFactory;
5+
use Illuminate\Database\Eloquent\Model;
6+
use Javaabu\Mediapicker\Concerns\InteractsWithAttachments;
7+
use Javaabu\Mediapicker\Contracts\HasAttachments;
8+
use Javaabu\Mediapicker\Tests\TestSupport\Factories\PostFactory;
9+
use Spatie\MediaLibrary\MediaCollections\File;
10+
use Spatie\MediaLibrary\MediaCollections\Models\Media;
11+
12+
class ModelWithMultipleConversions extends Post
13+
{
14+
public function registerAttachmentConversions(?Media $media = null)
15+
{
16+
$this->addAttachmentConversion('test')
17+
->width(100)
18+
->height(100)
19+
->crop(100, 100);
20+
21+
$this->addAttachmentConversion('test2')
22+
->width(50)
23+
->height(50)
24+
->crop(50, 50);
25+
}
26+
}

0 commit comments

Comments
 (0)