173 lines
5.1 KiB
PHP
173 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Media;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Spatie\MediaLibrary\HasMedia;
|
|
use Spatie\MediaLibrary\InteractsWithMedia;
|
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
|
|
|
class MediaService
|
|
{
|
|
public function syncCollection(
|
|
HasMedia $model,
|
|
string $collection,
|
|
?array $newFiles,
|
|
?array $removeIds,
|
|
int $maxFiles,
|
|
?string $type = null,
|
|
bool $required = false,
|
|
?string $errorKey = null,
|
|
?array $s3Keys = null,
|
|
): void {
|
|
// Handle removals
|
|
if ($maxFiles === 1 && (! empty($newFiles) || ! empty($s3Keys))) {
|
|
$model->clearMediaCollection($collection);
|
|
} elseif ($removeIds !== null && $removeIds !== []) {
|
|
$model->getMedia($collection)
|
|
->whereIn('id', $removeIds)
|
|
->each->delete();
|
|
}
|
|
|
|
// Determine items to add (S3 keys take priority)
|
|
$useS3 = ! empty($s3Keys);
|
|
$items = $useS3
|
|
? array_values(array_filter($s3Keys))
|
|
: array_values(array_filter($newFiles ?? []));
|
|
|
|
if ($maxFiles === 1) {
|
|
$items = array_slice($items, 0, 1);
|
|
}
|
|
|
|
$currentCount = $model->getMedia($collection)->count();
|
|
|
|
if ($currentCount + count($items) > $maxFiles) {
|
|
throw ValidationException::withMessages([
|
|
$errorKey ?? $collection => "Maksimal {$maxFiles} gambar per item.",
|
|
]);
|
|
}
|
|
|
|
foreach ($items as $item) {
|
|
if ($useS3) {
|
|
$this->registerS3Key($model, $item, $collection, $type);
|
|
} else {
|
|
$this->addUploadedFile($model, $item, $collection, $type);
|
|
}
|
|
}
|
|
|
|
if ($model instanceof Model) {
|
|
$model->unsetRelation('media');
|
|
}
|
|
|
|
if ($required && $model->getMedia($collection)->isEmpty()) {
|
|
throw ValidationException::withMessages([
|
|
$errorKey ?? $collection => 'Foto wajib diisi.',
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function addUploadedFile(
|
|
HasMedia $model,
|
|
UploadedFile $file,
|
|
string $collection,
|
|
?string $type = null,
|
|
): Media {
|
|
return $model->addMedia($file)
|
|
->withCustomProperties($this->customProperties($model, $type ?? $collection))
|
|
->toMediaCollection($collection);
|
|
}
|
|
|
|
/**
|
|
* @param HasMedia&InteractsWithMedia $model
|
|
*/
|
|
public function registerS3Key(
|
|
HasMedia $model,
|
|
string $s3Key,
|
|
string $collection,
|
|
?string $type = null,
|
|
): Media {
|
|
$disk = config('filesystems.default') === 's3' ? 's3' : config('filesystems.default', 'public');
|
|
try {
|
|
return $model->addMediaFromDisk($s3Key, $disk)
|
|
->withCustomProperties($this->customProperties($model, $type ?? $collection))
|
|
->toMediaCollection($collection);
|
|
} finally {
|
|
Storage::disk($disk)->delete($s3Key);
|
|
}
|
|
}
|
|
|
|
public function addBase64Image(
|
|
HasMedia $model,
|
|
string $base64Photo,
|
|
string $collection,
|
|
?string $type = null,
|
|
string $extension = 'jpg',
|
|
): Media {
|
|
$image = base64_decode(
|
|
(string) preg_replace('#^data:image/\w+;base64,#i', '', $base64Photo),
|
|
true,
|
|
);
|
|
|
|
if ($image === false) {
|
|
throw ValidationException::withMessages([
|
|
'photo' => 'Foto tidak valid.',
|
|
]);
|
|
}
|
|
|
|
$filename = sprintf('%s.%s', Str::uuid(), $extension);
|
|
$tempPath = 'temp/'.$filename;
|
|
|
|
Storage::disk('local')->put($tempPath, $image);
|
|
|
|
try {
|
|
return $model->addMedia(Storage::disk('local')->path($tempPath))
|
|
->usingFileName($filename)
|
|
->withCustomProperties($this->customProperties($model, $type ?? $collection))
|
|
->toMediaCollection($collection);
|
|
} finally {
|
|
Storage::disk('local')->delete($tempPath);
|
|
}
|
|
}
|
|
|
|
public function replaceSingleFile(
|
|
HasMedia $model,
|
|
UploadedFile $file,
|
|
string $collection,
|
|
?string $type = null,
|
|
): Media {
|
|
$model->clearMediaCollection($collection);
|
|
|
|
return $this->addUploadedFile($model, $file, $collection, $type);
|
|
}
|
|
|
|
public function replaceSingleS3Key(
|
|
HasMedia $model,
|
|
string $s3Key,
|
|
string $collection,
|
|
?string $type = null,
|
|
): Media {
|
|
$model->clearMediaCollection($collection);
|
|
|
|
return $this->registerS3Key($model, $s3Key, $collection, $type);
|
|
}
|
|
|
|
private function customProperties(HasMedia $model, ?string $type): array
|
|
{
|
|
$properties = [
|
|
'module' => method_exists($model, 'mediaModuleName')
|
|
? $model::mediaModuleName()
|
|
: 'media',
|
|
];
|
|
|
|
if ($type !== null && $type !== '') {
|
|
$properties['type'] = $type;
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
}
|