composer require ldc/web-status-checker-laravel remove Old static status checker Fix ImportMedia WIP commands OK many fixes Fix and try to optimize folder component Fix front icons + actions based on icons Favico front fix alert Fix Media upload on depot fix folder component buttons Full front fix with perf due tu vuejs Download medias Navigate within medias superfix Move media + loader isLocked boolean and remove media fix Folder scroll fix arcadia link color red Fix panier show external Tons of fixes back as front REwrited all
1089 lines
37 KiB
PHP
1089 lines
37 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Enums\MediaExtension;
|
|
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\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\Database\Eloquent\ModelNotFoundException;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
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;
|
|
/** @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_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
|
|
* @return \Illuminate\Http\JsonResponse
|
|
*/
|
|
public function loadMedia(LoadMediaRequest $request): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
/** @var \App\Models\Dossier|null */
|
|
$dossier = Dossier::where('id', $request->folder)->first();
|
|
|
|
/** @var \App\Models\Sujet */
|
|
$sujet = Sujet::where('codeSujet', $request->sujet)->firstOrFail();
|
|
|
|
$response = [];
|
|
$filters = (object)collect($request->filters)->all();
|
|
|
|
$isDepot = ($dossier->parent_id ?? null) === 1 || ($dossier->id ?? null) === 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,
|
|
$esFilters,
|
|
$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]]];
|
|
|
|
$response['data'] = Media::searchByQuery(
|
|
$query,
|
|
null,
|
|
null,
|
|
intval($request->post('limit', 50)),
|
|
intval($request->post('offset', 0)),
|
|
$sort
|
|
);
|
|
|
|
$response['draggable'] = $user->hasRole([config('roles.const.ADMIN'), config('roles.const.REDACTEUR')]);
|
|
$response['isDepot'] = $isDepot;
|
|
|
|
$response['isCAQuery'] = $searchText &&
|
|
strpos($searchText, '=') !== false &&
|
|
\strval(collect(explode('=', $searchText))->get(0)) === 'ca';
|
|
|
|
$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
|
|
{
|
|
/** @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();
|
|
|
|
$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);
|
|
});
|
|
|
|
/** @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->saveOrFail();
|
|
|
|
|
|
/** @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
|
|
*/
|
|
public function createArcadiaLink(Media $media): JsonResponse
|
|
{
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
$user->authorizeRoles([config('roles.const.ADMIN')]);
|
|
|
|
MediaLinkWithArcadia::dispatch($user, $media);
|
|
|
|
return response()->json(true);
|
|
}
|
|
|
|
/**
|
|
* 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 (!($user = Auth::user())) {
|
|
abort(401, 'Cette action n\'est pas autorisée.');
|
|
}
|
|
|
|
$history = Historique::whereHas('media', function ($q) use ($media) {
|
|
$q->whereId($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
|
|
* @param array $esMustNot
|
|
* @param array $esShould
|
|
* @param array $esFilters
|
|
* @param \App\Http\Requests\Bo\LoadMediaRequest $request
|
|
* @param \App\Models\Dossier|null $dossier
|
|
* @param \App\Models\Sujet $sujet
|
|
* @param boolean $isDepot
|
|
* @return void
|
|
*/
|
|
private function esFolderSearch(
|
|
array &$esMust,
|
|
array &$esMustNot,
|
|
array &$esShould,
|
|
array &$esFilters,
|
|
LoadMediaRequest $request,
|
|
Dossier|null $dossier,
|
|
Sujet $sujet,
|
|
bool $isDepot
|
|
): void {
|
|
/** @var \App\Models\User */
|
|
$user = auth()->user();
|
|
|
|
if (!$dossier) {
|
|
if ($request->folder === -1) {
|
|
// * Recherche globale .
|
|
$esMust = array_merge($esMust, [
|
|
\array_undot(['bool.must.match.sujet_id' => $sujet->codeSujet])
|
|
]);
|
|
} else {
|
|
// * Dossier racine .
|
|
$esMust = array_merge($esMust, [
|
|
\array_undot(['bool.should.match.sujet_id' => $sujet->codeSujet])
|
|
]);
|
|
$esMustNot = array_merge($esMustNot, [
|
|
\array_undot(['exists.field' => 'dossier_id'])
|
|
]);
|
|
} //end if
|
|
$esShould = array_merge($esShould, [
|
|
\array_undot(['match.statut' => config('services.statut.public_etendu')]),
|
|
\array_undot(['match.statut' => config('services.statut.public')]),
|
|
\array_undot(['match.created_by' => $user->id])
|
|
]);
|
|
} elseif (!$isDepot) {
|
|
// * Dossier classic .
|
|
$esMust = array_merge($esMust, [[
|
|
\array_undot([
|
|
'bool.must' => [
|
|
\array_undot(['match.sujet_id' => $sujet->codeSujet]),
|
|
\array_undot(['match.dossier_id' => $dossier->id]),
|
|
]
|
|
])
|
|
]]);
|
|
if (!$user->hasRole(config('roles.const.ADMIN'))) {
|
|
$esFilters = array_merge($esFilters, [
|
|
\array_undot([
|
|
'bool.should' => [
|
|
\array_undot([
|
|
'bool.must_not' => [[
|
|
\array_undot([
|
|
'term.statut.value' => config('services.statut.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
|
|
} else {
|
|
// * Dossier dépôt
|
|
$esMust = array_merge($esMust, [[
|
|
\array_undot(['match.dossier_id' => $dossier->id])
|
|
]]);
|
|
} //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
|
|
]
|
|
]
|
|
]);
|
|
}
|
|
|
|
// TODO: \array_undot( herre
|
|
$tmpFilters = [
|
|
[
|
|
'bool' => [
|
|
'should' => [
|
|
[
|
|
'bool' => [
|
|
'must' => $mustLib
|
|
]
|
|
],
|
|
[
|
|
'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
|
|
];
|
|
|
|
if (
|
|
in_array($media->extension, [
|
|
MediaExtension::pdf,
|
|
MediaExtension::ai,
|
|
MediaExtension::psd
|
|
])
|
|
) {
|
|
$sys_extension = MediaExtension::png;
|
|
} else {
|
|
$sys_extension = $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'
|
|
];
|
|
|
|
$formats = $media->sujet->formats;
|
|
foreach ($formats as $format) {
|
|
$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;
|
|
}
|
|
}
|