This commit is contained in:
2023-10-02 23:10:49 +03:00
commit c6cb488379
255 changed files with 18731 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace Lucent\File;
use Illuminate\Http\UploadedFile;
use Lucent\LucentException;
use Lucent\Record\File;
use Lucent\Schema\Schema;
use Lucent\Schema\Type;
class FileService
{
public function __construct()
{
}
/**
* @throws LucentException
*/
public static function create(Schema $schema, string $uploadFromUrl, array $file): FileUploadResult
{
$emptyUploadUrl = empty($uploadFromUrl);
$emptyFileData = empty($file);
if ($schema->type === Type::FILES && $emptyUploadUrl && $emptyFileData) {
throw new LucentException("No file data submitted");
} elseif ($schema->type !== Type::FILES && !($emptyUploadUrl && $emptyFileData)) {
throw new LucentException("You can't upload a file to a regular record");
} elseif ($schema->type !== Type::FILES) {
return new FileUploadResult(
recordFile: null, duplicateId: "", isDuplicate: false
);
}
if (!$emptyUploadUrl) {
$file = self::uploadFileFromUrl($uploadFromUrl);
return uploadFile($schema, $file);
}
return new FileUploadResult(
recordFile: File::fromArray($file), duplicateId: "", isDuplicate: false
);
}
/**
* @throws LucentException
*/
private static function uploadFileFromUrl(string $url): UploadedFile
{
$pathinfo = pathinfo($url);
$contents = file_get_contents($url);
if ($contents === false) {
throw new LucentException("Failed to upload file from url");
}
$file = '/tmp/' . $pathinfo['basename'];
file_put_contents($file, $contents);
return new UploadedFile($file, $pathinfo['basename']);
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace Lucent\File;
use Lucent\Record\File;
class FileUploadResult
{
public function __construct(
public ?File $recordFile,
public string $duplicateId,
public bool $isDuplicate,
)
{
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
namespace Lucent\File;
use Exception;
use Illuminate\Log\Logger;
use Intervention\Image\ImageManager;
use Lucent\Channel\ChannelService;
use Lucent\Record\QueryRecord;
class ImageService
{
private string $notFoundImage = "/not-found.jpg";
public function __construct(
public ImageManager $imageManager,
public ChannelService $channelService,
public Logger $logger
)
{
}
public function file(?QueryRecord $record, string $template = ""): string
{
if (empty($record)) {
return $this->notFoundImage;
}
$originalPath = $record->_file->path;
$templateUri = $this->findTemplate($originalPath, $template);
if ($templateUri === false) {
$templateUri = $this->createTemplate($originalPath, $template);
}
return $this->channelService->channel->filesUrl . "/" . $templateUri;
}
private function findTemplate(string $originalPath, string $template): string|false
{
$templateUri = "templates/" . $template . "/" . $originalPath;
$templateFilePath = public_path("storage/" . $templateUri);
if (file_exists($templateFilePath)) {
return $templateUri;
}
return false;
}
private function createTemplate(string $originalPath, string $template): string
{
$originalFilePath = public_path("storage/" . $originalPath);
$templateUri = "/templates/" . $template . "/" . $originalPath;
$templateFilePath = public_path("storage/" . $templateUri);
if (!file_exists($originalFilePath)) {
return $this->notFoundImage;
}
if (!file_exists(pathinfo($templateFilePath, PATHINFO_DIRNAME))) {
$this->make_dir(pathinfo($templateFilePath, PATHINFO_DIRNAME));
}
try {
$image = $this->imageManager->make($originalFilePath);
} catch (Exception $e) {
$this->logger->error($e->getMessage());
return $this->notFoundImage;
}
$image->filter(new $this->channelService->channel->imageFilters[$template]);
try {
$image->encode('webp', 75);
} catch (Exception $e) {
$this->logger->error($e->getMessage());
return $this->notFoundImage;
}
$image->save($templateFilePath);
return $templateUri;
}
private function make_dir(string $path): void
{
is_dir($path) || mkdir($path, 0777, true);
}
}
+133
View File
@@ -0,0 +1,133 @@
<?php
namespace Lucent\File;
use Exception;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\ImageManagerStatic;
use Lucent\LucentException;
use Lucent\Record\File as RecordFile;
use Lucent\Schema\Schema;
use Spatie\ImageOptimizer\OptimizerChainFactory;
/**
* @throws LucentException
*/
function uploadFile(Schema $schema, UploadedFile $file): FileUploadResult
{
$originalName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
$extension = pathinfo($file->getClientOriginalName(), PATHINFO_EXTENSION);
$originalFilename = $file->getClientOriginalName();
$filename = createFileName($originalName, $extension);
$mimetype = $file->getMimeType();
$optimizerChain = OptimizerChainFactory::create();
$optimizerChain->setTimeout(10)->optimize($file->getPathName());
$checksum = sha1_file($file);
$recordId = checkDuplicate($schema->name, $checksum, $file->getSize());
if (!empty($recordId)) {
return new FileUploadResult(
recordFile: null,
duplicateId: $recordId,
isDuplicate: true
);
}
$disk = loadDisk();
$path = $schema->path . "/" . $filename;
$res = $disk->put(
$path,
file_get_contents($file),
// 'public' // now managed by aws policy
);
if ($res === false) {
throw new LucentException("File $filename not uploaded");
}
createThumbnail($disk, $schema->path, $filename, $file);
list($width, $height) = isImage($mimetype) ? getimagesize($file) : [0, 0];
$recordFile = new RecordFile(
originalName: $originalFilename,
mime: $mimetype,
path: $path,
size: $file->getSize(),
width: $width,
height: $height,
checksum: $checksum
);
return new FileUploadResult(
recordFile: $recordFile,
duplicateId: "",
isDuplicate: false
);
}
function createFileName(string $originalName, string $extension): string
{
return Str::slug($originalName, '-') . '-' . uniqid() . '.' . $extension;
}
function isImage(string $mimetype): bool
{
$imageMimes = ['image/webp', 'image/gif', 'image/jpeg', 'image/png', 'image/tiff'];
return in_array($mimetype, $imageMimes);
}
function loadDisk(): Filesystem
{
return Storage::build([
'driver' => 'local',
// 'key' => config("filesystems.disks.s3.key"),
// 'secret' => config("filesystems.disks.s3.secret"),
// 'region' => config("filesystems.disks.s3.region"),
// 'bucket' => config("filesystems.disks.s3.bucket"),
// // 'url' => $schema->objectStorageUrl,
// 'endpoint' => $schema->objectStorageEndpoint,
'use_path_style_endpoint' => false,
'visibility' => 'public', // now managed by aws policy
'root' => storage_path('app/public'),
'throw' => true,
]);
}
function checkDuplicate(string $schemaName, string $checksum, int $filesize): string
{
$record = DB::table("records")
->where("_sys->schema", $schemaName)
->where("_file->checksum", $checksum)
->where("_file->size", $filesize)
->first();
return $record->id ?? "";
}
function createThumbnail(Filesystem $disk, string $schemaPath, string $filename, UploadedFile $file): void
{
try {
$image = ImageManagerStatic::make($file);
} catch (Exception $e) {
return;
}
$image->fit(300, 300);
try {
$image->encode('webp', 75);
$disk->put(
"thumbs/" . $schemaPath . "/" . $filename,
$image,
// 'public' // now managed by aws policy
);
} catch (Exception $e) {
}
}