1121 lines
39 KiB
PHP
1121 lines
39 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Enums\MediaExtension;
|
|
use App\Enums\MediaStatut;
|
|
use App\Events\MediaLinkWithArcadia;
|
|
use App\Events\MediaMoved;
|
|
use App\Events\MediaSearched;
|
|
use App\Http\Requests\Bo\Ajax\ApplyStickerRequest;
|
|
use App\Http\Requests\Bo\Ajax\CheckRefKeyRequest;
|
|
use App\Http\Requests\Bo\Ajax\DeleteMediaRequest;
|
|
use App\Http\Requests\Bo\Ajax\MoveMediaRequest;
|
|
use App\Http\Requests\Bo\Ajax\UpdateMediaRequest;
|
|
use App\Http\Requests\Bo\DownloadMediaPublicRequest;
|
|
use App\Http\Requests\Bo\DownloadMediaRequest;
|
|
use App\Http\Requests\Bo\LoadMediaRequest;
|
|
use App\Http\Requests\Bo\ShowInterfaceRequest;
|
|
use App\Lib\ArcadiaLinkUtilities;
|
|
use App\Lib\ToolboxHelper;
|
|
use App\Models\Article;
|
|
use App\Models\Copyright;
|
|
use App\Models\Dossier;
|
|
use App\Models\Etiquette;
|
|
use App\Models\Format;
|
|
use App\Models\Historique;
|
|
use App\Models\Langue;
|
|
use App\Models\Marque;
|
|
use App\Models\Media;
|
|
use App\Models\Recherche;
|
|
use App\Models\Setting;
|
|
use App\Models\Societe;
|
|
use App\Models\Sujet;
|
|
use App\Models\Tag;
|
|
use App\Models\TypeMedia;
|
|
use App\Traits\Http\HandlesMedia;
|
|
use Illuminate\Contracts\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\File;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
|
|
class MediaController extends Controller
|
|
{
|
|
use HandlesMedia;
|
|
|
|
/**
|
|
* Display a listing of the resource.
|
|
*
|
|
* @param \App\Http\Requests\Bo\ShowInterfaceRequest $request
|
|
* @return \Illuminate\Http\Response
|
|
*/
|
|
public function showInterface(ShowInterfaceRequest $request)
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$filters = (object)[];
|
|
|
|
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Sujet> */
|
|
$sujets = $user->sujets;
|
|
// ! Has to flush Media cache before querying basket with media list
|
|
Media::flushQueryCache();
|
|
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Panier> */
|
|
$paniers = $user->paniersOwner;
|
|
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Societe> */
|
|
$societes = Societe::orderBy('libelle')->get();
|
|
|
|
$typesmedia = TypeMedia::all();
|
|
$langues = Langue::all();
|
|
$copyrights = Copyright::all();
|
|
$etiquettes = Etiquette::all();
|
|
$marques = Marque::all();
|
|
|
|
/** @var int|null */
|
|
$dossier_id = $request->d;
|
|
/** @var \App\Models\Sujet|null */
|
|
$sujet = Sujet::where('codeSujet', $request->s)->first();
|
|
/** @var string */
|
|
$textSearch = \strval($request->t);
|
|
/** @var \App\Models\Recherche|null */
|
|
$recherche = Recherche::where('id', $request->r)->first();
|
|
|
|
// * Recherche type texte
|
|
if (\strlen($textSearch) and $sujet) {
|
|
// * On créé un object filtre.
|
|
$filters = (object)[
|
|
"search" => [
|
|
'type' => "search",
|
|
'legend' => "Recherche : ",
|
|
'value' => $textSearch,
|
|
'libelle' => [$textSearch],
|
|
]
|
|
];
|
|
MediaSearched::dispatch(
|
|
$user,
|
|
$sujet,
|
|
$textSearch,
|
|
$filters,
|
|
intval(Dossier::where('id', $dossier_id)->exists() ?
|
|
$dossier_id : (in_array($dossier_id, [-1, 0]) ? $dossier_id : -1))
|
|
);
|
|
}
|
|
|
|
// * Recherche favorite
|
|
if ($recherche) {
|
|
/** @var object */
|
|
$filters = $recherche->filters;
|
|
/** @var \App\Models\Sujet */
|
|
$sujet = $recherche->sujet;
|
|
$dossier_id = $recherche->dossier_id;
|
|
$textSearch = $recherche->libelle;
|
|
}
|
|
|
|
return view('media_manager')->with([
|
|
'sujets' => $sujets,
|
|
'typesmedia' => $typesmedia,
|
|
'langues' => $langues,
|
|
'copyrights' => $copyrights,
|
|
'etiquettes' => $etiquettes,
|
|
'societes' => $societes,
|
|
'marques' => $marques,
|
|
'currentFolder' => Dossier::query()->where('id', $dossier_id)->first() ?? $dossier_id,
|
|
'currentSujet' => optional($sujet)->codeSujet ?? \optional($sujets->first())->codeSujet,
|
|
'currentFilters' => json_encode($filters),
|
|
'paniers' => $paniers,
|
|
'textSearch' => $textSearch
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Show media
|
|
*
|
|
* @param Media $media
|
|
* @return \Illuminate\Http\RedirectResponse
|
|
*/
|
|
public function show(Media $media): RedirectResponse
|
|
{
|
|
return redirect()->route('media_manager')->with('autoOpen', $media);
|
|
}
|
|
|
|
/**
|
|
* Chargement des médias
|
|
*
|
|
* @param \App\Http\Requests\Bo\LoadMediaRequest $request
|
|
* @param \App\Models\Sujet $sujet
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function loadMedia(LoadMediaRequest $request, Sujet $sujet): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
/** @var \App\Models\Dossier|null */
|
|
$dossier = Dossier::query()
|
|
->with('dossierParent')
|
|
->where('id', $request->input('folder'))
|
|
->first();
|
|
|
|
$response = [];
|
|
$filters = (object)collect($request->input('filters'))->all();
|
|
|
|
/** @var boolean Est un dossier Dépot ? */
|
|
$isDepot = !empty($dossier) && (\optional($dossier->dossierParent)->id === 1 || $dossier->id === 1);
|
|
|
|
/**
|
|
* Elastic Search must conditions
|
|
* @var array
|
|
*/
|
|
$esMust = [];
|
|
/**
|
|
* Elastic Search must not conditions
|
|
* @var array
|
|
*/
|
|
$esMustNot = [];
|
|
/**
|
|
* Elastic Search should conditions
|
|
* @var array
|
|
*/
|
|
$esShould = [];
|
|
/**
|
|
* Elastic Search filters conditions
|
|
* @var array
|
|
*/
|
|
$esFilters = [];
|
|
|
|
/** @var string 'created_at' or 'updated_at' or 'version' or 'libelle.keyword' */
|
|
$orderField = collect($filters)->reduce(function (string|null $carry, array $item) {
|
|
$item = collect($item);
|
|
return $carry ?? ($item->get('order') ? $item->get('value') : null);
|
|
}) ?? 'created_at';
|
|
|
|
/** @var string 'asc' or 'desc' */
|
|
$order = collect($filters)->reduce(function (string|null $carry, array $item) {
|
|
return $carry ?? collect($item)->get('order');
|
|
}) ?? 'desc';
|
|
|
|
/** @var string|null */
|
|
$searchText = collect($filters)->reduce(function (string|null $carry, array $item) {
|
|
$item = collect($item);
|
|
return $carry ?? ($item->get('type') === 'search' ? $item->get('value') : null);
|
|
});
|
|
|
|
$this->esFolderSearch(
|
|
$esMust,
|
|
$esMustNot,
|
|
$esShould,
|
|
$request,
|
|
$dossier,
|
|
$sujet,
|
|
$isDepot
|
|
);
|
|
$this->esTextSearch($esMust, $request, $sujet, $searchText);
|
|
$this->esFilters($esMust, $request);
|
|
|
|
$query = \array_undot([
|
|
'bool.must' => $esMust,
|
|
'bool.must_not' => $esMustNot,
|
|
'bool.should' => $esShould,
|
|
'bool.filter' => $esFilters,
|
|
]);
|
|
$sort = [[$orderField => ['order' => $order]]];
|
|
|
|
Arr::set($response, 'data', Media::searchByQuery(
|
|
$query,
|
|
null,
|
|
null,
|
|
intval($request->post('limit', 50)),
|
|
intval($request->post('offset', 0)),
|
|
$sort
|
|
));
|
|
|
|
Arr::set($response, 'draggable', $user->hasRole([
|
|
config('roles.const.ADMIN'),
|
|
config('roles.const.REDACTEUR')
|
|
]));
|
|
Arr::set($response, 'isDepot', $isDepot);
|
|
Arr::set(
|
|
$response,
|
|
'isCAQuery',
|
|
$searchText &&
|
|
strpos($searchText, '=') !== false &&
|
|
\strval(collect(explode('=', $searchText))->get(0)) === 'ca'
|
|
);
|
|
Arr::set($response, 'role', $user->role);
|
|
|
|
return \response()->json($response);
|
|
}
|
|
|
|
/**
|
|
* Déplacement des médias
|
|
*
|
|
* @param \App\Http\Requests\Bo\Ajax\MoveMediaRequest $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function moveMedia(MoveMediaRequest $request): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$user->authorizeRoles([
|
|
config('roles.const.ADMIN'),
|
|
config('roles.const.REDACTEUR')
|
|
]);
|
|
|
|
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
|
|
$mediaList = Media::whereIn('id', collect($request->mediaList)->pluck('id'))
|
|
->where('isLocked', false)->get();
|
|
|
|
$destinationDossierId = \intval($request->dossier_id);
|
|
|
|
// * Update each Media dossier id than try to dispatch media moved event
|
|
$mediaList->map(function (Media $media) use ($destinationDossierId, $user) {
|
|
$media->dossier_id = $destinationDossierId > 0 ? $destinationDossierId : null;
|
|
if (!$media->saveQuietly()) {
|
|
throw new \RuntimeException('Failed to save Media');
|
|
}
|
|
/** @throws \RuntimeException */
|
|
$media->addToElasticSearch();
|
|
|
|
MediaMoved::dispatch($user, $media);
|
|
});
|
|
|
|
return \response()->json(true);
|
|
}
|
|
|
|
/**
|
|
* Supprimer des médias
|
|
*
|
|
* @param \App\Http\Requests\Bo\Ajax\DeleteMediaRequest $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function removeMedia(DeleteMediaRequest $request): JsonResponse
|
|
{
|
|
$deletedMediasList = [];
|
|
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
$user->authorizeRoles([
|
|
config('roles.const.ADMIN'),
|
|
config('roles.const.REDACTEUR')
|
|
]);
|
|
|
|
if ($user->hasRole(config('roles.const.ADMIN'))) {
|
|
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
|
|
$mediaCollection = Media::whereIn('id', $request->mediaList)->get();
|
|
} else {
|
|
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
|
|
$mediaCollection = Media::whereIn('id', $request->mediaList)->whereNull('arcadia_id')->get();
|
|
}
|
|
|
|
DB::transaction(function () use ($mediaCollection, &$deletedMediasList) {
|
|
$mediaCollection->map(function (Media $media) use (&$deletedMediasList) {
|
|
$deletedMediasList[] = $media->id;
|
|
$media->deleteOrFail();
|
|
});
|
|
});
|
|
|
|
return response()->json($deletedMediasList);
|
|
}
|
|
|
|
/**
|
|
* Récupération d'un média
|
|
*
|
|
* @param \Illuminate\Http\Request $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function recoverMedia(Request $request): JsonResponse
|
|
{
|
|
try {
|
|
return DB::transaction(function () use ($request) {
|
|
/** @var \App\Models\Media */
|
|
$media = Media::onlyTrashed()
|
|
->where('arcadia_id', '=', $request->arcadia_id)
|
|
->firstOrFail();
|
|
if (!$media->restore()) {
|
|
throw new \RuntimeException('Failed to restore media');
|
|
}
|
|
|
|
/** @throws \RuntimeException */
|
|
$media->addToElasticSearch();
|
|
|
|
// * Lien Arcadia
|
|
if (!($status = ArcadiaLinkUtilities::reactivate($media))) {
|
|
throw new \RuntimeException('Failed to restore media arcadia link');
|
|
}
|
|
|
|
return response()->json($status);
|
|
});
|
|
} catch (ModelNotFoundException | \RuntimeException $e) {
|
|
return response()->json($e->getMessage(), 500);
|
|
} //end try
|
|
}
|
|
|
|
/**
|
|
* Mets à jour toutes les informations d'un média
|
|
*
|
|
* @param \App\Http\Requests\Bo\Ajax\UpdateMediaRequest $request
|
|
* @param \App\Models\Media $media
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function updateMedia(UpdateMediaRequest $request, Media $media): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$user->authorizeRoles([
|
|
config('roles.const.ADMIN'),
|
|
config('roles.const.REDACTEUR'),
|
|
config('roles.const.CONTRIBUTEUR')
|
|
]);
|
|
|
|
if ($media->isLocked) {
|
|
return \response()->json([
|
|
'status' => false,
|
|
'error' => trans('Le média est en attente d\'un retour d\'Arcadia.')
|
|
]);
|
|
}
|
|
|
|
try {
|
|
DB::transaction(function () use ($request, $media) {
|
|
$media->fill($request->validated());
|
|
|
|
// MAJ des tags .
|
|
$media->tags()->detach();
|
|
|
|
collect($request->tags)->map(function (array $tag) use ($media) {
|
|
/** @var \App\Models\Tag */
|
|
$oTag = Tag::where('libelle', $tag['libelle'])->firstOrNew();
|
|
$oTag->libelle = $tag['libelle'];
|
|
$oTag->saveOrFail();
|
|
$media->tags()->attach($oTag);
|
|
});
|
|
|
|
// ---- Les sociétés
|
|
$media->societes()->sync(collect($request->societes)->pluck('id')->all());
|
|
|
|
// ---- Les marques
|
|
$media->marques()->sync(collect($request->marques)->pluck('codMarq')->all());
|
|
|
|
// ---- Les articles
|
|
$media->articles()->sync(collect($request->articles)->pluck('id')->all());
|
|
|
|
$media->saveOrFail();
|
|
|
|
$media->fresh();
|
|
$media->addToElasticSearch();
|
|
});
|
|
|
|
$media->fresh();
|
|
return \response()->json([
|
|
'status' => true,
|
|
'sujet_id' => $media->sujet_id,
|
|
'datas' => $media
|
|
]);
|
|
} catch (\RuntimeException $e) {
|
|
report($e);
|
|
return \response()->json([
|
|
'status' => false,
|
|
'error' => trans('Une erreur est survenue veuillez réessayer')
|
|
]);
|
|
} //end try
|
|
}
|
|
|
|
/**
|
|
* Duplique un média sans l'image
|
|
|
|
* @param \App\Models\Media $media
|
|
* @return \Illuminate\Http\JsonResponse
|
|
* @throws \RuntimeException If copying default picture or get defaultPicture informations fails.
|
|
*/
|
|
public function duplicateMedia(Media $media): JsonResponse
|
|
{
|
|
return DB::transaction(function () use ($media) {
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$user->authorizeRoles([
|
|
config('roles.const.ADMIN'),
|
|
config('roles.const.REDACTEUR'),
|
|
config('roles.const.CONTRIBUTEUR')
|
|
]);
|
|
|
|
if ($media->isLocked) {
|
|
return \response()->json([
|
|
'status' => false,
|
|
'error' => trans('Le média est en attente d\'un retour d\'Arcadia.')
|
|
]);
|
|
}
|
|
|
|
$clonedMedia = $media->replicate();
|
|
|
|
// * Remove Arcadia ID (cloned is not linked to arcadia)
|
|
$clonedMedia->arcadia_id = null;
|
|
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
$clonedMedia->uid = Str::uuid();
|
|
$clonedMedia->extension = MediaExtension::jpg;
|
|
|
|
if (!Storage::exists('assets/images/default.jpg')) {
|
|
throw new \RuntimeException('Missing default picture');
|
|
}
|
|
|
|
$fileContent = Storage::get('assets/images/default.jpg');
|
|
|
|
if (!$storage->put($clonedMedia->relative_path, $fileContent)) {
|
|
throw new \RuntimeException('Failed to copy default picture');
|
|
}
|
|
|
|
$clonedMedia->libelle = Str::limit("{$clonedMedia->libelle}_copy", 45);
|
|
$clonedMedia->taille = \strlen($fileContent);
|
|
|
|
$dimensions = ToolboxHelper::getImageDimensions(Storage::path('assets/images/default.jpg'));
|
|
|
|
if ($dimensions) {
|
|
$clonedMedia->resolution = $dimensions['resolutionX'];
|
|
$clonedMedia->largeur = $dimensions['width'];
|
|
$clonedMedia->hauteur = $dimensions['height'];
|
|
$clonedMedia->largeur_mm = !empty($media->resolution) ? ceil($media->largeur * 10) : 0;
|
|
$clonedMedia->hauteur_mm = !empty($media->resolution) ? ceil($media->hauteur * 10) : 0;
|
|
}
|
|
|
|
$clonedMedia->isDefault = true;
|
|
$clonedMedia->owner()->associate($user);
|
|
|
|
$clonedMedia->typeMedia()->associate(TypeMedia::getMediaType($clonedMedia->extension));
|
|
|
|
// ---- Creation des vignettes de base
|
|
$clonedMedia->createThumbnail();
|
|
// ---- Creation des vignettes en lien avec le sujet du média
|
|
$clonedMedia->createSubjectThumbnails();
|
|
|
|
$clonedMedia->save();
|
|
|
|
// * Add relations after having a media id
|
|
$media->articles->map(function (Article $article) use ($clonedMedia) {
|
|
$clonedMedia->articles()->attach($article);
|
|
});
|
|
$media->marques->map(function (Marque $marque) use ($clonedMedia) {
|
|
$clonedMedia->marques()->attach($marque);
|
|
});
|
|
$media->societes->map(function (Societe $societe) use ($clonedMedia) {
|
|
$clonedMedia->societes()->attach($societe);
|
|
});
|
|
$media->tags->map(function (Tag $tag) use ($clonedMedia) {
|
|
$clonedMedia->tags()->attach($tag);
|
|
});
|
|
|
|
|
|
/** @throws \RuntimeException */
|
|
$clonedMedia->addToElasticSearch();
|
|
|
|
// * Get props inserted by DB.
|
|
$clonedMedia->refresh();
|
|
|
|
return \response()->json([
|
|
'status' => true,
|
|
'sujet_id' => $clonedMedia->sujet_id,
|
|
'datas' => $clonedMedia
|
|
]);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Sauvegarde toutes les informations d'un média
|
|
*
|
|
* @param \App\Http\Requests\Bo\Ajax\ApplyStickerRequest $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function applySticker(ApplyStickerRequest $request): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$user->authorizeRoles([
|
|
config('roles.const.ADMIN'),
|
|
config('roles.const.REDACTEUR'),
|
|
config('roles.const.CONTRIBUTEUR')
|
|
]);
|
|
|
|
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Media> */
|
|
$mediaList = Media::whereIn('id', collect($request->mediaList)->pluck('id'))->get();
|
|
/** @var \App\Models\Etiquette */
|
|
$etiquette = Etiquette::where('etiquette_id', $request->etiquette_id)->firstOrFail();
|
|
|
|
DB::transaction(function () use ($mediaList, $etiquette) {
|
|
$mediaList->map(
|
|
function (Media $media) use ($etiquette) {
|
|
if ($media->isLocked) {
|
|
throw ValidationException::withMessages([
|
|
'media' => 'Impossible d\'appliquer la demande un des médias est verrouilé'
|
|
]);
|
|
}
|
|
$media->etiquette()->associate($etiquette);
|
|
$media->saveOrFail();
|
|
}
|
|
);
|
|
});
|
|
return response()->json();
|
|
}
|
|
|
|
/**
|
|
* Vérification des clés pour liaison arcadia avant création et mise à jour
|
|
*
|
|
* @param \App\Http\Requests\Bo\Ajax\CheckRefKeyRequest $request
|
|
* @return \Illuminate\Http\JsonResponse
|
|
* @throws \RuntimeException If media does not have a subject.
|
|
*/
|
|
public function checkRefKey(CheckRefKeyRequest $request): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$user->authorizeRoles([config('roles.const.ADMIN')]);
|
|
|
|
/** @var \App\Models\Media */
|
|
$media = $request->media;
|
|
|
|
// ? Media has subject ?
|
|
if (!$media->sujet) {
|
|
throw new \RuntimeException("Le media '{$media->id}' n'as pas de sujet");
|
|
}
|
|
// ? Subject is not arcadia ?
|
|
if (!$media->sujet->sujet_arcadia) {
|
|
return \response()->json(ArcadiaLinkUtilities::getRefKey($media)->count() > 0);
|
|
}
|
|
|
|
// * On est sur un sujet arcadia (donc pas le sujet Groupe par exemple) .
|
|
// ! restreindre pour tout sauf si type de vue 19 (BAT) et sujet 1 (Articles)
|
|
if (\optional($media->typeVue)->id === 19 and \optional($media->sujet)->id === 1) {
|
|
return \response()->json(ArcadiaLinkUtilities::getRefKey($media)->count() > 0);
|
|
}
|
|
|
|
// * On récupère les restrictions par arcadia.
|
|
/** @var string|null */
|
|
$checkwidth = Setting::where('key', 'arcadia_size_restriction_width')->value('value');
|
|
/** @var string|null */
|
|
$checkheight = Setting::where('key', 'arcadia_size_restriction_height')->value('value');
|
|
/** @var string|null */
|
|
$checkmime = Setting::where('key', 'arcadia_mime_restriction')->value('value');
|
|
/** @var string[] */
|
|
$checkmime = $checkmime ? \explode(',', $checkmime) : [];
|
|
|
|
// * Vérification du mime .
|
|
if (!(in_array($media->extension->value, $checkmime) || empty($checkmime))) {
|
|
// * fail type de fichier
|
|
return \response()->json([
|
|
'status' => false,
|
|
'error' => "Le type de fichier doit être " . implode('ou ', $checkmime) .
|
|
", veuillez charger un autre média"
|
|
]);
|
|
}
|
|
|
|
// * Verification de la largeur (hard default 1800)
|
|
// * Vérification hauteur (hard default 1800)
|
|
if (
|
|
!($media->largeur == $checkwidth || $media->largeur === 1800 || \is_null($checkwidth)) or
|
|
!($media->hauteur == $checkheight || $media->hauteur === 1800 || \is_null($checkheight))
|
|
) {
|
|
// * fail largeur
|
|
return \response()->json([
|
|
'status' => false,
|
|
'error' =>
|
|
"Les dimensions requises sont ${checkwidth}px par ${checkheight}px, veuillez charger un autre média"
|
|
]);
|
|
}
|
|
|
|
return \response()->json();
|
|
}
|
|
|
|
/**
|
|
* Applique un Id Arcadia à un média
|
|
*
|
|
* @param \App\Models\Media $media
|
|
* @return \Illuminate\Http\JsonResponse
|
|
* @throws \Illuminate\Validation\ValidationException If the media is already linked to Arcadia.
|
|
*/
|
|
public function createArcadiaLink(Media $media): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$user->authorizeRoles([config('roles.const.ADMIN')]);
|
|
|
|
if ($media->arcadia_id) {
|
|
throw ValidationException::withMessages([
|
|
'media' => trans('Ce média est déjà lié à arcadia')
|
|
]);
|
|
}
|
|
|
|
MediaLinkWithArcadia::dispatch($user, $media);
|
|
|
|
return response()->json(true);
|
|
}
|
|
|
|
/**
|
|
* Téléchargement des médias pour panier publics
|
|
*
|
|
* @param \App\Http\Requests\Bo\DownloadMediaPublicRequest $request
|
|
* @param \App\Models\Format|null $format
|
|
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
|
*/
|
|
public function downloadMediaPublic(
|
|
DownloadMediaPublicRequest $request,
|
|
Format|null $format = null
|
|
): BinaryFileResponse {
|
|
return $this->downloadMedia($request, $format);
|
|
}
|
|
|
|
/**
|
|
* Téléchargement des médias
|
|
*
|
|
* @param \App\Http\Requests\Bo\DownloadMediaRequest $request
|
|
* @param \App\Models\Format|null $format
|
|
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
|
*/
|
|
public function downloadMedia(DownloadMediaRequest $request, Format|null $format = null): BinaryFileResponse
|
|
{
|
|
$deleteFileAfterSend = false;
|
|
|
|
$mediaIds = collect($request->mediaList);
|
|
if ($mediaIds->count() === 1) {
|
|
/** @var \App\Models\Media */
|
|
$media = Media::whereIn('id', $mediaIds)->firstOrFail();
|
|
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
$fp = !$format ? $storage->path($media->relative_path) : $media->getPath($format);
|
|
|
|
if (!File::exists($fp)) {
|
|
abort(404, 'Fichier inconnu.');
|
|
}
|
|
|
|
$dlFileName = str_replace(' ', '_', Str::slug($media->libelle));
|
|
$ext = pathinfo($fp, PATHINFO_EXTENSION);
|
|
if (!$format) {
|
|
return response()
|
|
->download($fp, "{$dlFileName}_original_{$media->largeur}x{$media->hauteur}px.{$ext}")
|
|
->deleteFileAfterSend($deleteFileAfterSend);
|
|
}
|
|
return response()
|
|
->download($fp, "{$dlFileName}_{$format->libelle}_{$media->largeur}x{$media->hauteur}px.{$ext}")
|
|
->deleteFileAfterSend($deleteFileAfterSend);
|
|
} //end if
|
|
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('public');
|
|
$uniqId = uniqid();
|
|
$date = date("Ymd");
|
|
|
|
// * Create zip archive .
|
|
$zip_file = $storage->path("zips/DAM_{$uniqId}_{$date}.zip");
|
|
$zip = new \ZipArchive();
|
|
$zip->open($zip_file, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
|
|
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
// * Add file to archive.
|
|
foreach ($mediaIds as $mediaId) {
|
|
/** @var \App\Models\Media */
|
|
$media = Media::where('id', $mediaId)->firstOrFail();
|
|
|
|
$fp = !$format ? $storage->path($media->relative_path) : $media->getPath($format);
|
|
|
|
if (!File::exists($fp)) {
|
|
$zip->close();
|
|
abort(404, 'Fichier inconnu.');
|
|
}
|
|
|
|
$dlFileName = str_replace(' ', '_', Str::slug($media->libelle));
|
|
$ext = pathinfo($fp, PATHINFO_EXTENSION);
|
|
$dlFileName = !$format ?
|
|
"{$dlFileName}_original_{$media->largeur}x{$media->hauteur}px.{$ext}" :
|
|
"{$dlFileName}_{$format->libelle}_{$media->largeur}x{$media->hauteur}px.{$ext}";
|
|
|
|
$zip->addFile($fp, $dlFileName);
|
|
} //end foreach
|
|
$deleteFileAfterSend = true;
|
|
$zip->close();
|
|
$fp = $zip_file;
|
|
return response()->download($fp)->deleteFileAfterSend($deleteFileAfterSend);
|
|
}
|
|
|
|
/**
|
|
* Renvoie les infos complémentaires d'un média
|
|
*
|
|
* @param \App\Models\Media $media
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function getMediaOtherInfos(Media $media): JsonResponse
|
|
{
|
|
if (!auth()->check()) {
|
|
abort(401, 'Cette action n\'est pas autorisée.');
|
|
}
|
|
|
|
$history = Historique::query()
|
|
->whereHas('media', fn(Builder $q) => $q->where('id', $media->id))
|
|
->with('user')
|
|
->orderBy('created_date', 'DESC')
|
|
->get();
|
|
|
|
return \response()->json([
|
|
'history' => $history,
|
|
'vignettes' => $this->getVignettesByMedia($media)
|
|
]);
|
|
}
|
|
|
|
// * PRIVATE METHODS
|
|
|
|
/**
|
|
* Elastic Search filters
|
|
*
|
|
* @param array $esMust
|
|
* @param \App\Http\Requests\Bo\LoadMediaRequest $request
|
|
* @return void
|
|
*/
|
|
private function esFilters(array &$esMust, LoadMediaRequest $request): void
|
|
{
|
|
$filters = (object)collect($request->filters)->all();
|
|
|
|
$getFilterProp = function ($prop) use ($filters) {
|
|
return collect($filters)->reduce(function (array|null $carry, array $item) use ($prop) {
|
|
$item = collect($item);
|
|
return $carry ?? ($item->get('type') === $prop ? $item->get('value') : null);
|
|
});
|
|
};
|
|
|
|
/** @var array|null */
|
|
$codeTypemedia = $getFilterProp('type_media_id');
|
|
|
|
/** @var array|null */
|
|
$codeTypevue = $getFilterProp('type_vue_id');
|
|
|
|
/** @var array|null */
|
|
$etiquette_id = $getFilterProp('etiquette_id');
|
|
|
|
/** @var boolean */
|
|
$arcadia_id = collect($filters)->reduce(function (string|null $carry, array $item) {
|
|
$item = collect($item);
|
|
return $carry ?? ($carry or $item->get('type') === 'arcadia_id' ? true : false);
|
|
});
|
|
|
|
$esConditions = [];
|
|
|
|
// * Filtre liason avec Arcadia
|
|
if ($arcadia_id) {
|
|
$esConditions[] = \array_undot(['exists.field' => 'arcadia_id']);
|
|
}
|
|
|
|
// * Filtre type de média
|
|
if ($codeTypemedia) {
|
|
$esConditions[] = \array_undot(['bool.filter.terms.type_media_id' => collect($codeTypemedia)
|
|
->pluck('codeTypemedia')->values()->all()]);
|
|
}
|
|
|
|
// * Filtre type de vue
|
|
if ($codeTypevue) {
|
|
$esConditions[] = \array_undot(['bool.filter.terms.type_vue_id' => collect($codeTypevue)
|
|
->pluck('codeTypevue')->values()->all()]);
|
|
}
|
|
|
|
// * Filtre etiquette
|
|
if ($etiquette_id) {
|
|
$esConditions[] = \array_undot(['bool.filter.terms.etiquette_id' => collect($etiquette_id)
|
|
->pluck('etiquette_id')->values()->all()]);
|
|
}
|
|
|
|
$esMust = array_merge($esMust, $esConditions);
|
|
}
|
|
|
|
/**
|
|
* Elastic Search select appropriate Folder
|
|
*
|
|
* @param array $esMust ES conditions INCLURE TOUT (AND).
|
|
* @param array $esMustNot ES conditions EXCLURE.
|
|
* @param array $esShould ES conditions INCLURE AU MOINS (OR), avec un score.
|
|
* @param \App\Http\Requests\Bo\LoadMediaRequest $request La request Lrvl.
|
|
* @param \App\Models\Dossier|null $dossier Le dossier concerné, si les Medias
|
|
* doivent appartenir a celui-ci.
|
|
* @param \App\Models\Sujet $sujet Le sujet concerné, si les Medias
|
|
* doivent appartenir a celui-ci.
|
|
* @param boolean $isDepot Si les medias doivent se trouver dans le dossier dépot.
|
|
* @return void
|
|
*/
|
|
private function esFolderSearch(
|
|
array &$esMust,
|
|
array &$esMustNot,
|
|
array &$esShould,
|
|
LoadMediaRequest $request,
|
|
Dossier|null $dossier,
|
|
Sujet $sujet,
|
|
bool $isDepot
|
|
): void {
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
// ? Doivent être dans le dossier dépot ?
|
|
if ($isDepot) {
|
|
// * Dossier dépôt
|
|
$esMust = array_merge($esMust, [[
|
|
\array_undot(['match.dossier_id' => $dossier->id])
|
|
]]);
|
|
return;
|
|
}
|
|
|
|
// ? N'est pas dans le dossier dépot ou racine ?
|
|
if (!$dossier) {
|
|
// ? Recherche globale ?
|
|
if ($request->input('folder') === -1) {
|
|
// * Recherche globale .
|
|
$esMust = array_merge($esMust, [
|
|
// * AND
|
|
\array_undot(['bool.must.match.sujet_id' => $sujet->codeSujet])
|
|
]);
|
|
} else {
|
|
// * Dossier racine .
|
|
$esMust = array_merge($esMust, [
|
|
// * AND
|
|
\array_undot(['bool.should.match.sujet_id' => $sujet->codeSujet])
|
|
]);
|
|
$esMustNot = array_merge($esMustNot, [
|
|
\array_undot(['exists.field' => 'dossier_id'])
|
|
]);
|
|
} //end if
|
|
// * OR
|
|
$esShould = array_merge($esShould, [
|
|
\array_undot(['match.statut' => MediaStatut::public_etendu]),
|
|
\array_undot(['match.statut' => MediaStatut::public]),
|
|
\array_undot(['match.created_by' => $user->id])
|
|
]);
|
|
return;
|
|
} //end if
|
|
|
|
// * Dossier classic .
|
|
$esMust = array_merge($esMust, [[
|
|
// * AND
|
|
\array_undot([
|
|
'bool.must' => [
|
|
\array_undot(['match.sujet_id' => $sujet->codeSujet]),
|
|
\array_undot(['match.dossier_id' => $dossier->id]),
|
|
]
|
|
])
|
|
]]);
|
|
|
|
// ? User n'est pas ADMIN ?
|
|
if (!$user->hasRole(config('roles.const.ADMIN'))) {
|
|
// * Ajout de restrictions
|
|
// * Tout ce qui nous appartient et tout ce qui n'est pas brouillon
|
|
$esMust = array_merge($esMust, [
|
|
\array_undot([
|
|
// * OR
|
|
'bool.should' => [
|
|
\array_undot([
|
|
'bool.must_not' => [[
|
|
\array_undot([
|
|
'term.statut.value' => MediaStatut::brouillon,
|
|
'term.statut.boost' => 1.0
|
|
])
|
|
]],
|
|
'bool.adjust_pure_negative' => true,
|
|
'bool.boost' => 1.0
|
|
]),
|
|
\array_undot([
|
|
'term.created_by.value' => $user->id,
|
|
'term.created_by.boost' => 1.0
|
|
])
|
|
],
|
|
'bool.adjust_pure_negative' => true,
|
|
'bool.boost' => 1.0
|
|
])
|
|
]);
|
|
} //end if
|
|
}
|
|
|
|
/**
|
|
* Elastic Search Recherche texte
|
|
*
|
|
* eg : 'cv = 5010' OU 'poulet + certifie' OU 'nimporte quoi'.
|
|
*
|
|
* 'ca' => 'articles.noArt',
|
|
* 'fv' => 'articles.codFamVte',
|
|
* 'gca' => 'articles.codGencodAdm',
|
|
* 'gcs' => 'articles.codGencodSymb',
|
|
* 'gcp' => 'articles.codGencodPds',
|
|
* 'cd' => 'id',
|
|
* 'cv' => 'arcadia_id',
|
|
*
|
|
* @param array $esMust
|
|
* @param \App\Http\Requests\Bo\LoadMediaRequest $request
|
|
* @param \App\Models\Sujet $sujet
|
|
* @param string|null $searchText
|
|
* @return void
|
|
*/
|
|
private function esTextSearch(
|
|
array &$esMust,
|
|
LoadMediaRequest $request,
|
|
Sujet $sujet,
|
|
string|null $searchText
|
|
): void {
|
|
if (!$searchText) {
|
|
return;
|
|
}
|
|
|
|
$tmpFilters = [];
|
|
$search = strtolower(trim($searchText));
|
|
|
|
// * Search mode columns
|
|
if (strpos($search, '=') !== false) {
|
|
$tmpSearch = collect(explode('=', $search));
|
|
$key = \strval($tmpSearch->get(0));
|
|
$needle = \strval($tmpSearch->get(1));
|
|
|
|
$matches = [
|
|
'ca' => 'articles.noArt',
|
|
'fv' => 'articles.codFamVte',
|
|
'gca' => 'articles.codGencodAdm',
|
|
'gcs' => 'articles.codGencodSymb',
|
|
'gcp' => 'articles.codGencodPds',
|
|
'cd' => 'id',
|
|
'cv' => 'arcadia_id',
|
|
];
|
|
|
|
if (\array_key_exists($key, $matches)) {
|
|
$tmpFilters = [[
|
|
\array_undot(['bool.must.match' => [
|
|
$matches[$key] => $needle
|
|
]])
|
|
]];
|
|
}
|
|
// * Search keywords
|
|
} elseif (strpos($search, '+') !== false) {
|
|
$tmpSearch = explode('+', $search);
|
|
|
|
$mustLib = [];
|
|
foreach ($tmpSearch as $search) {
|
|
array_push($mustLib, [
|
|
'wildcard' => [
|
|
'libelle.keyword' => [
|
|
'wildcard' => "*$search*",
|
|
'boost' => 1.0
|
|
]
|
|
]
|
|
]);
|
|
}
|
|
|
|
$mustArt = [];
|
|
foreach ($tmpSearch as $search) {
|
|
array_push($mustArt, [
|
|
'wildcard' => [
|
|
'articles.libCcial.keyword' => [
|
|
'wildcard' => "*$search*",
|
|
'boost' => 1.0
|
|
]
|
|
]
|
|
]);
|
|
}
|
|
|
|
$tmpFilters = [
|
|
\array_undot(['bool.should' => [
|
|
\array_undot(['bool.must' => $mustLib]),
|
|
\array_undot(['bool.must' => $mustArt])
|
|
]])
|
|
];
|
|
} else {
|
|
// * Search auto
|
|
$tmpFilters = [[
|
|
'multi_match' => [
|
|
'query' => $search,
|
|
"type" => "most_fields",
|
|
'fields' => [
|
|
'libelle^3',
|
|
'commentaire^2',
|
|
'arcadia_id',
|
|
'articles.libCcial',
|
|
'articles.libMarq',
|
|
'articles.libFamVte',
|
|
'tags.libelle'
|
|
],
|
|
'operator' => 'or',
|
|
'fuzziness' => 'AUTO'
|
|
]
|
|
]];
|
|
} //end if
|
|
|
|
$esMust = array_merge($esMust, $tmpFilters);
|
|
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$filters = (object)collect($request->filters)->all();
|
|
|
|
MediaSearched::dispatch(
|
|
$user,
|
|
$sujet,
|
|
$searchText,
|
|
$filters,
|
|
intval($request->folder)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get vignettes info from media
|
|
*
|
|
* @param \App\Models\Media $media
|
|
* @return array
|
|
*/
|
|
private function getVignettesByMedia(Media $media): array
|
|
{
|
|
/** @var \Illuminate\Filesystem\FilesystemAdapter */
|
|
$storage = Storage::disk('media');
|
|
|
|
$vignettes = [];
|
|
|
|
$vignettes['original'] = [
|
|
'url' => $storage->url($media->relative_path),
|
|
'extension' => $media->extension->value,
|
|
'largeur' => $media->largeur,
|
|
'hauteur' => $media->hauteur
|
|
];
|
|
|
|
$sys_extension = in_array($media->extension, [
|
|
MediaExtension::pdf,
|
|
MediaExtension::ai,
|
|
MediaExtension::psd
|
|
]) ? MediaExtension::png : $media->extension->value;
|
|
|
|
$vignettes['preview'] = [
|
|
'url' => $storage->url($media->preview_relative_path),
|
|
'extension' => $sys_extension,
|
|
'largeur' => '1800',
|
|
'hauteur' => '1800'
|
|
];
|
|
$vignettes['thumb'] = [
|
|
'url' => $storage->url($media->thumb_relative_path),
|
|
'extension' => $sys_extension,
|
|
'largeur' => '200',
|
|
'hauteur' => '200'
|
|
];
|
|
|
|
$media->sujet->formats->map(function (Format $format) use (&$vignettes, $media, $storage) {
|
|
$vignettes[$format->libelle] = [
|
|
'url' => $storage->url("{$media->folder}/{$media->uid}_{$format->libelle}.{$format->extension}"),
|
|
'extension' => $format->extension,
|
|
'largeur' => $format->largeur,
|
|
'hauteur' => $format->hauteur
|
|
];
|
|
});
|
|
return $vignettes;
|
|
}
|
|
}
|