Skip to content

Commit 3f9cf84

Browse files
committed
created media manipulator
1 parent fffe1c0 commit 3f9cf84

8 files changed

Lines changed: 355 additions & 0 deletions

config/mediapicker.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,12 @@
3535
*/
3636

3737
'attachment_observer' => \Javaabu\Mediapicker\Models\Observers\AttachmentObserver::class,
38+
39+
/*
40+
* Here you can override the class names of the jobs used by this package. Make sure
41+
* your custom jobs extend the ones provided by the package.
42+
*/
43+
'jobs' => [
44+
'perform_conversions' => \Javaabu\Mediapicker\Conversions\Jobs\PerformAttachmentConversionsJob::class,
45+
],
3846
];
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Conversions\Actions;
4+
5+
use Javaabu\Mediapicker\Contracts\Attachment;
6+
use Javaabu\Mediapicker\Conversions\Events\AttachmentConversionHasBeenCompletedEvent;
7+
use Javaabu\Mediapicker\Conversions\Events\AttachmentConversionWillStartEvent;
8+
use Spatie\MediaLibrary\Conversions\Conversion;
9+
use Spatie\MediaLibrary\Conversions\ImageGenerators\ImageGeneratorFactory;
10+
use Spatie\MediaLibrary\MediaCollections\Filesystem;
11+
use Spatie\MediaLibrary\ResponsiveImages\ResponsiveImageGenerator;
12+
13+
class PerformAttachmentConversionAction
14+
{
15+
public function execute(
16+
Conversion $conversion,
17+
Attachment $attachment,
18+
string $copiedOriginalFile
19+
): void {
20+
$media = $attachment->media;
21+
22+
$imageGenerator = ImageGeneratorFactory::forMedia($media);
23+
24+
$copiedOriginalFile = $imageGenerator->convert($copiedOriginalFile, $conversion);
25+
26+
if (! $copiedOriginalFile) {
27+
return;
28+
}
29+
30+
event(new AttachmentConversionWillStartEvent($attachment, $conversion, $copiedOriginalFile));
31+
32+
$manipulationResult = (new PerformAttachmentManipulationsAction)->execute($attachment, $conversion, $copiedOriginalFile);
33+
34+
$newFileName = $conversion->getConversionFile($media);
35+
36+
$renamedFile = $this->renameInLocalDirectory($manipulationResult, $newFileName);
37+
38+
if ($conversion->shouldGenerateResponsiveImages()) {
39+
/** @var ResponsiveImageGenerator $responsiveImageGenerator */
40+
$responsiveImageGenerator = app(ResponsiveImageGenerator::class);
41+
42+
$responsiveImageGenerator->generateResponsiveImagesForConversion(
43+
$media,
44+
$conversion,
45+
$renamedFile
46+
);
47+
}
48+
49+
app(Filesystem::class)->copyToMediaLibrary($renamedFile, $media, 'conversions');
50+
51+
$media->markAsConversionGenerated($conversion->getName());
52+
53+
event(new AttachmentConversionHasBeenCompletedEvent($attachment, $conversion));
54+
}
55+
56+
protected function renameInLocalDirectory(
57+
string $fileNameWithDirectory,
58+
string $newFileNameWithoutDirectory
59+
): string {
60+
$targetFile = pathinfo($fileNameWithDirectory, PATHINFO_DIRNAME).'/'.$newFileNameWithoutDirectory;
61+
62+
rename($fileNameWithDirectory, $targetFile);
63+
64+
return $targetFile;
65+
}
66+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Conversions\Actions;
4+
5+
use Illuminate\Support\Facades\File;
6+
use Illuminate\Support\Str;
7+
use Javaabu\Mediapicker\Models\Attachment;
8+
use Spatie\Image\Exceptions\UnsupportedImageFormat;
9+
use Spatie\Image\Image;
10+
use Spatie\MediaLibrary\Conversions\Conversion;
11+
use Spatie\MediaLibrary\MediaCollections\Models\Media;
12+
13+
class PerformAttachmentManipulationsAction
14+
{
15+
public function execute(
16+
Attachment $attachment,
17+
Conversion $conversion,
18+
string $imageFile,
19+
): string {
20+
$media = $attachment->media;
21+
22+
if ($conversion->getManipulations()->isEmpty()) {
23+
return $imageFile;
24+
}
25+
26+
$conversionTempFile = $this->getConversionTempFileName($media, $conversion, $imageFile);
27+
28+
File::copy($imageFile, $conversionTempFile);
29+
30+
$supportedFormats = ['jpg', 'jpeg', 'pjpg', 'png', 'gif', 'webp'];
31+
if ($conversion->shouldKeepOriginalImageFormat() && in_array($media->extension, $supportedFormats)) {
32+
$conversion->format($media->extension);
33+
}
34+
35+
$image = Image::useImageDriver(config('media-library.image_driver'))
36+
->loadFile($conversionTempFile)
37+
->format('jpg');
38+
39+
try {
40+
$conversion->getManipulations()->apply($image);
41+
42+
$image->save();
43+
} catch (UnsupportedImageFormat) {
44+
45+
}
46+
47+
return $conversionTempFile;
48+
}
49+
50+
protected function getConversionTempFileName(
51+
Media $media,
52+
Conversion $conversion,
53+
string $imageFile,
54+
): string {
55+
$directory = pathinfo($imageFile, PATHINFO_DIRNAME);
56+
57+
$extension = $media->extension;
58+
59+
if ($extension === '') {
60+
$extension = 'jpg';
61+
}
62+
63+
$fileName = Str::random(32)."{$conversion->getName()}.{$extension}";
64+
65+
return "{$directory}/{$fileName}";
66+
}
67+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Conversions\Events;
4+
5+
use Illuminate\Queue\SerializesModels;
6+
use Javaabu\Mediapicker\Contracts\Attachment;
7+
use Spatie\MediaLibrary\Conversions\Conversion;
8+
9+
class AttachmentConversionHasBeenCompletedEvent
10+
{
11+
use SerializesModels;
12+
13+
public function __construct(public Attachment $attachment, public Conversion $conversion) {}
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Conversions\Events;
4+
5+
use Illuminate\Queue\SerializesModels;
6+
use Javaabu\Mediapicker\Contracts\Attachment;
7+
use Spatie\MediaLibrary\Conversions\Conversion;
8+
9+
class AttachmentConversionWillStartEvent
10+
{
11+
use SerializesModels;
12+
13+
public function __construct(
14+
public Attachment $attachment,
15+
public Conversion $conversion,
16+
public string $copiedOriginalFile,
17+
) {}
18+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Conversions\Jobs;
4+
5+
use Illuminate\Bus\Queueable;
6+
use Illuminate\Contracts\Queue\ShouldQueue;
7+
use Illuminate\Queue\InteractsWithQueue;
8+
use Illuminate\Queue\SerializesModels;
9+
use Javaabu\Mediapicker\Contracts\Attachment;
10+
use Spatie\MediaLibrary\Conversions\ConversionCollection;
11+
use Spatie\MediaLibrary\Conversions\FileManipulator;
12+
use Spatie\MediaLibrary\MediaCollections\Models\Media;
13+
14+
class PerformAttachmentConversionsJob implements ShouldQueue
15+
{
16+
use InteractsWithQueue;
17+
use Queueable;
18+
use SerializesModels;
19+
20+
public $deleteWhenMissingModels = true;
21+
22+
public function __construct(
23+
protected ConversionCollection $conversions,
24+
protected Attachment $attachment,
25+
protected bool $onlyMissing = false,
26+
) {}
27+
28+
public function handle(FileManipulator $fileManipulator): bool
29+
{
30+
$fileManipulator->performConversions(
31+
$this->conversions,
32+
$this->media,
33+
$this->onlyMissing
34+
);
35+
36+
return true;
37+
}
38+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
namespace Javaabu\Mediapicker\Conversions;
4+
5+
use Illuminate\Support\Facades\Storage;
6+
use Illuminate\Support\Str;
7+
use Javaabu\Mediapicker\Contracts\Attachment;
8+
use Javaabu\Mediapicker\Conversions\Jobs\PerformAttachmentConversionsJob;
9+
use Spatie\MediaLibrary\Conversions\Actions\PerformConversionAction;
10+
use Spatie\MediaLibrary\Conversions\Conversion;
11+
use Spatie\MediaLibrary\Conversions\FileManipulator;
12+
use Spatie\MediaLibrary\Conversions\ImageGenerators\ImageGeneratorFactory;
13+
use Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob;
14+
use Spatie\MediaLibrary\MediaCollections\Filesystem;
15+
use Spatie\MediaLibrary\MediaCollections\Models\Media;
16+
use Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob;
17+
use Spatie\MediaLibrary\Support\TemporaryDirectory;
18+
19+
class MediaManipulator extends FileManipulator
20+
{
21+
public function createDerivedAttachmentFiles(
22+
Attachment $attachment,
23+
array $onlyConversionNames = [],
24+
bool $onlyMissing = false,
25+
bool $withResponsiveImages = false,
26+
bool $queueAll = false,
27+
): void {
28+
$media = $attachment->media;
29+
30+
if (! $this->canConvertMedia($media)) {
31+
return;
32+
}
33+
34+
[$queuedConversions, $conversions] = AttachmentConversionCollection::createForAttachment($attachment)
35+
->filter(function (Conversion $conversion) use ($onlyConversionNames) {
36+
if (count($onlyConversionNames) === 0) {
37+
return true;
38+
}
39+
40+
return in_array($conversion->getName(), $onlyConversionNames);
41+
})
42+
->filter(fn (Conversion $conversion) => $conversion->shouldBePerformedOn($attachment->collection_name))
43+
->partition(fn (Conversion $conversion) => $queueAll || $conversion->shouldBeQueued());
44+
45+
$this
46+
->performAttachmentConversions($conversions, $attachment, $onlyMissing)
47+
->dispatchQueuedAttachmentConversions($attachment, $queuedConversions, $onlyMissing);
48+
}
49+
50+
public function performAttachmentConversions(
51+
AttachmentConversionCollection $conversions,
52+
Attachment $attachment,
53+
bool $onlyMissing = false
54+
): self {
55+
$media = $attachment->media;
56+
57+
$conversions = $conversions
58+
->when(
59+
$onlyMissing,
60+
fn (AttachmentConversionCollection $conversions) => $conversions->reject(function (Conversion $conversion) use ($attachment, $media) {
61+
$relativePath = $attachment->getPath($conversion->getName());
62+
63+
if ($rootPath = config("filesystems.disks.{$media->disk}.root")) {
64+
$relativePath = str_replace($rootPath, '', $relativePath);
65+
}
66+
67+
return Storage::disk($media->disk)->exists($relativePath);
68+
})
69+
);
70+
71+
if ($conversions->isEmpty()) {
72+
return $this;
73+
}
74+
75+
$temporaryDirectory = TemporaryDirectory::create();
76+
77+
$copiedOriginalFile = app(Filesystem::class)->copyFromMediaLibrary(
78+
$media,
79+
$temporaryDirectory->path(Str::random(32).'.'.$media->extension)
80+
);
81+
82+
$conversions->each(fn (Conversion $conversion) => (new PerformConversionAction)->execute($conversion, $media, $copiedOriginalFile));
83+
84+
$temporaryDirectory->delete();
85+
86+
return $this;
87+
}
88+
89+
/**
90+
* @return $this
91+
*/
92+
protected function dispatchQueuedAttachmentConversions(
93+
Attachment $attachment,
94+
AttachmentConversionCollection $conversions,
95+
bool $onlyMissing = false
96+
): self {
97+
if ($conversions->isEmpty()) {
98+
return $this;
99+
}
100+
101+
$performConversionsJobClass = config(
102+
'mediapicker.jobs.perform_conversions',
103+
PerformAttachmentConversionsJob::class
104+
);
105+
106+
/** @var PerformAttachmentConversionsJob $job */
107+
$job = (new $performConversionsJobClass($conversions, $attachment, $onlyMissing))
108+
->onConnection(config('media-library.queue_connection_name'))
109+
->onQueue(config('media-library.queue_name'));
110+
111+
config('media-library.queue_conversions_after_database_commit')
112+
? dispatch($job)->afterCommit()
113+
: dispatch($job);
114+
115+
return $this;
116+
}
117+
118+
protected function canConvertMedia(Media $media): bool
119+
{
120+
$imageGenerator = ImageGeneratorFactory::forMedia($media);
121+
122+
return $imageGenerator ? true : false;
123+
}
124+
}

src/Models/Observers/AttachmentObserver.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Javaabu\Mediapicker\Models\Observers;
44

55
use Javaabu\Mediapicker\Contracts\Attachment;
6+
use Javaabu\Mediapicker\Conversions\MediaManipulator;
7+
use Javaabu\Mediapicker\Mediapicker;
68

79
class AttachmentObserver
810
{
@@ -15,5 +17,23 @@ public function creating(Attachment $attachment): void
1517
}
1618
}
1719

20+
public function created(Attachment $attachment): void
21+
{
22+
if (is_null($attachment->model_id)) {
23+
return;
24+
}
25+
26+
$attachmentClass = Mediapicker::attachmentModel();
27+
28+
$eventDispatcher = $attachmentClass::getEventDispatcher();
29+
$attachmentClass::unsetEventDispatcher();
30+
31+
/** @var MediaManipulator $mediaManipulator */
32+
$mediaManipulator = app(MediaManipulator::class);
33+
34+
$mediaManipulator->createDerivedAttachmentFiles($attachment);
35+
36+
$attachmentClass::setEventDispatcher($eventDispatcher);
37+
}
1838
// TODO
1939
}

0 commit comments

Comments
 (0)