848 lines
25 KiB
PHP
848 lines
25 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Enums\MediaExtension;
|
|
use App\Enums\MediaStatut;
|
|
use App\Events\MediaChangedLabel;
|
|
use App\Events\MediaCreated;
|
|
use App\Events\MediaDestroyed;
|
|
use App\Events\MediaUpdated;
|
|
use App\Lib\ToolboxHelper;
|
|
use App\Traits\Models\BindedToElasticSearch;
|
|
use App\Models\User;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Prunable;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Rennokki\QueryCache\Traits\QueryCacheable;
|
|
|
|
class Media extends Model
|
|
{
|
|
use BindedToElasticSearch;
|
|
use Prunable;
|
|
use QueryCacheable;
|
|
use SoftDeletes;
|
|
|
|
/**
|
|
* The timeout cache for this model
|
|
*
|
|
* @var integer
|
|
*/
|
|
protected $cacheFor = -1;
|
|
|
|
/**
|
|
* The cache driver to be used.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $cacheDriver = 'redis';
|
|
|
|
/**
|
|
* Is the model a duplicate of another (only true before we save it in database)
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $isDuplicate = false;
|
|
|
|
/**
|
|
* The relations to eager load on every query.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $with = [
|
|
'owner',
|
|
'tags',
|
|
'etiquette',
|
|
'articles',
|
|
'sujet',
|
|
'typeMedia',
|
|
'societes',
|
|
'marques'
|
|
];
|
|
|
|
/**
|
|
* The attributes that are mass assignable.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $fillable = [
|
|
// ! id est obligatoire ici pour Jobs/XmlArcadiaMediasIn
|
|
'id',
|
|
'libelle',
|
|
'type_vue_id',
|
|
'variante_id',
|
|
'copyright_id',
|
|
'etiquette_id',
|
|
'langue_id',
|
|
'commentaire',
|
|
'version',
|
|
'statut',
|
|
];
|
|
|
|
/**
|
|
* The attributes that should be cast.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $casts = [
|
|
'isDefault' => 'bool',
|
|
'isLocked' => 'bool',
|
|
'statut' => MediaStatut::class,
|
|
'extension' => MediaExtension::class
|
|
];
|
|
|
|
/**
|
|
* ES The elasticsearch settings.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $indexSettings = [
|
|
'analysis' => [
|
|
'char_filter' => [
|
|
'replace' => [
|
|
'type' => 'mapping',
|
|
'mappings' => [
|
|
'&=> and '
|
|
],
|
|
],
|
|
],
|
|
'filter' => [
|
|
'word_delimiter' => [
|
|
'type' => 'word_delimiter',
|
|
'split_on_numerics' => false,
|
|
'split_on_case_change' => true,
|
|
'generate_word_parts' => true,
|
|
'generate_number_parts' => true,
|
|
'catenate_all' => true,
|
|
'preserve_original' => true,
|
|
'catenate_numbers' => true,
|
|
]
|
|
],
|
|
'analyzer' => [
|
|
'default' => [
|
|
'type' => 'custom',
|
|
'char_filter' => [
|
|
'html_strip',
|
|
'replace',
|
|
],
|
|
'tokenizer' => 'whitespace',
|
|
'filter' => [
|
|
'lowercase',
|
|
'word_delimiter',
|
|
],
|
|
],
|
|
],
|
|
'normalizer' => [
|
|
'my_normalizer' => [
|
|
'type' => 'custom',
|
|
'char_filter' => [],
|
|
'filter' => [
|
|
'lowercase'
|
|
]
|
|
]
|
|
]
|
|
],
|
|
];
|
|
|
|
/**
|
|
* ES Mapping Properties
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $mappingProperties = array(
|
|
'libelle' => array(
|
|
'type' => 'text',
|
|
'analyzer' => 'default',
|
|
'fields' => [
|
|
'keyword' => [
|
|
'type' => 'keyword',
|
|
'normalizer' => 'my_normalizer'
|
|
]
|
|
],
|
|
'fielddata' => true
|
|
),
|
|
'commentaire' => array(
|
|
'type' => 'text',
|
|
'analyzer' => 'default',
|
|
'fields' => [
|
|
'keyword' => [
|
|
'type' => 'keyword',
|
|
'normalizer' => 'my_normalizer'
|
|
]
|
|
],
|
|
'fielddata' => true
|
|
),
|
|
'created_at' => [
|
|
'type' => 'date',
|
|
"format" => "yyyy-MM-dd HH:mm:ss"
|
|
],
|
|
'updated_at' => [
|
|
'type' => 'date',
|
|
"format" => "yyyy-MM-dd HH:mm:ss"
|
|
],
|
|
'version' => [
|
|
'type' => 'text',
|
|
'fielddata' => true
|
|
],
|
|
'arcadia_id' => [
|
|
'type' => 'text',
|
|
'analyzer' => 'standard'
|
|
],
|
|
'articles.noArt' => [
|
|
'type' => 'text',
|
|
'analyzer' => 'standard'
|
|
],
|
|
'articles.libCcial' => [
|
|
'type' => 'text',
|
|
'analyzer' => 'default',
|
|
'fields' => [
|
|
'keyword' => [
|
|
'type' => 'keyword',
|
|
'normalizer' => 'my_normalizer'
|
|
]
|
|
],
|
|
'fielddata' => true
|
|
]
|
|
);
|
|
|
|
/**
|
|
* Perform any actions required after the model boots.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected static function booted()
|
|
{
|
|
static::created(function (self $model) {
|
|
// * Flush Eloquent cache.
|
|
self::flushQueryCache();
|
|
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
MediaCreated::dispatch($user, $model);
|
|
|
|
if (empty($model->isDuplicate)) {
|
|
/** @throws \RuntimeException */
|
|
$model->addToElasticSearch();
|
|
}
|
|
});
|
|
static::updating(function (self $model) {
|
|
if ($model->statut === MediaStatut::brouillon and $model->arcadia_id) {
|
|
throw ValidationException::withMessages([
|
|
'statut' => trans('Impossible de changer le statut en brouillon quand la fiche est liée à arcadia')
|
|
]);
|
|
}
|
|
});
|
|
static::updated(function (self $model) {
|
|
// * Flush Eloquent cache.
|
|
self::flushQueryCache();
|
|
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
// * If update is not running from console, we prevent soft delete before trigerring update event
|
|
if ($user and !\array_key_exists('deleted_at', $model->getChanges())) {
|
|
MediaUpdated::dispatch($user, $model);
|
|
}
|
|
|
|
if ($model->getRawOriginal('etiquette_id') != $model->etiquette_id) {
|
|
/** @var \App\Models\Etiquette|null */
|
|
$oldLabel = Etiquette::where('etiquette_id', $model->getRawOriginal('etiquette_id'))->first();
|
|
/** @var \App\Models\Etiquette|null */
|
|
$newLabel = Etiquette::where('etiquette_id', $model->etiquette_id)->first();
|
|
MediaChangedLabel::dispatch($user, $model, $oldLabel, $newLabel);
|
|
}
|
|
|
|
/** @throws \RuntimeException */
|
|
$model->addToElasticSearch();
|
|
});
|
|
static::deleted(function (self $model) {
|
|
// * Flush Eloquent cache.
|
|
self::flushQueryCache();
|
|
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
MediaDestroyed::dispatch($user, $model);
|
|
|
|
/** @throws \RuntimeException */
|
|
$model->removeFromElasticSearch();
|
|
});
|
|
}
|
|
|
|
// * Laravel Behaviors
|
|
|
|
/**
|
|
* Get the route key for the model.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getRouteKeyName()
|
|
{
|
|
return 'uid';
|
|
}
|
|
|
|
/**
|
|
* Set the base cache tags that will be present
|
|
* on all queries.
|
|
*
|
|
* ! This is used to flush caching
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function getCacheBaseTags(): array
|
|
{
|
|
return [
|
|
'dam_media',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get the prunable model query.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Builder
|
|
*/
|
|
public function prunable()
|
|
{
|
|
return static::query();
|
|
}
|
|
|
|
/**
|
|
* Prepare the model for pruning.
|
|
*
|
|
* @return void
|
|
* @throws \RuntimeException If pruning the model fails.
|
|
*/
|
|
protected function pruning()
|
|
{
|
|
$storage = Storage::disk('media');
|
|
if ($storage->exists($this->relative_path) and !$storage->delete($this->relative_path)) {
|
|
throw new \RuntimeException("Could not delete $this->relative_path from storage.");
|
|
}
|
|
if ($storage->exists($this->preview_relative_path) and !$storage->delete($this->preview_relative_path)) {
|
|
throw new \RuntimeException("Could not delete $this->preview_relative_path from storage.");
|
|
}
|
|
if ($storage->exists($this->thumb_relative_path) and !$storage->delete($this->thumb_relative_path)) {
|
|
throw new \RuntimeException("Could not delete $this->thumb_relative_path from storage.");
|
|
}
|
|
}
|
|
|
|
// * RELATIONSHIPS
|
|
|
|
/**
|
|
* BelongsTo dossier relation
|
|
* Get the dossier that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function dossier()
|
|
{
|
|
return $this->belongsTo(Dossier::class, 'dossier_id');
|
|
}
|
|
|
|
/**
|
|
* BelongsTo sujet relation
|
|
* Get the sujet that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function sujet()
|
|
{
|
|
return $this->belongsTo(Sujet::class, 'sujet_id');
|
|
}
|
|
|
|
/**
|
|
* BelongsTo typeMedia relation
|
|
* Get the typeMedia that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function typeMedia()
|
|
{
|
|
return $this->belongsTo(TypeMedia::class, 'type_media_id');
|
|
}
|
|
|
|
/**
|
|
* BelongsTo typevue relation
|
|
* Get the typevue that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function typevue()
|
|
{
|
|
return $this->belongsTo(TypeVue::class);
|
|
}
|
|
|
|
/**
|
|
* BelongsTo langue relation
|
|
* Get the langue that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function langue()
|
|
{
|
|
return $this->belongsTo(Langue::class, 'langue_id');
|
|
}
|
|
|
|
/**
|
|
* BelongsTo copyright relation
|
|
* Get the copyright that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function copyright()
|
|
{
|
|
return $this->belongsTo(Copyright::class, 'copyright_id');
|
|
}
|
|
|
|
/**
|
|
* BelongsTo etiquette relation
|
|
* Get the etiquette that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function etiquette()
|
|
{
|
|
return $this->belongsTo(Etiquette::class, 'etiquette_id');
|
|
}
|
|
|
|
/**
|
|
* BelongsToMany tags relation
|
|
* The tags that belong to the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function tags()
|
|
{
|
|
return $this->belongsToMany(Tag::class, 'media_tag');
|
|
}
|
|
|
|
/**
|
|
* BelongsToMany articles relation
|
|
* The articles that belong to the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function articles()
|
|
{
|
|
return $this->belongsToMany(Article::class, 'media_article');
|
|
}
|
|
|
|
/**
|
|
* BelongsToMany societes relation
|
|
* The societes that belong to the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function societes()
|
|
{
|
|
return $this->belongsToMany(Societe::class, 'media_societe');
|
|
}
|
|
|
|
/**
|
|
* BelongsToMany marques relation
|
|
* The marques that belong to the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function marques()
|
|
{
|
|
return $this->belongsToMany(Marque::class, 'media_marque', 'media_id', 'marque_id');
|
|
}
|
|
|
|
/**
|
|
* BelongsTo user relation
|
|
* Get the user that owns the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function owner()
|
|
{
|
|
return $this->belongsTo(User::class, 'created_by');
|
|
}
|
|
|
|
/**
|
|
* HasMany historiques relation
|
|
* Get the historiques for the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function historiques()
|
|
{
|
|
return $this->hasMany(Historique::class);
|
|
}
|
|
|
|
/**
|
|
* BelongsToMany paniers relation
|
|
* The paniers that belong to the media.
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function paniers()
|
|
{
|
|
return $this->belongsToMany(Panier::class, 'panier_media');
|
|
}
|
|
|
|
// * METHODS
|
|
|
|
/**
|
|
* Get basename
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getBasenameAttribute(): string
|
|
{
|
|
return "{$this->uid}.{$this->extension->value}";
|
|
}
|
|
|
|
/**
|
|
* Get preview_basename
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPreviewBasenameAttribute(): string
|
|
{
|
|
$extension = match ($this->extension) {
|
|
MediaExtension::pdf, MediaExtension::ai, MediaExtension::psd => MediaExtension::png,
|
|
default => $this->extension,
|
|
};
|
|
return "{$this->uid}_preview.{$extension->value}";
|
|
}
|
|
|
|
/**
|
|
* Get thumb_basename
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getThumbBasenameAttribute(): string
|
|
{
|
|
$extension = match ($this->extension) {
|
|
MediaExtension::pdf, MediaExtension::ai, MediaExtension::psd => MediaExtension::png,
|
|
default => $this->extension,
|
|
};
|
|
return "{$this->uid}_thumb.{$extension->value}";
|
|
}
|
|
|
|
/**
|
|
* Get relative_path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getRelativePathAttribute(): string
|
|
{
|
|
return "{$this->folder}/{$this->basename}";
|
|
}
|
|
|
|
/**
|
|
* Get preview_relative_path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPreviewRelativePathAttribute(): string
|
|
{
|
|
return "{$this->folder}/{$this->preview_basename}";
|
|
}
|
|
|
|
/**
|
|
* Get thumb_relative_path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getThumbRelativePathAttribute(): string
|
|
{
|
|
return "{$this->folder}/{$this->thumb_basename}";
|
|
}
|
|
|
|
/**
|
|
* Get full_path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getFullPathAttribute(): string
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
return $storage->path($this->relative_path);
|
|
}
|
|
|
|
/**
|
|
* Get preview_full_path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getPreviewFullPathAttribute(): string
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
return $storage->path($this->preview_relative_path);
|
|
}
|
|
|
|
/**
|
|
* Get thumb_full_path
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getThumbFullPathAttribute(): string
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
return $storage->path($this->thumb_relative_path);
|
|
}
|
|
|
|
/**
|
|
* Delete files on path
|
|
* @return void
|
|
* @throws \RuntimeException If the media does not have a subject.
|
|
*/
|
|
public function deleteFilesOnAllPath()
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
$storage->delete($this->relative_path);
|
|
$storage->delete($this->thumb_relative_path);
|
|
$storage->delete($this->preview_relative_path);
|
|
if (!$this->sujet) {
|
|
throw new \RuntimeException('This medias does not have any subject wich is forbidden');
|
|
}
|
|
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
$this->sujet->formats->map(function (Format $format) use ($storage) {
|
|
$filePath = "{$this->folder}/{$this->uid}_{$format->libelle}.{$format->extension}";
|
|
if ($storage->exists($filePath)) {
|
|
$storage->delete($filePath);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Add this media into Elastic Search
|
|
*
|
|
* @return void
|
|
* @throws \RuntimeException If adding to ES failed.
|
|
*/
|
|
public function addToElasticSearch()
|
|
{
|
|
$this->removeFromElasticSearch();
|
|
try {
|
|
$this->refresh();
|
|
$this->addToIndex();
|
|
} catch (\Exception $e) {
|
|
report($e);
|
|
throw new \RuntimeException("Failed to add media '$this->arcadia_id' to ES", 0, $e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove this media from ElasticSearch
|
|
*
|
|
* @return void
|
|
* @throws \RuntimeException If someting goes wrong.
|
|
*/
|
|
public function removeFromElasticSearch()
|
|
{
|
|
$esExist = self::searchByQuery(['match' => ['arcadia_id' => strval($this->arcadia_id)]]);
|
|
|
|
// * Remove all from elastic if exists
|
|
if ($esExist->totalHits() > 0) {
|
|
try {
|
|
$this->removeFromIndex();
|
|
} catch (\Exception $e) {
|
|
report($e);
|
|
throw new \RuntimeException("Failed to add media '$this->arcadia_id' to ES", 0, $e);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create thumbnail image for a Media Subject on very of its formats.
|
|
* - Creation des vignettes en lien avec le sujet du média
|
|
*
|
|
* @return void
|
|
* @throws \ImagickException On errors.
|
|
* @throws \RuntimeException If media file is missing.
|
|
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
|
*/
|
|
public function createSubjectThumbnails()
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
if (!$storage->exists($this->relative_path)) {
|
|
throw new \RuntimeException("Missing Media file at path '$this->relative_full_path'");
|
|
}
|
|
|
|
$im = new \Imagick();
|
|
$im->readImageBlob(
|
|
$storage->get($this->relative_path),
|
|
$this->basename
|
|
);
|
|
$im->setImageBackgroundColor('#ffffff');
|
|
$im->setImageAlphaChannel(\Imagick::ALPHACHANNEL_REMOVE);
|
|
$im->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
|
|
$im->stripImage();
|
|
if (in_array($this->extension, [MediaExtension::pdf, MediaExtension::ai, MediaExtension::psd])) {
|
|
$im->setIteratorIndex(0);
|
|
}
|
|
|
|
/** @var \Illuminate\Support\Collection<\App\Models\Format> $formats */
|
|
$formats = optional($this->sujet)->formats ?? collect();
|
|
|
|
$formats->map(function (Format $format) use ($storage, $im) {
|
|
$targetWidth = \floatval($format->largeur);
|
|
$targetHeight = \floatval($format->hauteur) == 0 ?
|
|
\floatval(floor(($this->hauteur * $format->largeur) / $this->largeur)) :
|
|
\floatval($format->hauteur);
|
|
|
|
$im->setImageFormat($format->extension);
|
|
if ($this->largeur >= $targetWidth || $this->hauteur >= $targetHeight) {
|
|
$im->thumbnailImage($targetWidth, $targetHeight, true);
|
|
}
|
|
$storage->put(
|
|
"{$this->folder}/{$this->uid}_{$format->libelle}.{$format->extension}",
|
|
$im->getImageBlob()
|
|
);
|
|
});
|
|
$im->destroy();
|
|
unset($im);
|
|
}
|
|
|
|
/**
|
|
* Create thumbnail image for a Media.
|
|
* - Creation des vignettes de base
|
|
*
|
|
* @return void
|
|
* @throws \ImagickException On errors.
|
|
* @throws \RuntimeException If media file is missing.
|
|
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
|
*/
|
|
public function createThumbnail()
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
if (!$storage->exists($this->relative_path)) {
|
|
throw new \RuntimeException("Missing Media file at path '$this->relative_full_path'");
|
|
}
|
|
|
|
$im = new \Imagick();
|
|
$im->readImageBlob(
|
|
$storage->get($this->relative_path),
|
|
$this->basename
|
|
);
|
|
|
|
if (in_array($this->extension, [MediaExtension::pdf, MediaExtension::ai, MediaExtension::psd])) {
|
|
$im->setIteratorIndex(0);
|
|
}
|
|
|
|
/*
|
|
Handle CMJN - DOESN'T WORK
|
|
if ($im->getImageColorspace() === \Imagick::COLORSPACE_CMYK){
|
|
$im->transformImageColorspace(\Imagick::COLORSPACE_RGB);
|
|
}
|
|
*/
|
|
|
|
// * create preview
|
|
/** @var \App\Models\Format $format */
|
|
$format = Format::withoutGlobalScope('App\Scopes\SystemScope')
|
|
->where('libelle', '=', 'preview')->firstOrFail();
|
|
|
|
if ($this->extension == MediaExtension::gif) {
|
|
if ($this->largeur >= $format->largeur || $this->hauteur >= $format->hauteur || $this->largeur == "") {
|
|
$im = $im->coalesceImages();
|
|
foreach ($im as $frame) {
|
|
$frame->thumbnailImage($format->largeur, $format->hauteur);
|
|
$frame->setImagePage($format->largeur, $format->hauteur, 0, 0);
|
|
}
|
|
$im = $im->deconstructImages();
|
|
}
|
|
$im->setImageFormat(MediaExtension::gif);
|
|
$storage->put(
|
|
$this->preview_relative_path,
|
|
$im->getImagesBlob()
|
|
);
|
|
} else {
|
|
$im->setImageFormat(\pathinfo($this->preview_relative_path, \PATHINFO_EXTENSION));
|
|
if ($this->largeur >= $format->largeur || $this->hauteur >= $format->hauteur || $this->largeur == "") {
|
|
$im->thumbnailImage($format->largeur, $format->hauteur, true);
|
|
}
|
|
$storage->put(
|
|
$this->preview_relative_path,
|
|
$im->getImageBlob()
|
|
);
|
|
} //end if
|
|
|
|
// * create thumb
|
|
/** @var \App\Models\Format $format */
|
|
$format = Format::withoutGlobalScope('App\Scopes\SystemScope')
|
|
->where('libelle', '=', 'thumb')->firstOrFail();
|
|
if ($this->extension != MediaExtension::png) {
|
|
$im->setImageBackgroundColor('#ffffff');
|
|
$im->setImageAlphaChannel(\Imagick::ALPHACHANNEL_REMOVE);
|
|
$im->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
|
|
$im->stripImage();
|
|
}
|
|
$im->thumbnailImage($format->largeur, $format->hauteur, true);
|
|
$storage->put(
|
|
$this->thumb_relative_path,
|
|
$im->getImageBlob()
|
|
);
|
|
$im->destroy();
|
|
unset($im);
|
|
}
|
|
|
|
/**
|
|
* Renvoi le chemin attendu d'un média selon le format demandé
|
|
*
|
|
* @param \App\Models\Format $format
|
|
* @return string
|
|
* @throws \RuntimeException If Format is not handled.
|
|
*/
|
|
public function getPath(Format $format): string
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
// * format spécifique
|
|
if (!$format->system) {
|
|
if (in_array($this->extension, ['gif', 'jpeg', 'jpg', 'png', 'pdf', 'ai', 'psd'])) {
|
|
return $storage->path("/{$this->folder}/{$this->uid}_{$format->libelle}.{$format->extension->value}");
|
|
}
|
|
return $storage->path($this->relative_path);
|
|
}
|
|
// * format système (thumb et preview)
|
|
if ($format->system) {
|
|
if (in_array($this->extension, ['gif', 'jpeg', 'jpg', 'png'])) {
|
|
// * Gestion du cas de format qui fixe l'extension.
|
|
$file_extension = $format->extension != '' ? $format->extension : $this->extension;
|
|
return $storage->path("/{$this->folder}/{$this->uid}_{$format->libelle}.{$file_extension}");
|
|
} elseif (in_array($this->extension, ['pdf', 'ai', 'psd'])) {
|
|
return $storage->path("/{$this->folder}/{$this->uid}_{$format->libelle}.png");
|
|
}
|
|
return $storage->path("/{$this->folder}/{$this->uid}.{$this->extension->value}");
|
|
}
|
|
throw new \RuntimeException("Unhandled Format $format->id $format->libelle");
|
|
}
|
|
|
|
/**
|
|
* Convert the model instance to an array.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function toArray()
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
return array_merge(parent::toArray(), [
|
|
'size' => ToolboxHelper::formatBytes($this->taille),
|
|
'url' => $storage->url($this->relative_path),
|
|
'preview_url' => $storage->url($this->preview_relative_path),
|
|
'thumb_url' => $storage->url($this->thumb_relative_path),
|
|
'jpeg_url' => $storage->url($this->jpeg_relative_path),
|
|
'created_at' => $this->created_at->formatLocalized('%Y-%m-%d %H:%M:%S'),
|
|
'updated_at' => $this->updated_at->formatLocalized('%Y-%m-%d %H:%M:%S')
|
|
]);
|
|
}
|
|
}
|