File: /home/xedaptot/ai.naniguide.com/app/Model/Asset.php
<?php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use App\Library\Traits\HasUid;
use App\Model\Customer;
use Illuminate\Support\Str;
use App\Library\Storage\StoragePathResolver;
use Symfony\Component\HttpFoundation\File\File;
use App\Library\Storage\StorableInterface;
class Asset extends Model implements StorableInterface
{
use HasUid;
public const VISIBILITY_PRIVATE = 'private';
public const VISIBILITY_PUBLIC = 'public';
public const TYPE_MEDIA = 'media';
public function customer()
{
return $this->belongsTo(Customer::class);
}
protected static function booted()
{
// Automatically generate friendly_name before creating the asset
static::creating(function (Asset $asset) {
if (!$asset->filename) {
$asset->generateUniqueFilename($asset->original_name);
}
});
}
public static function makeMedia(File $file)
{
$media = new static();
$media->original_name = ($file instanceof \Illuminate\Http\UploadedFile) ? $file->getClientOriginalName() : $file->getFilename();
$media->size = $file->getSize();
$media->mime_type = $file->getMimeType();
$media->type = static::TYPE_MEDIA;
$media->visibility = static::VISIBILITY_PUBLIC;
return $media;
}
public function forCustomer(Customer $customer)
{
if (!is_null($this->path)) {
throw new \Exception("path is already set");
}
$this->customer()->associate($customer);
$this->path = app(StoragePathResolver::class)->mediaPath($customer);
return $this;
}
public function forApplication()
{
if (!is_null($this->customer_id) || !is_null($this->path)) {
throw new \Exception("Already associated with a customer OR path is already set");
}
$this->path = app(StoragePathResolver::class)->applicationMediaPath();
return $this;
}
/**
* Generate a Unix/S3 friendly version of a file name.
*/
public function generateFriendlyName(string $original)
{
$extension = pathinfo($original, PATHINFO_EXTENSION);
$name = pathinfo($original, PATHINFO_FILENAME);
$friendly = Str::slug($name);
return $friendly . ($extension ? '.' . strtolower($extension) : '');
}
protected function generateUniqueFilename($original)
{
$this->filename = $this->generateFriendlyName($original);
$extension = pathinfo($this->filename, PATHINFO_EXTENSION);
$name = pathinfo($this->filename, PATHINFO_FILENAME);
$counter = 1;
// Loop until a unique name is found
while ($this->fileExists()) {
$this->filename = "{$name}-{$counter}" . ($extension ? ".{$extension}" : '');
$counter++;
}
}
// Path does not include filename
public function getPath(): string
{
return $this->path ?? '';
}
public function getFullPath(): string
{
return join_paths($this->path, $this->filename);
}
public function getFilename(): string
{
return $this->filename;
}
public function store(File $file)
{
$publicUrl = $this->getStorage()->store($file, $this);
if ($publicUrl) {
$this->public_url = $publicUrl;
$this->save();
}
}
// @important: although every asset has a public URL, it might be either public or private
// See the AssetController@show method which evaluate the asset->visibility attribute before returning
public function getUrl()
{
return route('public_media', ['uid' => $this->uid, 'filename' => $this->getFilename()]);
}
public function isPublic()
{
return $this->visibility == static::VISIBILITY_PUBLIC;
}
public function getFileContent()
{
return $this->getStorage()->getFileContent($this);
}
public function fileExists()
{
return $this->getStorage()->fileExists($this);
}
public function remove()
{
$this->getStorage()->delete($this);
$this->delete();
}
public function belongsToCustomer()
{
return !is_null($this->customer);
}
public function getStorage()
{
return app(\App\Library\Storage\StorageInterface::class);
}
}