<?php
namespace App\Controller\Athena;
use App\Entity\Athena\Page;
use App\Entity\Athena\User;
use App\Entity\Athena\VideoTutorial;
use App\Form\Athena\DeleteForm;
use App\Service\Asclepios\ClinicService;
use App\Service\Athena\ComingSoonLogoutService;
use App\Service\Athena\ContextService;
use App\Service\Athena\DatatableService;
use App\Service\Athena\PageService;
use App\Service\Athena\TranslationService;
use App\Service\Hephaistos\DateService;
use Doctrine\Persistence\ObjectRepository;
use Exception;
use ReflectionClass;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Profiler\Profiler;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;
class DefaultController extends AbstractController
{
const DEFAULT_TEMPLATE = 'Athena/index';
const TEMPLATE_EXTENSION = '.html.twig';
const STATUS_MESSAGE = 'message';
const STATUS_WARNING = 'warning';
const STATUS_ERROR = 'error';
const STATUS_EXCEPTION = 'exception';
const TAG_BREADCRUMB = 'a-breadcrumb';
const TAG_BUTTONS = 'a-buttons';
const TAG_JAVASCRIPT = 'a-javascript';
const TAG_KEEP_MODAL_OPENED = 'a-keep-modal-opened';
const TAG_MAIN = 'a-main';
const TAG_MAIN_OVERTITLE = 'a-main-overtitle';
const TAG_MAIN_SUBTITLE = 'a-main-subtitle';
const TAG_MAIN_TITLE = 'a-main-title';
const TAG_MODAL_TITLE = 'a-modal-title';
const TAG_MODAL_CONTENT = 'a-modal-content';
const TAG_MODAL_CLOSABLE = 'a-modal-closable';
const TAG_ERROR_TITLE = 'a-error-title';
const TAG_ERROR_CONTENT = 'a-error-content';
const TAG_PREVENT_URL_UPDATE = 'a-prevent-url-update';
const TAG_REDIRECT = 'a-redirect';
const TAG_REDIRECT_WITHOUT_LOADER = 'a-redirect-without-loader';
const TAG_REDRAW_BRICK_ID = 'a-redraw-brick-id';
const TAG_REDRAW_BRICK_DATAS = 'a-redraw-brick-datas';
const TAG_RELOAD_IFRAME = 'a-reload-iframe';
const TAG_SET_VALUE = 'a-set-value';
const TAG_STATUS = 'a-status';
const TAG_TARGET_BLANK = 'a-target-blank';
const TAG_FORM_BLANK = 'a-form-blank';
const TAG_FORM_BLANK_DATAS = 'a-form-blank-datas';
const TAG_FUNCTION_ON_LOAD = 'a-function-on-load';
const TAG_SCROLL_TO_TOP = 'a-scroll-content-to-top';
const TAG_KEEP_SIDEBAR_MODAL_OPENED = 'a-keep-sidebar-modal-opened';
const TAG_SIDEBAR_MODAL_TITLE = 'a-sidebar-modal-title';
const TAG_SIDEBAR_MODAL_CONTENT = 'a-sidebar-modal-content';
const TAG_HIDE_MAIN_TITLE = 'a-hide-main-title';
const TAG_SIDEBAR_MODAL_ICON = 'a-sidebar-modal-icon';
const TAG_ONBOARDING = 'a-onboarding';
const TAG_SET_INNER_HTML = 'a-set-inner-html';
const TAG_VIDEO_TUTORIAL = 'a-video-tutorial';
protected array $args;
protected array $cookies;
protected ClinicService $clinicService;
protected ContextService $context;
protected DateService $dateService;
protected DatatableService $datatableService;
protected string $domain;
protected string $entityClass;
protected string $entityName;
protected string $file;
protected string $fileDisposition = HeaderUtils::DISPOSITION_ATTACHMENT;
protected string $fileName;
protected bool $isJson;
protected array $otherData;
protected array $extractData;
protected PageService $pageService;
protected ?Request $request;
protected string $routePrefix;
protected ?Security $security;
protected string $template;
protected TranslationService $translationService;
protected TranslatorInterface $translator;
private ComingSoonLogoutService $comingSoonLogoutService;
private static array $messagesFromService;
public function __construct(
ClinicService $clinicService,
DatatableService $datatableService,
DateService $dateService,
PageService $pageService,
RequestStack $requestStack,
Security $security,
TranslationService $translationService,
TranslatorInterface $translator,
ContextService $context,
ComingSoonLogoutService $comingSoonLogoutService
)
{
$this->comingSoonLogoutService = $comingSoonLogoutService;
if ($this->comingSoonLogoutService->isComingSoon()) {
$this->comingSoonLogoutService->logoutAllConnectedUser();
}
$this->args = [];
$this->cookies = [];
$this->clinicService = $clinicService;
$this->dateService = $dateService;
$this->datatableService = $datatableService;
$this->file = '';
$this->fileName = '';
$this->otherData = [];
$this->extractData = [];
$this->isJson = false;
$this->pageService = $pageService;
$this->request = $requestStack->getCurrentRequest();
$this->security = $security;
$this->template = self::DEFAULT_TEMPLATE;
$this->translationService = $translationService;
$this->translator = $translator;
self::$messagesFromService = [];
$reflection = new ReflectionClass(get_class($this));
foreach ($reflection->getAttributes() as $attribute) {
if (isset($attribute->getArguments()['name'])) {
if ('Symfony\Component\Routing\Annotation\Route' === $attribute->getName()) {
$this->routePrefix = $attribute->getArguments()['name'];
} else {
switch ($attribute->getArguments()[0]) {
case 'entity':
$this->entityClass = $attribute->getArguments()['name'];
$tabEntity = explode('\\', $this->entityClass);
$this->entityName = end($tabEntity);
break;
case 'domain':
$this->domain = $attribute->getArguments()['name'];
break;
}
}
}
}
$this->context = $context;
}
public function getResponse(): Response
{
$clinicDatas = ['sign' => null];
if ($clinic = $this->getContext()->get('clinic')) {
$clinicDatas = [
'sign' => $clinic->getSign(),
'slug' => $this->getParameter('prestashop.url') . '/mon-veterinaire/' . $clinic->getSlug(),
'hasShop' => $clinic->getClubvetShop(),
'hasWebSite' => $clinic->getClubvetWeb(),
'clinicSiteUrl' => $clinic->getClubvetWeb() ? $this->clinicService->getClinicDomain($clinic) : '',
'hasAdvPhoneNumber' => $this->clinicService->getClinicSalesman($clinic)?->getAdvPhoneNumber() ?? false,
'isVeterinary' =>
in_array('ROLE_VETERINARY', $this->getUser()->getRoles()) ||
in_array('ROLE_ASV_LIGHT', $this->getUser()->getRoles()) ||
in_array('ROLE_ASV', $this->getUser()->getRoles()),
'hasBusinessSoftware' => $this->security->isGranted('IS_IMPERSONATOR') ? true : (bool)$clinic->getBusinessSoftware(),
];
}
foreach (self::$messagesFromService as $message) {
$this->addStatus($message['text'], $message['severity'], $message['domain']);
}
if ($this->file && $this->fileName) {
$response = new Response($this->file);
$response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
$this->fileDisposition,
$this->fileName, preg_replace('#^.*\.#', md5($this->fileName) . '.', $this->fileName)
));
if ($this->fileDisposition === HeaderUtils::DISPOSITION_INLINE) {
$fileName = explode('.', $this->fileName);
$response->headers->set('Content-Type', 'application/' . array_pop($fileName));
}
return $response;
}
if ('fetch' === $this->request->headers->get('A-Sending-Method') || $this->isJson) {
if (
str_contains($this->request->getRequestUri(), 'admin/clinic') &&
str_contains($this->request->getRequestUri(), 'choose') &&
!str_contains($this->request->getRequestUri(), 'choosePricePlan')
) {
$this->setContent('searchClinicsUrl', $this->generateUrl('adminClinicSearchClinics'));
$this->setContent('a-switch-clinic', $clinicDatas);
}
if ($page = $this->getRepository(Page::class)->findOneByPath($this->request->getRequestUri())) {
$breadcrumb = [];
while ($page) {
$breadcrumb[] = ['link' => $page->getPath(), 'label' => $this->translationService->getContent($page, 'label')];
$page = $page->getParent();
}
$this->args[self::TAG_BREADCRUMB] = array_reverse($breadcrumb);
}
if ($this->security->getUser() === null) {
$response = $this->json(['a-reload' => true]);
} else {
if ('true' === $this->request->headers->get('A-Fetching-Menu')) {
$this->setContent('a-pages', $this->pageService->getPages());
}
if (self::DEFAULT_TEMPLATE != $this->template) {
$this->args[self::TAG_MAIN] = $this->renderView(
$this->template . self::TEMPLATE_EXTENSION,
$this->args
);
}
if (
empty($this->args[self::TAG_PREVENT_URL_UPDATE])
&& !empty($this->args[self::TAG_MAIN])
) {
// display video tutorial, if any, in header
$this->args[self::TAG_VIDEO_TUTORIAL] = $this->getVideoTutorialUrl();
}
if ($clinic
&& $clinic->getClubvetShop()
&& empty($this->args[self::TAG_MODAL_CONTENT])
&& empty($this->args[self::TAG_REDIRECT])
&& empty($this->args[self::TAG_REDIRECT_WITHOUT_LOADER])
&& !$this->request->cookies->get('alertHolidaySummer2025')
) {
$this->addCookie('alertHolidaySummer2025', '1');
if ($this->request->get('_route') !== 'adminAdministrationHolidayIndex') {
$this->setModal(
'Vous partez aussi en vacances ?',
'
<p class="mb-1">N’oubliez pas d’activer le mode vacances directement depuis votre espace vétérinaire ClubVET Shop afin d’avertir vos clients de votre absence.</p>
<p class="mb-1">
<span class="font-bold">Bon à savoir</span> : les commandes d’abonnement de vos clients, prévues pendant la période de fermeture de la clinique, seront annulées.<br/>
Les clients sont informés par e-mail à deux reprises : une première fois lors de l’envoi de votre message de congés, puis une seconde fois lors de l’annulation automatique, 3 jours avant la date prévue de réception.
</p>
<p class="flex justify-between gap-2">
<a
href="https://xs4xg.mjt.lu/nl3/IrJhnnAzmvnKaFmRsULMRQ?m=AUAAAU7EgGAAAAAAAAAAAKpkxpMAAAAAF1AAAAAAAA27zwBmqMe-pZ-NByaTSG-YlD08x2njaAANpOw&b=1e897e7e&e=dfc0cc58&x=clFl3uxmAix1csWcfeNWGg"
target="_blank"
class="bg-secondary text-center text-white rounded-lg align-middle cursor-pointer inline-flex items-center justify-center min-h-10 px-3"
>
<span class="material-symbols-outlined flex justify-center mr-2">help</span>
Tutoriel
</a>
<a
href="' . $this->generateUrl('adminAdministrationHolidayIndex') . '"
a-click="fetch"
a-modal="closer"
class="bg-secondary text-center text-white rounded-lg align-middle cursor-pointer inline-flex items-center justify-center min-h-10 px-3"
>
<span class="material-symbols-outlined flex justify-center mr-2">beach_access</span>
Activer le mode vacances
</a>
'
);
}
}
$response = $this->json($this->args);
}
} else {
if ($user = $this->security->getUser()) {
$this->args['user'] = [
'firstname' => $user->getFirstname(),
'lastname' => $user->getLastname(),
'avatar' => $user->getAvatar()?->getUrl(),
'onboardingStep' => $user->getOnboardingStep(),
'screenResolutions' => $user->getScreenResolutions(),
];
}
$this->setContent('searchClinicsUrl', $this->generateUrl('adminClinicSearchClinics'));
$this->setContent('a-switch-clinic', $clinicDatas);
$this->setContent('canEditVideoTutorial', $this->canEditVideoTutorial());
$response = $this->render(
$this->template . self::TEMPLATE_EXTENSION,
$this->args
);
}
if (count($this->cookies)) {
try {
$expire = $this->dateService->getDate(interval: 'P1Y');
foreach ($this->cookies as $name => $value) {
$response->headers->setCookie(new Cookie($name, $value, $expire));
}
} catch (Exception $exception) {
$this->addException($exception);
}
}
return $response;
}
public function setContent(string $key, mixed $content, ?array $args = null, ?string $domain = null): self
{
$this->args[$key] = (is_null($args) ?
(is_string($content) ? $this->trans($content, $domain) : $content) :
$this->renderView(
$content . self::TEMPLATE_EXTENSION,
$args
)
);
return $this;
}
public function setMain(string $content, ?array $args = null): self
{
return $this->setContent(self::TAG_MAIN, $content, $args);
}
public function setMainTitle(string $content, ?string $domain = null): self
{
return $this->setContent(self::TAG_MAIN_TITLE, $this->trans($content, $domain));
}
public function hideMainTitle(): self
{
return $this->setContent(self::TAG_HIDE_MAIN_TITLE, true);
}
public function setMainSubTitle(string $content, ?string $domain = null): self
{
return $this->setContent(self::TAG_MAIN_SUBTITLE, $this->trans($content, $domain));
}
public function setMainOverTitle(string $content, ?string $domain = null): self
{
return $this->setContent(self::TAG_MAIN_OVERTITLE, $this->trans($content, $domain));
}
public function setRedirect(string $url): self
{
return $this->setContent(self::TAG_REDIRECT, $url);
}
public function setRedirectWithoutLoader(string $url): self
{
return $this->setContent(self::TAG_REDIRECT_WITHOUT_LOADER, $url);
}
public function setModal(string $title, string $content, ?array $args = null, ?string $domain = null): self
{
return $this
->setContent(self::TAG_MODAL_TITLE, $this->trans($title, $domain))
->setContent(self::TAG_MODAL_CONTENT, $content, $args)
->setContent(self::TAG_MODAL_CLOSABLE, true);
}
public function setUnclosableModal(string $title, string $content, ?array $args = null, ?string $domain = null): self
{
return $this
->setContent(self::TAG_MODAL_TITLE, $this->trans($title, $domain))
->setContent(self::TAG_MODAL_CONTENT, $content, $args)
->setContent(self::TAG_MODAL_CLOSABLE, false);
}
public function setWaitingModal(string $files, string $subject, string $body, bool $plural = false): self
{
return $this
->addJS('Athena.programDeferredDeliveryCheck();')
->setContent(self::TAG_MODAL_TITLE, ($plural ? 'Vos fichiers sont' : 'Votre fichier est') . ' en cours de préparation')
->setcontent(self::TAG_MODAL_CONTENT, 'Athena/DeferredDelivery/waitingModal', [
'files' => $files,
'plural' => $plural,
'subject' => $subject,
'body' => $body,
])
->setContent(self::TAG_MODAL_CLOSABLE, false);
}
public function setSidebarModal(string $title, string $content, string $iconSb, ?array $args = null, ?string $domain = null): self
{
return $this
->setContent(self::TAG_SIDEBAR_MODAL_TITLE, $this->trans($title, $domain))
->setContent(self::TAG_SIDEBAR_MODAL_CONTENT, $content, $args)
->setContent(self::TAG_SIDEBAR_MODAL_ICON, $iconSb);
}
public function setError(string $title, string $content, ?array $args = null, ?string $domain = null): self
{
return $this
->setContent(self::TAG_ERROR_TITLE, $this->trans($title, $domain))
->setContent(self::TAG_ERROR_CONTENT, $content, $args);
}
public function setTemplate(string $template): self
{
$this->template = $template;
return $this;
}
public function setReloadIframe(): self
{
$this->args[self::TAG_RELOAD_IFRAME] = true;
return $this;
}
/**
* @param $key string|array
* @param $value ?string
* @return $this
*/
public function setValue($key, $value = null): self
{
if (is_array($key)) {
$this->args[self::TAG_SET_VALUE] = json_encode($key);
} else {
$this->args[self::TAG_SET_VALUE] = json_encode(['key' => $key, 'value' => $value]);
}
return $this;
}
public function setInnerHTML(array $data): self
{
if (isset($this->args[self::TAG_SET_INNER_HTML])) {
$data = array_merge(json_decode($this->args[self::TAG_SET_INNER_HTML], true), $data);
}
$this->args[self::TAG_SET_INNER_HTML] = json_encode($data);
return $this;
}
public function preventUrlUpdate(): self
{
$this->args[self::TAG_PREVENT_URL_UPDATE] = true;
return $this;
}
public function addCookie(string $name, string $value): self
{
$this->cookies[$name] = $value;
return $this;
}
public function addStatus(
string $message,
string $type = self::STATUS_MESSAGE,
?string $domain = null
): self
{
if (!isset($this->args[self::TAG_STATUS])) {
$this->args[self::TAG_STATUS] = [];
}
$this->args[self::TAG_STATUS][] = [
'text' => $this->trans($message, $domain),
'severity' => $type,
];
return $this;
}
public static function addStatusFromService(
string $message,
string $type = self::STATUS_MESSAGE,
?string $domain = null
): void
{
self::$messagesFromService[] = [
'text' => $message,
'severity' => $type,
'domain' => $domain,
];
}
public function addButton(
string $url,
string $label,
string $icon,
string $class = '',
?string $domain = null,
string $wrapper = '',
bool $fetch = true
): self
{
if (!isset($this->args[self::TAG_BUTTONS])) {
$this->args[self::TAG_BUTTONS] = [];
}
$this->args[self::TAG_BUTTONS][] = [
'url' => $url,
'label' => $this->trans($label, $domain),
'icon' => $icon,
'class' => $class,
'wrapper' => $wrapper,
'fetch' => $fetch,
];
return $this;
}
public function addException(Exception $exception): self
{
return $this->setError('Exception', $exception->getMessage());
}
public function addJS(string $js): self
{
if (!isset($this->args[self::TAG_JAVASCRIPT])) {
$this->args[self::TAG_JAVASCRIPT] = '';
}
$this->args[self::TAG_JAVASCRIPT] .= $js;
return $this;
}
public function getRepository(string $class): ObjectRepository
{
return $this->getDoctrine()->getManager()->getRepository($class);
}
public function persist(): self
{
foreach (func_get_args() as $entity) {
$this->getDoctrine()->getManager()->persist($entity);
}
return $this;
}
public function remove(): self
{
foreach (func_get_args() as $entity) {
$this->getDoctrine()->getManager()->remove($entity);
}
return $this;
}
public function clear(): self
{
foreach (func_get_args() as $entity) {
$this->getDoctrine()->getManager()->clear($entity);
}
return $this;
}
public function detach(): self
{
foreach (func_get_args() as $entity) {
$this->getDoctrine()->getManager()->detach($entity);
}
return $this;
}
public function flush(): self
{
if (count(func_get_args())) {
foreach (func_get_args() as $entity) {
$this->getDoctrine()->getManager()->flush($entity);
}
} else {
$this->getDoctrine()->getManager()->flush();
}
return $this;
}
public function trans(string $string, string $domain = null, array $args = [], ?string $locale = null): string
{
return $this->translator->trans($string, $args, $domain, $locale);
}
public function keepModalOpened(): self
{
$this->args[self::TAG_KEEP_MODAL_OPENED] = true;
return $this;
}
public function keepSideBarModalOpened(): self
{
$this->args[self::TAG_KEEP_SIDEBAR_MODAL_OPENED] = true;
return $this;
}
public function scrollToTop(): self
{
$this->args[self::TAG_SCROLL_TO_TOP] = true;
return $this;
}
public function openOnboarding($datas): self
{
$this->args[self::TAG_ONBOARDING] = json_encode($datas);
return $this;
}
public function redirectByFetch(string $url): Response
{
return $this
->setMain(
'Athena/redirect',
[
'url' => $url,
]
)
->getResponse();
}
public function redirectToRouteByFetch(string $route, array $parameters = []): Response
{
return $this->redirectByFetch($this->generateUrl($route, $parameters));
}
#[Route('/', name: 'home')]
public function home(): Response
{
return $this->redirectToRoute('admin');
}
#[Route('/admin', name: 'admin')]
public function admin(): Response
{
return $this->getResponse();
}
#[Route('/health_check', name: 'healthCheck')]
public function healthCheck(?Profiler $profiler): Response
{
$profiler?->disable();
$return = [];
try {
if (!$this->getRepository(User::class)->find(1)) {
throw new \Exception('Problème de connexion à la DB', 1, null);
}
$return['DB'] = 'OK';
} catch (\Exception $e) {
return new Response(json_encode(['error' => $e->getCode(), 'message' => $e->getMessage(), 'line' => $e->getLine()]), 500);
}
return new Response(json_encode($return), 200);
}
public function handleGenericForm(
Request $request,
mixed $object,
string $type,
array $optionsForRoute = [],
bool $delete = false,
array $options = [],
?object $service = null,
?string $preProcess = null,
?string $postProcess = null,
?string $updateProcess = null,
?string $validateProcess = null,
): object
{
if (is_string($object)) {
$object = new $object();
}
$form = $this->createForm(
$type,
$object,
array_merge(
['action' => $this->generateUrl($request->attributes->get('_route'), $optionsForRoute)],
$options
)
);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($service && $validateProcess) {
$service->$validateProcess($object, $form);
}
if ($form->isValid()) {
if ($service && $preProcess) {
try {
$service->$preProcess($object, $form);
} catch (\Exception $e) {
$this->addException($e);
return $form;
}
}
if ($service && $updateProcess) {
try {
$service->$updateProcess($object, $form);
} catch (\Exception $e) {
$this->addException($e);
return $form;
}
} elseif ($object) {
if ($delete) {
$this->remove($object)->flush();
} else {
$this->persist($object)->flush();
}
}
if ($service && $postProcess) {
try {
$service->$postProcess($object, $form, $this);
} catch (\Exception $e) {
$this->addException($e);
return $form;
}
}
return $object;
}
}
return $form;
}
public function getAvailableRoles(): array
{
$result = [];
foreach ($this->getParameter('security.role_hierarchy.roles') as $role => $roles) {
$result[$this->trans('User.controller.User.Roles.' . $role, 'Athena')] = $role;
}
krsort($result);
if (!$this->security->isGranted('ROLE_SUPER_ADMIN')) {
unset($result['ROLE_SUPER_ADMIN']);
}
return $result;
}
public function getTranslatedAvailableRoles(): array
{
$result = [];
foreach ($this->getParameter('security.role_hierarchy.roles') as $role => $roles) {
$result[$role] = $this->trans('User.controller.User.Roles.' . $role, 'Athena');
}
ksort($result);
if (!$this->security->isGranted('ROLE_SUPER_ADMIN')) {
unset($result['ROLE_SUPER_ADMIN']);
}
return $result;
}
public function _datatableIndex(
string $template = 'Athena/datatable',
bool $addButton = true,
bool $searchField = true,
array $additionalButton = [],
?string $getDatatableUrl = null,
?string $createUrl = null
): Response
{
$this
->setMainTitle(
$this->translator->trans(
$this->entityName . '.controller.' . $this->entityName . '.main_title',
[],
$this->domain
)
)
->setMain(
$template,
[
'datatableUrl' => $getDatatableUrl ?: $this->generateUrl($this->routePrefix . 'GetDatatable'),
'other' => $this->otherData,
'searchField' => (int)$searchField
]
);
if ($addButton) {
$this->addButton(
$createUrl ?: $this->generateUrl($this->routePrefix . 'Create'),
$this->entityName . '.controller.' . $this->entityName . '.buttons.create',
'add_circle_outline',
'',
$this->domain
);
}
if (!empty($additionalButton)) {
$this->addButton(
$additionalButton['url'] ?? '',
$additionalButton['text'] ?? '',
$additionalButton['icon'] ?? '',
'',
$this->domain
);
}
return $this->getResponse();
}
public function _datatable(
int $page = 1,
int $limit = 1,
string $sort = 'none',
string $search = '',
string $datatableTemplate = 'Default',
?ContextService $context = null,
?array $preLoadedDatas = null,
string $templateForPreload = '',
array $optionsForPreload = [],
array $additionalSearchField = [],
int $countForPreload = -1
): Response
{
$session = $this->request->getSession();
$datatablesFilters = $session->get('datatablesFilters', []);
if ($this->request->get('firstLoad', false)) {
if (isset($datatablesFilters[$this->routePrefix])) {
$search = $datatablesFilters[$this->routePrefix]['search'] ?? '';
$additionalSearchField = $datatablesFilters[$this->routePrefix]['additionalSearchField'] ?? [];
}
} else {
$datatablesFilters[$this->routePrefix] = [
'search' => $search,
'additionalSearchField' => $additionalSearchField,
];
$session->set('datatablesFilters', $datatablesFilters);
}
$this->setContent(
'entity',
$this->translator->trans(
$this->entityName . '.template.index.entity.plural',
[],
$this->domain
)
);
$datatable = $this->datatableService->buildDatatable(
$this->entityClass,
$page,
$limit,
$sort,
$search,
$datatableTemplate,
$context,
$preLoadedDatas,
$templateForPreload,
$optionsForPreload,
$additionalSearchField,
$countForPreload
);
foreach ($datatable as $key => $val) {
$this->setContent($key, $val);
}
return $this->getResponse();
}
public function _create(
Request $request,
string $formClass,
array $optionsForRoute = [],
bool $delete = false,
array $options = [],
?object $service = null,
?string $preProcess = null,
?string $postProcess = null,
?string $updateProcess = null,
?string $validateProcess = null,
bool $modal = true,
string $content = 'Athena/genericType',
array $args = [],
bool $returnRequest = false,
string $postUpdateMessage = null,
string $postUpdateStatus = null,
array $buttonAttribute = [],
?string $entityName = null,
?object $object = null,
?string $postRedirectUrl = null,
)
{
$return = $this->handleGenericForm(
$request,
$object ?: $this->entityClass,
$formClass,
$optionsForRoute,
$delete,
$options,
$service,
$preProcess,
$postProcess,
$updateProcess,
$validateProcess
);
if ($return instanceof $this->entityClass) {
if ($postUpdateMessage) {
$this->addStatus($postUpdateMessage, $postUpdateStatus ?? self::STATUS_MESSAGE);
}
if ($postRedirectUrl) {
return $this
->setRedirect($postRedirectUrl)
->getResponse();
} elseif ($returnRequest) {
return $this->index($request);
} else {
return $this->index();
}
} else {
if ($modal) {
$this->setModal(
($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.createTitle',
$content,
array_merge($args, ['form' => $return->createView(), 'entity' => ($entityName ?? $this->entityName)]),
$this->domain
);
} else {
$this->setMainTitle(
$this->translator->trans(
$this->entityName . '.controller.' . $this->entityName . '.main.createTitle',
[],
$this->domain
)
)
->setMain(
$content,
array_merge($args, ['form' => $return->createView(), 'entity' => $this->entityName])
);
if ($buttonAttribute && !empty($buttonAttribute)) {
$this->addButton(
$this->generateUrl($buttonAttribute['url']),
$this->entityName . '.controller.' . $this->entityName . '.buttons.' . $buttonAttribute['label'],
$buttonAttribute['icon'],
$buttonAttribute['class'],
$buttonAttribute['transDomain']
);
}
}
return $this->getResponse();
}
}
public function _update(
Request $request,
object $object,
string $formClass,
array $optionsForRoute = [],
bool $delete = false,
array $options = [],
?object $service = null,
?string $preProcess = null,
?string $postProcess = null,
?string $updateProcess = null,
?string $validateProcess = null,
bool $modal = true,
string $content = 'Athena/genericType',
array $args = [],
bool $returnRequest = false,
string $postUpdateMessage = null,
string $postUpdateStatus = null,
?string $entityName = null,
?string $postRedirectUrl = null,
): Response
{
$return = $this->handleGenericForm(
$request,
$object,
$formClass,
$optionsForRoute,
$delete,
$options,
$service,
$preProcess,
$postProcess,
$updateProcess,
$validateProcess
);
if ($return instanceof $this->entityClass) {
if ($postUpdateMessage) {
$this->addStatus($postUpdateMessage, $postUpdateStatus ?? self::STATUS_MESSAGE);
}
if ($postRedirectUrl) {
return $this
->setRedirect($postRedirectUrl)
->getResponse();
} elseif ($returnRequest) {
return $this->index($request);
} else {
return $this->index();
}
} else {
if ($modal) {
$this
->setModal(
($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.updateTitle',
$content,
array_merge($args, ['form' => $return->createView(), 'entity' => ($entityName ?? $this->entityName)]),
$this->domain
);
} else {
$this->setMainTitle(
$this->translator->trans(
$this->entityName . '.controller.' . $this->entityName . '.main.updateTitle',
[],
$this->domain
)
)
->setMain(
$content,
array_merge($args, ['form' => $return->createView(), 'entity' => $this->entityName])
);
}
return $this->getResponse();
}
}
public function _delete(
Request $request,
object $object,
$optionsForRoute,
string $postUpdateMessage = null,
string $postUpdateStatus = null,
array $options = [],
?object $service = null,
?string $preProcess = null,
?string $postProcess = null,
?string $updateProcess = null,
?string $validateProcess = null,
bool $returnRequest = false,
?string $entityName = null,
?string $postRedirectUrl = null,
)
{
if (($return = $this->handleGenericForm(
$request,
$object,
DeleteForm::class,
$optionsForRoute,
true,
$options,
$service,
$preProcess,
$postProcess,
$updateProcess,
$validateProcess
)) instanceof $this->entityClass) {
if ($postUpdateMessage) {
$this->addStatus($postUpdateMessage, $postUpdateStatus ?? self::STATUS_MESSAGE);
}
if ($postRedirectUrl) {
return $this
->setRedirect($postRedirectUrl)
->getResponse();
} elseif ($returnRequest) {
return $this->index($request);
} else {
return $this->index();
}
} else {
return $this
->setModal(
($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.deleteTitle',
'Athena/deleteType',
[
'form' => $return->createView(),
'entity' => $this->translator->trans(
($entityName ?? $this->entityName) . '.controller.' . ($entityName ?? $this->entityName) . '.modal.entity',
[],
$this->domain
),
],
$this->domain
)
->getResponse();
}
}
public function _autocomplete(string $search, ?string $entityClass = null): JsonResponse
{
$result = array();
if ($search) {
foreach ($this->getRepository($entityClass ?? $this->entityClass)->getAutocomplete($search) as $object) {
$result[] = ['id' => $object->getId(), 'text' => $object->_toAutocomplete()];
}
}
return $this->json($result);
}
public function _show(
string $content,
bool $modal = false,
array $args = [],
array $translateParameters = []
): Response
{
if ($modal) {
$this
->setModal(
$this->entityName . '.controller.' . $this->entityName . '.modal.showTitle',
$content,
array_merge($args, ['entity' => $this->entityName]),
$this->domain
);
} else {
$this->setMainTitle(
$this->translator->trans(
$this->entityName . '.controller.' . $this->entityName . '.main.showTitle',
$translateParameters,
$this->domain
)
)
->setMain(
$content,
array_merge($args, ['entity' => $this->entityName])
);
}
return $this->getResponse();
}
public function getContext(): ContextService
{
return $this->context;
}
public function setTargetBlank(string $url, ?array $args = null): self
{
return $this->setContent(self::TAG_TARGET_BLANK, $url, $args);
}
public function setFormTargetBlank(string $url, string $datas, ?array $args = null): self
{
return $this
->setContent(self::TAG_FORM_BLANK, $url, $args)
->setContent(self::TAG_FORM_BLANK_DATAS, $datas, $args);
}
public function setFunctionOnLoad(string $function): self
{
return $this->setContent(self::TAG_FUNCTION_ON_LOAD, $function);
}
public function _extract(
Request $request,
mixed $class = '',
string $filename = '',
string $search = '',
array $additionalSearchFields = [],
string $datatableTemplate = '',
$context = null
)
{
if (is_array($class)) {
$object = $class['data'];
if (isset($request->request->all()['extract_fields'])) {
$columns = [];
foreach ($request->request->all() as $key => $value) {
if ($key !== 'extract_fields' && $value == 'on') {
$columns[] = $this->trans($key, 'fields');
}
}
if (empty($columns)) {
return $this->addStatus("Vous devez sélectionner une colonne pour l'extraction!", self::STATUS_ERROR)->setRedirect($this->generateUrl($this->routePrefix . 'Index'))->getResponse();
} else {
$res = $this->datatableService->filterArray($object, $columns);
foreach ($res as &$line) {
foreach ($line as $key => $val) {
if (isset($class['options']['extract']['fields'][$key])) {
$line[$this->trans($class['options']['extract']['fields'][$key], 'fields')] = $val;
unset($line[$key]);
}
}
}
$fileName = $this->datatableService->export_data_to_csv($res, $filename);
$this->setTargetBlank($this->generateUrl($this->routePrefix . 'DownloadExtract', ['filename' => $fileName]));
return $this->addStatus("Le fichier a bien été téléchargé!", self::STATUS_MESSAGE)->setRedirect($this->generateUrl($this->routePrefix . 'Index'))
->getResponse();
}
}
$params = '';
foreach ($additionalSearchFields as $param) {
$params = $params . '/' . $param;
}
if (!empty($search)) {
$params = $params . '/' . $search;
}
return $this
->setModal(
$this->entityName . '.controller.' . $this->entityName . '.modal.extractTitle',
'Athena/extractFields',
[
'url' => $this->generateUrl($this->routePrefix . 'Extract') . $params,
'options' => $class['options']
],
$this->domain
)
->getResponse();
} else {
$object = new $class;
if (isset($request->request->all()['extract_fields'])) {
$columns = [];
foreach ($request->request->all() as $key => $value) {
if ($key !== 'extract_fields' && $value == 'on') {
$columns[] = $key;
}
}
if (empty($columns)) {
return $this->addStatus("Vous devez sélectionner une colonne pour l'extraction!", self::STATUS_ERROR)->setRedirect($this->generateUrl($this->routePrefix . 'Index'))->getResponse();
} else {
$dat = $this->getRepository($class)->getDatatableForDownload($search, $datatableTemplate, $context, $additionalSearchFields);
$arrayDat = $this->datatableService->entityToArray($dat, $columns, $class);
$fileName = $this->datatableService->export_data_to_csv($arrayDat, $filename);
$this->setTargetBlank($this->generateUrl($this->routePrefix . 'DownloadExtract', ['filename' => $fileName]));
return $this->addStatus("Le fichier a bien été téléchargé!", self::STATUS_MESSAGE)->setRedirect($this->generateUrl($this->routePrefix . 'Index'))
->getResponse();
}
}
$params = '';
foreach ($additionalSearchFields as $param) {
$params = $params . '/' . $param;
}
if (!empty($search)) {
$params = $params . '/' . $search;
}
return $this
->setModal(
$this->entityName . '.controller.' . $this->entityName . '.modal.extractTitle',
'Athena/extractFields',
[
'url' => $this->generateUrl($this->routePrefix . 'Extract') . $params,
'options' => $object->_getMetadataDefault()
],
$this->domain
)
->getResponse();
}
}
public function handleS3Files(array $datas, string $subject, string $body): Response
{
if (isset($datas['s3Files'])) {
$this->setFormTargetBlank($this->generateUrl('adminAwsS3Download'), json_encode($datas));
} elseif (isset($datas['files'])) {
$this->setWaitingModal(json_encode($datas['files']), $subject, $body);
} else {
$this->addStatus('Une erreur est survenue lors de la création du fichier : ' . print_r($datas, 1), self::STATUS_ERROR);
}
return $this->getResponse();
}
/**
* @return false|string
*/
public function getVideoTutorialUrl(?string $route = null): string|false
{
$route ??= $this->request->attributes->get('_route');
$videoTutorial = $this->getRepository(VideoTutorial::class)->findOneByRoute($route);
return $videoTutorial ? $this->generateUrl(
'adminVideoViewerIndex',
[
'videoUrl' => $videoTutorial->getUrl(),
'title' => $videoTutorial->getTitle() ?: 'Tutoriel vidéo',
]
) : false;
}
private function canEditVideoTutorial(): string
{
$user = $this->getUser();
if ($this->security->isGranted('IS_IMPERSONATOR')) {
$user = $this->security->getToken()->getOriginalToken()->getUser();
}
return in_array('ROLE_SUPER_ADMIN', $user?->getRoles(), true) ? '1' : '0';
}
}