350 lines
11 KiB
PHP
350 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Helpers\FirstParty\MediaEngine;
|
|
|
|
use App\Models\Media;
|
|
use App\Models\MediaCollection;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
|
|
class MediaEngine
|
|
{
|
|
const LOCAL_TEMP_DISK = 'local_temp';
|
|
|
|
const USER_UPLOADED = 'user_uploaded';
|
|
|
|
const USER_RENDERED = 'user_rendered';
|
|
|
|
const USER = 'user';
|
|
|
|
public static function getMediaCloudUrl($media)
|
|
{
|
|
return Storage::disk($media->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;
|
|
}
|
|
}
|