124 lines
4.0 KiB
PHP
124 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace Modules\AssetExchange\Services;
|
|
|
|
use App\Business;
|
|
use App\User;
|
|
use App\Utils\Util;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Modules\AssetExchange\Models\Listing;
|
|
use Modules\AssetExchange\Models\ListingMedia;
|
|
|
|
class MediaService
|
|
{
|
|
public const UPLOAD_DIR = 'aex_listings';
|
|
|
|
public function __construct(
|
|
protected Util $commonUtil
|
|
) {
|
|
}
|
|
|
|
public function uploadForListing(Business $business, Listing $listing, Request $request, ?User $user = null): int
|
|
{
|
|
if (! Schema::hasTable('aex_listing_media')) {
|
|
return 0;
|
|
}
|
|
|
|
$count = 0;
|
|
$sort = (int) $listing->media()->max('sort_order');
|
|
|
|
if ($request->hasFile('photos')) {
|
|
foreach ((array) $request->file('photos') as $file) {
|
|
if ($file instanceof UploadedFile && $file->isValid()) {
|
|
$this->storeFile($business, $listing, $file, 'photo', null, ++$sort);
|
|
$count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($request->hasFile('documents')) {
|
|
foreach ((array) $request->file('documents') as $file) {
|
|
if ($file instanceof UploadedFile && $file->isValid()) {
|
|
$this->storeFile($business, $listing, $file, 'document', null, ++$sort);
|
|
$count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (['photo', 'document'] as $type) {
|
|
$single = $type === 'photo' ? 'photo' : 'document';
|
|
if ($request->hasFile($single) && $request->file($single)->isValid()) {
|
|
$this->storeFile($business, $listing, $request->file($single), $type, null, ++$sort);
|
|
$count++;
|
|
}
|
|
}
|
|
|
|
return $count;
|
|
}
|
|
|
|
public function storeFile(
|
|
Business $business,
|
|
Listing $listing,
|
|
UploadedFile $file,
|
|
string $mediaType,
|
|
?string $caption = null,
|
|
int $sortOrder = 0
|
|
): ListingMedia {
|
|
if (config('app.env') === 'demo') {
|
|
throw new \RuntimeException('آپلود در محیط دمو غیرفعال است.');
|
|
}
|
|
|
|
$fileType = $mediaType === 'photo' ? 'image' : 'document';
|
|
|
|
if ($fileType === 'image' && ! str_starts_with((string) $file->getMimeType(), 'image/')) {
|
|
throw new \RuntimeException('فایل تصویر نامعتبر است.');
|
|
}
|
|
|
|
if ($fileType === 'document') {
|
|
$allowed = array_keys(config('constants.document_upload_mimes_types', []));
|
|
if ($allowed && ! in_array($file->getMimeType(), $allowed, true)) {
|
|
throw new \RuntimeException('نوع فایل مجاز نیست.');
|
|
}
|
|
}
|
|
|
|
if ($file->getSize() > config('constants.document_size_limit')) {
|
|
throw new \RuntimeException('حجم فایل بیش از حد مجاز است.');
|
|
}
|
|
|
|
$original = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
|
|
$extension = $file->getClientOriginalExtension();
|
|
$stored = time().'_'.Str::slug($original).($extension ? '.'.$extension : '');
|
|
|
|
if (! $file->storeAs(self::UPLOAD_DIR, $stored)) {
|
|
throw new \RuntimeException('آپلود فایل ناموفق بود.');
|
|
}
|
|
|
|
return ListingMedia::create([
|
|
'business_id' => $business->id,
|
|
'listing_id' => $listing->id,
|
|
'media_type' => $mediaType,
|
|
'path' => $stored,
|
|
'caption' => $caption,
|
|
'sort_order' => $sortOrder,
|
|
]);
|
|
}
|
|
|
|
public function deleteMedia(ListingMedia $media): void
|
|
{
|
|
$fullPath = public_path('uploads/'.self::UPLOAD_DIR.'/'.$media->path);
|
|
if (is_file($fullPath)) {
|
|
@unlink($fullPath);
|
|
}
|
|
$media->delete();
|
|
}
|
|
|
|
public function publicUrl(ListingMedia $media): string
|
|
{
|
|
return asset('uploads/'.self::UPLOAD_DIR.'/'.$media->path);
|
|
}
|
|
}
|