web/app/Http/Livewire/Develop/Create.php

186 lines
6.1 KiB
PHP

<?php
namespace App\Http\Livewire\Develop;
use App\Enums\AssetType;
use App\Models\Asset;
use App\Helpers\Cdn;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Storage;
use Livewire\Component;
use Livewire\TemporaryUploadedFile;
use Livewire\WithFileUploads;
use claviska\SimpleImage;
class Create extends Component
{
use WithFileUploads;
/**
* @var AssetType
*/
public $selected_type;
/**
* @var TemporaryUploadedFile
*/
public $asset_file;
/**
* @var string
*/
public $asset_name;
public function __construct()
{
abort_unless(Auth::check(), 401);
}
public function mount()
{
abort_unless($this->selected_type->isDevelopCreatable(), 404);
}
/**
* @return array
*/
protected function rules(): array
{
return [
'asset_name' => ['required', 'min:3', 'max:50'],
'asset_file' => ['required', ... $this->selected_type->rules()]
];
}
public function upload()
{
$this->validate();
if (RateLimiter::tooManyAttempts('create-asset:' . Auth::user()->id, 1))
{
$wait = RateLimiter::availableIn('create-asset:' . Auth::user()->id);
$this->dispatchBrowserEvent('error', __('Please wait :time before creating a new :asset_type.', ['time' => seconds2human($wait), 'asset_type' => $this->selected_type->fullname()]));
return;
}
// static thumbnail processing
if (in_array($this->selected_type, [AssetType::TShirt, AssetType::Decal]))
{
try
{
$image = new SimpleImage($this->asset_file->getRealPath());
}
catch(\Exception $exception)
{
$this->addError('asset_file', __('Failed to process image, it might be corrupted?'));
return;
}
if ($this->selected_type == AssetType::TShirt)
{
$imageData = new SimpleImage();
$imageData->fromNew($image->getWidth(), $image->getWidth());
$assetThumbnail = new SimpleImage(resource_path('img/tshirt-template.png'));
$assetThumbnail->resize(420, 420);
// fit the image in a 1:1 canvas, 420x420 max
$imageData->resize($image->getWidth());
$imageData->overlay($image, 'top');
if ($image->getWidth() > 420) $imageData->resize(420, 420);
// image thumbnail must be 420x420
$imageThumbnail = clone $imageData;
$imageThumbnail->resize(420, 420);
// asset thumbnail is image thumbnail overlayed onto t-shirt template
$assetThumbnailOverlay = clone $imageThumbnail;
$assetThumbnailOverlay->resize(250, 250);
$assetThumbnail->overlay($assetThumbnailOverlay, 'center', 1);
}
else if ($this->selected_type == AssetType::Decal)
{
// image retains original ratio, original size is retained if under 420x420
$imageData = clone $image;
$imageData->bestFit(420, 420);
// image and asset thumbnails are the image resized to 420x420
$imageThumbnail = clone $image;
$imageThumbnail->resize(420, 420);
$assetThumbnail = clone $imageThumbnail;
}
$imageData = $imageData->toString();
$imageThumbnail = $imageThumbnail->toString();
$assetThumbnail = $assetThumbnail->toString();
RateLimiter::hit('create-asset:' . Auth::user()->id, 30);
$imageAsset = Asset::create([
'name' => $this->asset_name,
'description' => $this->selected_type->fullname() . ' ' . AssetType::Image->name,
'type' => AssetType::Image->value,
'creator_id' => Auth::user()->id
]);
$imageAsset->initialize($imageData, $imageThumbnail);
$document = simplexml_load_file(resource_path(sprintf('xml/%s.xml', $this->selected_type->name)));
$document->xpath("//url")[0][0] = sprintf('%s/asset/?id=%d', config('app.url'), $imageAsset->id);
// we need to remove the first line that contains the XML declaration
$assetData = $document->asXML();
$assetData = preg_replace('/^.+\n/', '', $assetData);
}
else
{
if ($this->selected_type == AssetType::Audio)
{
$assetThumbnail = file_get_contents(resource_path('img/audio.png'));
$assetData = $this->asset_file->get();
}
if ($this->selected_type == AssetType::Animation)
{
$assetThumbnail = file_get_contents(resource_path('img/animation.png'));
$assetData = $this->asset_file->get();
}
RateLimiter::hit('create-asset:' . Auth::user()->id, 30);
}
$asset = Asset::create([
'name' => $this->asset_name,
'description' => $this->selected_type->fullname(),
'type' => $this->selected_type->value,
'image_id' => $imageAsset->id ?? null,
'creator_id' => Auth::user()->id
]);
$asset->initialize($assetData, $assetThumbnail);
if (in_array($this->selected_type, [AssetType::TShirt, AssetType::Decal]))
{
Cdn::save($imageData);
Cdn::save($imageThumbnail, 'png');
}
Cdn::save($assetData);
Cdn::save($assetThumbnail, 'png');
$this->dispatchBrowserEvent('success', __('Successfully created :asset_type.', ["asset_type" => __($this->selected_type->fullname())]));
$this->emitTo('develop.assets', 'assetCreated');
}
public function updated($property)
{
$this->validateOnly($property);
}
public function render()
{
return view('livewire.develop.create')->with('selected_type', $this->selected_type);
}
}