|null $newFiles * @param list|null $removeIds */ public function syncCollection( HasMedia $model, string $collection, ?array $newFiles, ?array $removeIds, int $maxFiles, ?string $type = null, bool $required = false, ?string $errorKey = null, ): void { $newFiles = array_values(array_filter($newFiles ?? [])); if ($maxFiles === 1 && $newFiles !== []) { $model->clearMediaCollection($collection); } elseif ($removeIds !== null && $removeIds !== []) { $model->getMedia($collection) ->whereIn('id', $removeIds) ->each->delete(); } if ($maxFiles === 1) { $newFiles = array_slice($newFiles, 0, 1); } $currentCount = $model->getMedia($collection)->count(); if ($currentCount + count($newFiles) > $maxFiles) { throw ValidationException::withMessages([ $errorKey ?? $collection => "Maksimal {$maxFiles} gambar per item.", ]); } foreach ($newFiles as $file) { $this->addUploadedFile($model, $file, $collection, $type); } 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); } 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); } /** * @return array{module: string, type?: string} */ 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; } }