src/Controller/Back/StaticController.php line 55

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Back;
  3. use App\Client\Algolia\Exception\ClientException;
  4. use App\Entity\BackUser;
  5. use App\Entity\BackUserLog;
  6. use App\Entity\Contact;
  7. use App\Entity\Newsletter;
  8. use App\Entity\Page;
  9. use App\Entity\Utils\History;
  10. use App\Entity\Utils\Notification;
  11. use App\Form\FeaturesType;
  12. use App\Form\Model\Features;
  13. use App\Form\Model\Settings;
  14. use App\Form\SettingsType;
  15. use App\Repository\BackUserLogRepository;
  16. use App\Repository\ContactRepository;
  17. use App\Repository\NewsletterRepository;
  18. use App\Repository\PageRepository;
  19. use App\Repository\Utils\HistoryRepository;
  20. use App\Repository\Utils\NotificationRepository;
  21. use App\Service\Algolia\AnalyticsService as AlgoliaAnalyticsService;
  22. use App\Service\Google\AnalyticsService;
  23. use App\Utils\FormHelper;
  24. use Doctrine\Persistence\ManagerRegistry;
  25. use GuzzleHttp\Exception\GuzzleException;
  26. use Psr\Cache\InvalidArgumentException;
  27. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  28. use Symfony\Component\HttpFoundation\JsonResponse;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use Symfony\Component\HttpFoundation\Response;
  31. use Symfony\Component\Routing\Annotation\Route;
  32. use Symfony\Contracts\Translation\TranslatorInterface;
  33. #[Route('/back')]
  34. class StaticController extends AbstractController
  35. {
  36.     /**
  37.      * StaticController constructor.
  38.      */
  39.     public function __construct(
  40.         protected AnalyticsService $googleAnalyticsService,
  41.         protected AlgoliaAnalyticsService $algoliaAnalyticsService,
  42.         protected TranslatorInterface $translator,
  43.         protected ManagerRegistry $registry
  44.     ) {
  45.     }
  46.     /**
  47.      * @throws InvalidArgumentException
  48.      * @throws \Exception
  49.      */
  50.     #[Route(''name'back_static_index')]
  51.     public function index(): Response
  52.     {
  53.         /** @var BackUser $user */
  54.         $user  $this->getUser();
  55.         $today = new \DateTime();
  56.         /** @var HistoryRepository $historyRepository */
  57.         $historyRepository $this->registry->getRepository(History::class);
  58.         /** @var BackUserLogRepository $userLogRepository */
  59.         $userLogRepository $this->registry->getRepository(BackUserLog::class);
  60.         /** @var NotificationRepository $notificationRepository */
  61.         $notificationRepository $this->registry->getRepository(Notification::class);
  62.         /** @var ContactRepository $contactRepository */
  63.         $contactRepository $this->registry->getRepository(Contact::class);
  64.         /** @var NewsletterRepository $newsletterRepository */
  65.         $newsletterRepository $this->registry->getRepository(Newsletter::class);
  66.         /** @var PageRepository $pageRepository */
  67.         $pageRepository $this->registry->getRepository(Page::class);
  68.         $histories       $historyRepository->getLastEntries($today);
  69.         $lastConnections $userLogRepository->countConnectionsByUserOnCurrentMonth($user->getId());
  70.         $notificationCpt $notificationRepository->countByUser($user->getId());
  71.         $contactCpt      $contactRepository->countContact();
  72.         $pageCpt         $pageRepository->countPage();
  73.         $newsletterCpt   $newsletterRepository->countSubscription();
  74.         $settings  = new Settings();
  75.         $analytics null;
  76.         if ($settings->getGoogleAnalyticsAuthFile()) {
  77.             $analytics $this->googleAnalyticsService->getFullAnalytics('30daysAgo''today');
  78.         }
  79.         return $this->render('back/static/index.html.twig', [
  80.             'analytics'       => $analytics,
  81.             'histories'       => $histories,
  82.             'lastConnections' => $lastConnections[0][1],
  83.             'notificationCpt' => $notificationCpt[0][1],
  84.             'contactCpt'      => $contactCpt[1],
  85.             'pageCpt'         => $pageCpt[1],
  86.             'newsletterCpt'   => $newsletterCpt[1],
  87.         ]);
  88.     }
  89.     #[Route('/insights/search'name'back_static_insights_search')]
  90.     public function search(): Response
  91.     {
  92.         $allIndexes $this->algoliaAnalyticsService->getAllIndexes();
  93.         return $this->render('back/static/search.html.twig', [
  94.             'allIndexes' => $allIndexes,
  95.         ]);
  96.     }
  97.     #[Route('/insights/analytics'name'back_static_insights_analytics')]
  98.     public function analytics(): Response
  99.     {
  100.         $settings = new Settings();
  101.         if (!$settings->getGoogleAnalyticsAuthFile()) {
  102.             throw $this->createNotFoundException('Analytics not configured !');
  103.         }
  104.         return $this->render('back/static/analytics.html.twig');
  105.     }
  106.     #[Route('/insights/stats'name'back_static_insights_stats')]
  107.     public function stats(): Response
  108.     {
  109.         return $this->render('back/custom/static/stats.html.twig', [
  110.         ]);
  111.     }
  112.     /**
  113.      * @throws InvalidArgumentException
  114.      * @throws \Exception
  115.      */
  116.     #[Route('/analytics/kpi'name'back_static_analytics_kpi')]
  117.     public function analyticsKpiMetrics(Request $request): JsonResponse
  118.     {
  119.         $dateStart $request->get('dateStart''2018-04-08');
  120.         $dateEnd   $request->get('dateEnd''2018-05-08');
  121.         $metrics = [
  122.             'sessions',
  123.             'users',
  124.             'sessionsPerUser',
  125.             'bounceRate',
  126.             'pageviews',
  127.             'pageviewsPerSession',
  128.             'avgTimeOnPage',
  129.             'percentNewSessions',
  130.             'exitRate',
  131.         ];
  132.         $data $this->googleAnalyticsService->getMetricsReport($metrics$dateStart$dateEnd);
  133.         return new JsonResponse($data);
  134.     }
  135.     /**
  136.      * @throws InvalidArgumentException
  137.      * @throws \Exception
  138.      */
  139.     #[Route('/analytics/speed'name'back_static_analytics_speed')]
  140.     public function analyticsSpeedMetrics(Request $request): JsonResponse
  141.     {
  142.         $dateStart $request->get('dateStart''2018-04-08');
  143.         $dateEnd   $request->get('dateEnd''2018-05-08');
  144.         $metrics = [
  145.             'avgPageLoadTime',
  146.             'avgDomainLookupTime',
  147.             'avgPageDownloadTime',
  148.             'avgRedirectionTime',
  149.             'avgServerConnectionTime',
  150.             'avgServerResponseTime',
  151.             'avgDomInteractiveTime',
  152.             'avgDomContentLoadedTime',
  153.         ];
  154.         $data $this->googleAnalyticsService->getMetricsReport($metrics$dateStart$dateEnd);
  155.         return new JsonResponse($data);
  156.     }
  157.     /**
  158.      * @throws InvalidArgumentException
  159.      * @throws \Exception
  160.      */
  161.     #[Route('/analytics/chart'name'back_static_analytics_chart')]
  162.     public function analyticsChart(Request $request): JsonResponse
  163.     {
  164.         $sort          = [];
  165.         $data          = [];
  166.         $metricsStr    $request->get('metrics''users'); // maybe null instead of user ?
  167.         $dimensionsStr $request->get('dimensions''date'); // maybe null instead of date ?
  168.         $sortStr       $request->get('sort');
  169.         $order         $request->get('order');
  170.         $limit         $request->get('limit');
  171.         if (null === $metricsStr) {
  172.             new JsonResponse([]);
  173.         }
  174.         $dateStart   $request->get('dateStart''2018-04-08');
  175.         $dateEnd     $request->get('dateEnd''2018-05-08');
  176.         $getPrevious 'true' === $request->get('getPrevious');
  177.         $start \DateTime::createFromFormat('Y-m-d'$dateStart);
  178.         $end   \DateTime::createFromFormat('Y-m-d'$dateEnd);
  179.         $diff  $end->diff($start)->format('%a');
  180.         if ($getPrevious) {
  181.             $previousEnd   \DateTime::createFromFormat('Y-m-d'$dateStart);
  182.             $previousEnd   $previousEnd->sub(new \DateInterval('P1D'));
  183.             $previousStart = new \DateTime($previousEnd->format('Y-m-d'));
  184.             $previousStart $previousStart->sub(new \DateInterval('P'.$diff.'D'));
  185.         }
  186.         $metrics    explode(',', (string) $metricsStr);
  187.         $dimensions explode(',', (string) $dimensionsStr);
  188.         if (null !== $sortStr) {
  189.             $sort['fields'] = explode(',', (string) $sortStr);
  190.             $sort['order']  = $order;
  191.         } else {
  192.             $sort null;
  193.         }
  194.         if ($getPrevious) {
  195.             $result                               $this->googleAnalyticsService->getDataDateRangeMetricsDimensions($previousStart->format('Y-m-d'), $dateEnd$metrics$dimensions$sortnullnull$limit);
  196.             [$data['previous'], $data['current']] = array_chunk($resultceil(count($result) / 2));
  197.         } else {
  198.             $data $this->googleAnalyticsService->getDataDateRangeMetricsDimensions($dateStart$dateEnd$metrics$dimensions$sortnullnull$limit);
  199.         }
  200.         return new JsonResponse($data);
  201.     }
  202.     #[Route('/activity'name'back_static_activity')]
  203.     public function activity(): Response
  204.     {
  205.         return $this->render('back/static/activity.html.twig', [
  206.             'url' => $this->generateUrl('back_activity_paginate'),
  207.         ]);
  208.     }
  209.     /**
  210.      * @throws \Exception
  211.      */
  212.     #[Route('/activity/paginate'name'back_activity_paginate')]
  213.     public function paginateActivity(Request $request): Response
  214.     {
  215.         $today    = new \DateTime();
  216.         $nextDate null;
  217.         $date     $request->get('date'$today->format('Ymd'));
  218.         /** @var HistoryRepository $repository */
  219.         $repository $this->registry->getRepository(History::class);
  220.         $date       \DateTime::createFromFormat('Ymd'$date);
  221.         $items $repository->paginate($date);
  222.         return $this->render('back/static/partials/activity/block.html.twig', [
  223.             'date'     => $date,
  224.             'nextDate' => $nextDate,
  225.             'items'    => $items,
  226.         ]);
  227.     }
  228.     #[Route('/members-logs'name'back_static_log')]
  229.     public function log(): Response
  230.     {
  231.         return $this->render('back/static/user-log.html.twig', [
  232.             'url' => $this->generateUrl('back_log_paginate'),
  233.         ]);
  234.     }
  235.     /**
  236.      * @throws \Exception
  237.      */
  238.     #[Route('/members-logs/paginate'name'back_log_paginate')]
  239.     public function paginateLog(Request $request): Response
  240.     {
  241.         $today    = new \DateTime();
  242.         $nextDate null;
  243.         $date     $request->get('date'$today->format('Ymd'));
  244.         /** @var BackUserLogRepository $repository */
  245.         $repository $this->registry->getRepository(BackUserLog::class);
  246.         $date       \DateTime::createFromFormat('Ymd'$date);
  247.         $items $repository->paginate($date);
  248.         return $this->render('back/static/partials/user-log/block.html.twig', [
  249.             'date'     => $date,
  250.             'nextDate' => $nextDate,
  251.             'items'    => $items,
  252.         ]);
  253.     }
  254.     #[Route('/settings'name'back_static_settings')]
  255.     public function settings(Request $request): JsonResponse|Response
  256.     {
  257.         $settings = new Settings();
  258.         $this->denyAccessUnlessGranted('edit'$settings);
  259.         $form $this->createForm(SettingsType::class, $settings);
  260.         if ('POST' == $request->getMethod()) {
  261.             $data FormHelper::getDataDecoded($request->getContent(), 'json');
  262.             $form->setData($data['settings']);
  263.             $form->submit($data['settings']);
  264.             $featuresValid true;
  265.             if (isset($data['features'])) {
  266.                 $features = new Features();
  267.                 $this->denyAccessUnlessGranted('edit'$features);
  268.                 $formFeatures $this->createForm(FeaturesType::class, $features);
  269.                 $formFeatures->setData($data['features']);
  270.                 $formFeatures->submit($data['features']);
  271.                 if ($formFeatures->isSubmitted() && $formFeatures->isValid()) {
  272.                     $features->exportFile();
  273.                 } else {
  274.                     $featuresValid false;
  275.                 }
  276.             }
  277.             if ($form->isSubmitted() && $form->isValid() && $featuresValid) {
  278.                 $settings->exportFile();
  279.                 return new JsonResponse([
  280.                     'success' => true,
  281.                 ]);
  282.             }
  283.             return new JsonResponse([
  284.                 'success' => false,
  285.                 'error'   => [
  286.                     'title'       => $this->translator->trans('form.error.main.title'),
  287.                     'description' => $this->translator->trans('form.error.main.description'),
  288.                 ],
  289.                 'errors'  => FormHelper::getErrorMessages($form),
  290.             ]);
  291.         }
  292.         $form FormHelper::getData($form);
  293.         // replace this example code with whatever you need
  294.         return $this->render('back/static/settings.html.twig', [
  295.             'form' => $form['settings']['children'],
  296.         ]);
  297.     }
  298.     #[Route('/features/form'name'back_static_features')]
  299.     public function features(Request $request): JsonResponse|Response
  300.     {
  301.         $password $request->query->get('password'null);
  302.         $features = new Features();
  303.         $this->denyAccessUnlessGranted('edit'$features);
  304.         if (!$password || !$features->isValidPassword($password)) {
  305.             return new JsonResponse([
  306.                 'success' => false,
  307.                 'error'   => [
  308.                     'title'       => 'Access denied',
  309.                     'description' => 'Either you enter a wrong password or you don\'t have enough rights to access this part...',
  310.                 ],
  311.             ]);
  312.         }
  313.         $form $this->createForm(FeaturesType::class, $features);
  314.         $form FormHelper::getData($form);
  315.         // replace this example code with whatever you need
  316.         return new JsonResponse([
  317.             'success' => true,
  318.             'view'    => $this->renderView('back/static/partials/features.html.twig', [
  319.                 'form' => $form['features']['children'],
  320.             ]),
  321.         ]);
  322.     }
  323.     #[Route('/help'name'back_static_help')]
  324.     public function help(): Response
  325.     {
  326.         // replace this example code with whatever you need
  327.         return $this->render('back/custom/static/help.html.twig');
  328.     }
  329.     #[Route('/about'name'back_static_about')]
  330.     public function about(): Response
  331.     {
  332.         // replace this example code with whatever you need
  333.         return $this->render('back/static/about.html.twig');
  334.     }
  335.     #[Route('/notification-center'name'back_static_notification')]
  336.     public function notification(): Response
  337.     {
  338.         // replace this example code with whatever you need
  339.         return $this->render('back/static/notification.html.twig', [
  340.             'url' => $this->generateUrl('back_notification_paginate'),
  341.         ]);
  342.     }
  343.     #[Route('/notification-center/paginate'name'back_notification_paginate')]
  344.     public function paginateNotification(Request $request): Response
  345.     {
  346.         $page  $request->get('page'0);
  347.         $limit $request->get('limit'30);
  348.         $user  $this->getUser();
  349.         /** @var NotificationRepository $repository */
  350.         $repository $this->registry->getRepository(Notification::class);
  351.         $items $repository->paginate($user->getId(), $limit$page $limit);
  352.         return $this->render('back/static/partials/notification/block.html.twig', [
  353.             'items' => $items,
  354.         ]);
  355.     }
  356.     /**
  357.      * @throws \Exception
  358.      */
  359.     public function findNextDate(\DateTime $date): \DateTime
  360.     {
  361.         $repository $this->registry->getRepository(History::class);
  362.         $nextDate $date;
  363.         $nextDate->sub(new \DateInterval('P1D'));
  364.         /** @var HistoryRepository $repository */
  365.         $items $repository->paginate($nextDate);
  366.         if ($items) {
  367.             return $nextDate->add(new \DateInterval('P1D'));
  368.         }
  369.         return $this->findNextDate($nextDate);
  370.     }
  371.     #[Route('/preview-mode'name'back_static_preview_mode')]
  372.     public function previewMode(Request $request): Response
  373.     {
  374.         // replace this example code with whatever you need
  375.         return $this->render('back/static/preview-mode.html.twig', [
  376.             'url' => $request->get('url'),
  377.         ]);
  378.     }
  379.     /**
  380.      * @throws ClientException
  381.      * @throws GuzzleException
  382.      * @throws InvalidArgumentException
  383.      * @throws \Exception
  384.      */
  385.     #[Route('/search/performances'name'back_static_search_performances')]
  386.     public function algoliaGlobalPerformances(Request $request): JsonResponse
  387.     {
  388.         $data $this->algoliaAnalyticsService->getGlobalPerformances(
  389.             new \DateTime($request->get('dateStart')),
  390.             new \DateTime($request->get('dateEnd'))
  391.         );
  392.         return $this->json(
  393.             $data
  394.         );
  395.     }
  396.     /**
  397.      * @throws ClientException
  398.      * @throws GuzzleException
  399.      * @throws InvalidArgumentException
  400.      * @throws \Exception
  401.      */
  402.     #[Route('/search/daily'name'back_static_search_daily')]
  403.     public function algoliaSearchPerformances(Request $request): JsonResponse
  404.     {
  405.         $data $this->algoliaAnalyticsService->getSearchPerformances(
  406.             new \DateTime($request->get('dateStart')),
  407.             new \DateTime($request->get('dateEnd'))
  408.         );
  409.         return new JsonResponse(
  410.             $data
  411.         );
  412.     }
  413.     /**
  414.      * @throws ClientException
  415.      * @throws GuzzleException
  416.      * @throws \Exception
  417.      */
  418.     #[Route('/search/countries'name'back_static_search_countries')]
  419.     public function algoliaSearchByCountries(Request $request): JsonResponse
  420.     {
  421.         $data $this->algoliaAnalyticsService->getTopCountries(
  422.             new \DateTime($request->get('dateStart')),
  423.             new \DateTime($request->get('dateEnd'))
  424.         );
  425.         return new JsonResponse($data);
  426.     }
  427.     /**
  428.      * @throws \Exception
  429.      */
  430.     #[Route('/prospects/daily'name'back_prospects_daily')]
  431.     public function prospectsDaily(Request $request): JsonResponse
  432.     {
  433.         /** @var ContactRepository $contactRepository */
  434.         $contactRepository $this->registry->getRepository(Contact::class);
  435.         /** @var NewsletterRepository $newsletterRepository */
  436.         $newsletterRepository $this->registry->getRepository(Newsletter::class);
  437.         $from = new \DateTime($request->get('dateStart'));
  438.         $to   = new \DateTime($request->get('dateEnd'));
  439.         $contacts    $contactRepository->findContactsPerDay($from$to);
  440.         $newsletters $newsletterRepository->findNewslettersPerDay($from$to);
  441.         // arrange datas
  442.         $interval $from->diff($to);
  443.         $diff     $interval->format('%a');
  444.         $contactDatas    = [];
  445.         $newsletterDatas = [];
  446.         for ($i 0$i <= $diff; ++$i) {
  447.             $date                 = new \DateTime($from->format('Y-m-d'));
  448.             $date                 $date->modify('+'.$i.' day');
  449.             $df                   $date->format('Ymd');
  450.             $contactDatas[$df]    = 0;
  451.             $newsletterDatas[$df] = 0;
  452.             foreach ($contacts as $item) {
  453.                 if ($item['date'] == $df) {
  454.                     $contactDatas[$df] = intval($item['value']);
  455.                 }
  456.             }
  457.             foreach ($newsletters as $item) {
  458.                 if ($item['date'] == $df) {
  459.                     $newsletterDatas[$df] = intval($item['value']);
  460.                 }
  461.             }
  462.         }
  463.         $data = [
  464.             'contacts'    => $contactDatas,
  465.             'newsletters' => $newsletterDatas,
  466.         ];
  467.         return new JsonResponse(
  468.             $data
  469.         );
  470.     }
  471. }