mivita/app/Repositories/DC/FileRepository.php
2025-04-01 10:36:47 +02:00

217 lines
No EOL
6.8 KiB
PHP

<?php
namespace App\Repositories\DC;
use App\Models\DcFile;
use App\Services\Util;
use App\Models\DcFileTag;
use App\Repositories\BaseRepository;
use Intervention\Image\Facades\Image;
use Imagick;
class FileRepository extends BaseRepository {
private const ALLOWED_IMAGE_TYPES = [
'image/jpeg',
'image/gif',
'image/png'
];
private const ALLOWED_PDF_TYPES = [
'application/pdf'
];
private const THUMB_WIDTH = 542;
private const THUMB_HEIGHT = 360;
private const BIG_WIDTH = 1600;
private const BIG_HEIGHT = 900;
public function uploadFile(array $form_data): DcFile
{
if (!isset($form_data['file']) || !$form_data['file']->isValid()) {
throw new \InvalidArgumentException('Invalid file provided');
}
$file = $form_data['file'];
$originalName = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$mine = $file->getClientMimeType();
$size = $file->getSize();
$originalNameWithoutExt = substr($originalName, 0, strlen($originalName) - strlen($extension) - 1);
$filename = Util::sanitize($originalNameWithoutExt, true, false, true);
$allowed_filename = uniqid() . '_' . $filename.".".$extension;
$file->storeAs('dc/files', $allowed_filename, 'public');
// $store = $file->store('files/');
$dc_file = DcFile::create([
'filename' => $allowed_filename,
'original_name' => $originalName,
'ext' => $extension,
'mine' => $mine,
'size' => $size
]);
$this->makeThumbFromFile($dc_file);
return $dc_file;
}
public function makeThumb(int $id): bool
{
$file = DcFile::findOrFail($id);
$this->makeThumbFromFile($file);
return true;
}
public function makeThumbFromFile(DcFile $file): bool
{
try {
$path = $file->getFile(true);
if (!file_exists($path)) {
throw new \Exception('File not found');
}
$filename = $file->filename;
$mime = \File::mimeType($path);
if (in_array($mime, self::ALLOWED_IMAGE_TYPES)) {
$this->processImage($path, $filename);
} elseif (in_array($mime, self::ALLOWED_PDF_TYPES)) {
$this->processPdf($path, $filename);
}
return true;
} catch (\Exception $e) {
\Log::error('Thumbnail creation failed: ' . $e->getMessage());
return false;
}
}
private function processImage(string $path, string $filename): void
{
// Thumbnail
$img = Image::make($path);
$img->resize(542, 360, function ($c) {
$c->aspectRatio();
$c->upsize();
});
\Storage::disk('public')->put('dc/thumb/'.basename($filename), (string) $img->encode());
// Big image
$img = Image::make($path);
$img->resize(1600, 900, function ($c) {
$c->aspectRatio();
$c->upsize();
});
\Storage::disk('public')->put('dc/big/'.basename($filename), (string) $img->encode());
}
private function processPdf(string $path, string $filename): void
{
try {
// PDF mit höherer Auflösung rendern
$imagick = new \Imagick();
$imagick->setResolution(300, 300);
$imagick->readImage($path.'[0]');
// Grundlegende Bildoptimierungen
$imagick->setImageBackgroundColor('#ffffff');
$imagick->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
$imagick->setImageFormat('jpg');
$imagick->setImageCompression(\Imagick::COMPRESSION_JPEG);
$imagick->setImageCompressionQuality(80);
// Große Version erstellen
$bigImage = clone $imagick;
$bigImage->resizeImage(self::BIG_WIDTH, self::BIG_HEIGHT, \Imagick::FILTER_LANCZOS, 1, true);
$bigImage->writeImage(\Storage::disk('public')->path('dc/big/').basename($filename).'.jpg');
$bigImage->clear();
// Thumbnail erstellen
$imagick->resizeImage(self::THUMB_WIDTH, self::THUMB_HEIGHT, \Imagick::FILTER_LANCZOS, 1, true);
$imagick->writeImage(\Storage::disk('public')->path('dc/thumb/').basename($filename).'.jpg');
// Ressourcen freigeben
$imagick->clear();
} catch (\ImagickException $e) {
\Log::error('PDF Verarbeitung fehlgeschlagen: ' . $e->getMessage());
throw new \RuntimeException('PDF Verarbeitung fehlgeschlagen: ' . $e->getMessage());
} finally {
if (isset($bigImage)) {
$bigImage->destroy();
}
if (isset($imagick)) {
$imagick->destroy();
}
}
}
public function tagsUpdate($id, array $tags = []): bool
{
$file = DcFile::findOrFail($id);
// Get existing tags
$existingTags = DcFileTag::where('file_id', $file->id)
->pluck('tag_id')
->toArray();
// Delete removed tags
$tagsToDelete = array_diff($existingTags, $tags);
if (!empty($tagsToDelete)) {
DcFileTag::where('file_id', $file->id)
->whereIn('tag_id', $tagsToDelete)
->delete();
}
// Add new tags
$tagsToAdd = array_diff($tags, $existingTags);
$newTags = [];
foreach ($tagsToAdd as $tagId) {
$newTags[] = [
'file_id' => $file->id,
'tag_id' => $tagId
];
}
if (!empty($newTags)) {
DcFileTag::insert($newTags);
}
return true;
}
private function deleteFileIfExists(string $path): void
{
if (file_exists($path)) {
unlink($path);
}
}
public function deleteThumb($id): bool
{
try {
$file = DcFile::findOrFail($id);
$this->deleteFileIfExists($file->getThumb(true));
$this->deleteFileIfExists($file->getBig(true));
return true;
} catch (\Exception $e) {
\Log::error('Thumbnail deletion failed: ' . $e->getMessage());
return false;
}
}
public function deleteFile(int $id): bool
{
try {
$file = DcFile::findOrFail($id);
$this->deleteFileIfExists($file->getThumb(true));
$this->deleteFileIfExists($file->getBig(true));
$this->deleteFileIfExists($file->getFile(true));
$file->delete();
return true;
} catch (\Exception $e) {
\Log::error('File deletion failed: ' . $e->getMessage());
return false;
}
}
}