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 ?? false) 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; } }