disk)->url($media->file_path.$media->file_name); } public static function loadMediaToLocalTemp($uuid) { $media = self::getMediaByUuid($uuid); $result = [ 'media' => $media, 'uuid' => $uuid, 'temp_path' => null, 'temp' => null, ]; if (! $media) { return $result; } if (! Storage::disk($media->disk)->exists($media->file_path.$media->file_name)) { return $result; } $tempPath = 'temp_'.$media->file_name; $fileContent = Storage::disk($media->disk)->get($media->file_path.$media->file_name); if (! Storage::disk(self::LOCAL_TEMP_DISK)->exists($tempPath)) { if (Storage::disk(self::LOCAL_TEMP_DISK)->put($tempPath, $fileContent)) { $result['temp_path'] = $tempPath; $result['temp'] = Storage::disk(self::LOCAL_TEMP_DISK)->path($tempPath); } } else { $result['temp_path'] = $tempPath; $result['temp'] = Storage::disk(self::LOCAL_TEMP_DISK)->path($tempPath); } return $result; } public static function loadMediasToLocalTemp(array $uuids) { $medias = self::getMediaByUuids($uuids); $result = []; foreach ($medias as $media) { if (! $media) { continue; // Skip invalid media instead of returning early } $tempPath = 'temp_'.$media->file_name; $singleResult = [ 'media' => $media, 'uuid' => $media->uuid, 'temp_path' => null, 'temp' => null, 'cloud_url' => Storage::disk($media->disk)->url($media->file_path.$media->file_name), ]; // Check if file exists in cloud storage if (! Storage::disk($media->disk)->exists($media->file_path.$media->file_name)) { $result[] = $singleResult; // Add to results but with null temp paths continue; } // Check if already loaded in local temp if (Storage::disk(self::LOCAL_TEMP_DISK)->exists($tempPath)) { // File already exists in temp, just set the paths $singleResult['temp_path'] = $tempPath; $singleResult['temp'] = Storage::disk(self::LOCAL_TEMP_DISK)->path($tempPath); } else { // File needs to be loaded to temp $fileContent = Storage::disk($media->disk)->get($media->file_path.$media->file_name); if (Storage::disk(self::LOCAL_TEMP_DISK)->put($tempPath, $fileContent)) { $singleResult['temp_path'] = $tempPath; $singleResult['temp'] = Storage::disk(self::LOCAL_TEMP_DISK)->path($tempPath); } } $result[] = $singleResult; } return $result; } public static function deleteMediaFromLocalTemp($uuid) { $result = self::loadMediaToLocalTemp($uuid); if ($result['temp_path']) { Storage::disk(self::LOCAL_TEMP_DISK)->delete($result['temp_path']); } return [ 'media' => $result['media'], 'uuid' => $uuid, 'temp_path' => null, 'temp' => null, ]; } public static function deleteMediasFromLocalTemp(array $uuids) { $results = self::loadMediasToLocalTemp($uuids); $deletedResults = []; foreach ($results as $result) { if ($result['temp_path']) { Storage::disk(self::LOCAL_TEMP_DISK)->delete($result['temp_path']); } $deletedResults[] = [ 'media' => $result['media'], 'uuid' => $result['uuid'], 'temp_path' => null, 'temp' => null, ]; } return $deletedResults; } /** * Add a new media file to the specified media collection. * * Example: $newMedia = MediaEngine::addMedia( * 'bgm_collection', * 'bgm', * 'user_upload', * 'web_app', * 'background_music.mp3', * $fileContent, * 'r2', * 'name of file', * $user_id, * ); */ public static function addMedia( string $mediaCollectionKey, string $mediaType, string $mediaSource, string $mediaProvider, string $fileName, string $fileContent, string $disk = 'r2', ?string $name = null, ?int $userId = null, ) { $mediaCollection = MediaCollection::where('key', $mediaCollectionKey)->first(); if (! $mediaCollection) { throw new \InvalidArgumentException("Media collection with key '{$mediaCollectionKey}' not found."); } $config = config("platform.media.{$mediaCollectionKey}"); // Adjust fileName with prefix, postfix, and ensure extension $adjustedFileName = $config['prefix'].epoch_now_timestamp().'-'.$fileName; // Construct file path $filePath = $config['location']; // Store the file $stored = Storage::disk($disk)->put($filePath.$adjustedFileName, $fileContent); if (! $stored) { throw new \RuntimeException("Failed to store file: {$filePath}"); } // Get filetype $mimeType = null; $tempFile = tempnam(sys_get_temp_dir(), 'mime_'); try { file_put_contents($tempFile, $fileContent); $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimeType = finfo_file($finfo, $tempFile); finfo_close($finfo); } finally { // This ensures the file is deleted even if an exception occurs if (file_exists($tempFile)) { unlink($tempFile); } } if (is_empty($mimeType)) { $mimeType = $config['mime']; } $media = new Media([ 'uuid' => Str::uuid(), 'media_collection_id' => $mediaCollection->id, 'user_id' => $userId, 'media_type' => $mediaType, 'media_source' => $mediaSource, 'media_provider' => $mediaProvider, 'mime_type' => $mimeType, 'file_name' => $adjustedFileName, 'file_path' => $filePath, 'disk' => $disk, 'name' => $name, ]); $media->save(); return $media; } private static function ensureUniqueFileName($fileName, $disk, $location) { $uniqueFileName = $fileName; $counter = 1; while (Storage::disk($disk)->exists($location.$uniqueFileName)) { $info = pathinfo($fileName); $uniqueFileName = $info['filename'].'-'.$counter.'.'.$info['extension']; $counter++; } return $uniqueFileName; } public static function getMediaByUuid($uuid) { return Media::where('uuid', $uuid)->first(); } public static function getMediaByUuids(array $uuids) { return Media::whereIn('uuid', $uuids)->get(); } public static function getMediasByCollectionKey($key) { $collection = MediaCollection::where('key', $key)->first(); if (! $collection) { return collect(); } return $collection->media; } public static function getCollectionKeyByOwnerMediaType($owner_type, $media_type) { $mediaConfig = config('platform.media'); foreach ($mediaConfig as $key => $item) { if ($item['owner_type'] == $owner_type && $item['media_type'] == $media_type) { return $key; } } } /** * Get file details from a URL including filename, extension and MIME type * * @param string $url The URL of the file * @return object Object containing filename, extension and MIME type */ public static function getFileDetailsbyUrl($url) { // Create an empty result object $result = new \stdClass; // Parse the URL to extract the filename $pathInfo = pathinfo(parse_url($url, PHP_URL_PATH)); // Set the filename and extension $result->filename = $pathInfo['filename'] ?? ''; $result->extension = $pathInfo['extension'] ?? ''; // Initialize the MIME type as unknown $result->mimetype = 'application/octet-stream'; // Try to get the real MIME type using fileinfo try { // Create a temporary file $tempFile = tempnam(sys_get_temp_dir(), 'file_'); // Get the file content from URL $fileContent = @file_get_contents($url); if ($fileContent !== false) { // Write the content to the temporary file file_put_contents($tempFile, $fileContent); // Create a finfo object $finfo = new \finfo(FILEINFO_MIME_TYPE); // Get the MIME type $result->mimetype = $finfo->file($tempFile); // Clean up the temporary file @unlink($tempFile); } } catch (\Exception $e) { // If there's an error, try to determine MIME type from extension $commonMimeTypes = [ // Images 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', 'svg' => 'image/svg+xml', // Audio 'mp3' => 'audio/mpeg', 'wav' => 'audio/wav', 'ogg' => 'audio/ogg', 'm4a' => 'audio/mp4', 'flac' => 'audio/flac', // Video 'mp4' => 'video/mp4', 'webm' => 'video/webm', 'avi' => 'video/x-msvideo', 'mov' => 'video/quicktime', 'mkv' => 'video/x-matroska', ]; if (! empty($result->extension) && isset($commonMimeTypes[strtolower($result->extension)])) { $result->mimetype = $commonMimeTypes[strtolower($result->extension)]; } } return $result; } }