src/Controller/PublicApiController.php line 685

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Carbon\Carbon;
  4. use Knp\Snappy\Pdf;
  5. use Knp\Snappy\Image;
  6. use Pimcore\Model\Asset;
  7. use App\Service\RedisCache;
  8. use App\Model\ReportLogModel;
  9. use App\Service\EmailService;
  10. use App\Service\ReportService;
  11. use DateTime;
  12. use Pimcore\Log\ApplicationLogger;
  13. use App\Model\EwsNotificationModel;
  14. use App\Service\NotificationService;
  15. use Pimcore\Model\DataObject\Report;
  16. use App\Service\MeteomaticApiService;
  17. use App\Model\WeatherForecastCityModel;
  18. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  19. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  20. use App\Service\CustomNotificationService;
  21. use App\Service\MeteomaticsWeatherService;
  22. use Pimcore\Controller\FrontendController;
  23. use Knp\Component\Pager\PaginatorInterface;
  24. use App\Service\PublicUserPermissionService;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\Routing\Annotation\Route;
  28. use Pimcore\Model\DataObject\ReportWeatherSymbols;
  29. use Symfony\Component\HttpFoundation\JsonResponse;
  30. use Symfony\Contracts\Translation\TranslatorInterface;
  31. use Symfony\Component\Security\Core\User\UserInterface;
  32. use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
  33. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  34. class PublicApiController extends FrontendController
  35. {
  36.     private $ewsNotificationModel;
  37.     private $reportModel;
  38.     public function __construct(
  39.         private TokenStorageInterface $tokenStorageInterface,
  40.         private JWTTokenManagerInterface $jwtManager,
  41.         private PublicUserPermissionService $publicUserPermissionService,
  42.         protected TranslatorInterface $translator,
  43.         private ApplicationLogger $logger,
  44.         private MeteomaticApiService $meteomaticApiService,
  45.         private \Doctrine\DBAL\Connection $connection,
  46.         private RedisCache $redisCache,
  47.         private MeteomaticsWeatherService $meteomaticsWeatherService,
  48.         private Pdf $snappy,
  49.         private CustomNotificationService $customNotificationService,
  50.         private ReportService $reportService,
  51.         private NotificationService $notificationService,
  52.         private Image $snappyImage,
  53.         private EmailService $emailService
  54.     ) {
  55.        // header('Content-Type: application/json; charset=UTF-8');
  56.        // header("Access-Control-Allow-Origin: *");
  57.         $this->meteomaticApiService $meteomaticApiService;
  58.         $this->publicUserPermissionService $publicUserPermissionService;
  59.         $this->ewsNotificationModel = new EwsNotificationModel();
  60.         $this->reportModel = new ReportLogModel();
  61.     }
  62.     /**
  63.      * @Route("/api/public/{startdate}/{enddate}/{resolution}/{parameter}/{coordinate}/{format}", name="api_public_route_query", methods={"GET"})
  64.      */
  65.     public function publicRouteQueryData(Request $request): JsonResponse
  66.     {
  67.         try {
  68.             // check user credentials and expiry
  69.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  70.             if ($response['success'] !== true) {
  71.                 return $this->json($response);
  72.             }
  73.             $startDate $request->get('startdate');
  74.             $endDate $request->get('enddate');
  75.             $resolution $request->get('resolution');
  76.             $parameter $request->get('parameter');
  77.             $coordinate $request->get('coordinate');
  78.             $format $request->get('format');
  79.             // Optional Parameter
  80.             $source $request->get('source');
  81.             $onInvalid $request->get('on_invalid');
  82.             $model $request->get('model');
  83.             if (!$startDate) {
  84.                 throw new \InvalidArgumentException("Missing mandatory parameter: start date");
  85.             }
  86.             if (!$endDate) {
  87.                 throw new \InvalidArgumentException("Missing mandatory parameter: end date");
  88.             }
  89.             if (!$resolution) {
  90.                 throw new \InvalidArgumentException("Missing mandatory parameter: resolution");
  91.             }
  92.             if (!$parameter) {
  93.                 throw new \InvalidArgumentException("Missing mandatory parameter: parameters");
  94.             }
  95.             if (!$coordinate) {
  96.                 throw new \InvalidArgumentException("Missing mandatory parameter: coordinate");
  97.             }
  98.             if (!$format) {
  99.                 throw new \InvalidArgumentException("Missing mandatory parameter: format");
  100.             }
  101.             $startDate = new DateTime($startDate);
  102.             $endDate = new DateTime($endDate);
  103.             $user $response['user'];
  104.             $parametersArray explode(','$parameter);
  105.             // Varify user allowed permissions
  106.             // $reslult = $this->publicUserPermissionService->publicUserPermissionCheck($user, $parametersArray, $this->translator);
  107.             // if ($reslult['success'] !== true) {
  108.             //     return $this->json($reslult);
  109.             // }
  110.             $response $this->meteomaticApiService->publicRouteQuery(
  111.                 $startDate,
  112.                 $endDate,
  113.                 $resolution,
  114.                 $parametersArray,
  115.                 $coordinate,
  116.                 $format,
  117.                 $model,
  118.                 $source,
  119.                 $onInvalid
  120.             );
  121.             // For demonstration purposes, we will just return a JSON response
  122.             return $this->json($response);
  123.         } catch (\Exception $ex) {
  124.             $this->logger->error($ex->getMessage());
  125.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  126.         }
  127.     }
  128.     /**
  129.      * @Route("/api/public/get-report-detail", name="public_get_report_detail")
  130.      */
  131.     public function getReportDetails(Request $request)
  132.     {
  133.         try {
  134.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  135.             if ($response['success'] !== true) {
  136.                 return $this->json($response);
  137.             }
  138.             $user $response['user'];
  139.             // $params = json_decode($request->getContent(), true);
  140.             $requestUri $request->getRequestUri();
  141.             // Extract the last segment from the URL
  142.             $segments explode('/'trim($requestUri'/'));
  143.             $action end($segments);
  144.             $action str_replace("-""_"$action);
  145.             $params[] = $action;
  146.             // $reslult = $this->publicUserPermissionService->publicUserPermissionCheck($user, $params, $this->translator);
  147.             // if ($reslult['success'] !== true) {
  148.             //     return $this->json($reslult);
  149.             // }
  150.             $latestReport Report::getList([
  151.                 "limit" => 1,
  152.                 "orderKey" => "createdOn",
  153.                 "order" => "desc"
  154.             ]);
  155.             if ($latestReport->getCount() <= 0) {
  156.                 throw new \Exception('no_latest_report_found');
  157.             } else {
  158.                 $data = [];
  159.                 foreach ($latestReport as $report) {
  160.                     $data = [
  161.                         'name' => $report->getCreatedBy()?->getName(),
  162.                         'email' => $report->getCreatedBy()?->getEmail(),
  163.                         'jsonData' => json_decode($report->getJsonData(), true),
  164.                         'createdOn' => $report->getCreatedOn()
  165.                     ];
  166.                 }
  167.                 return $this->json(['success' => true'data' => $data]);
  168.             }
  169.         } catch (\Exception $ex) {
  170.             $this->logger->error($ex->getMessage());
  171.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  172.         }
  173.     }
  174.     /**
  175.      * @Route("/api/public/ews-analytics", methods={"POST"})
  176.      */
  177.     public function ewsAnalyticsAction(Request $request): JsonResponse
  178.     {
  179.         try {
  180.             $params json_decode($request->getContent(), true);
  181.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  182.             $lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
  183.             $result $this->ewsNotificationModel->ewsAnalytics($params$this->connection$lang);
  184.             return $this->json($result);
  185.         } catch (\Exception $ex) {
  186.             $this->logger->error($ex->getMessage());
  187.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  188.         }
  189.     }
  190.     /**
  191.      * @Route("/api/public/generate-report", methods={"POST"})
  192.      */
  193.     public function generateReport(Request $request): JsonResponse
  194.     {
  195.         try {
  196.             $response = [];
  197.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  198.             if ($permissions['success'] !== true) {
  199.                 return $this->json($permissions);
  200.             }
  201.             $params json_decode($request->getContent(), true);
  202.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  203.             if (
  204.                 !isset($params['from_date']) ||
  205.                 !isset($params['to_date']) ||
  206.                 !isset($params['hours']) ||
  207.                 !isset($params['parameters'])  ||
  208.                 !isset($params['locations'])
  209.             ) {
  210.                 throw new \Exception('Missing required parameters');
  211.             }
  212.             if (empty($params['parameters'] || !is_array($params['parameters']))) {
  213.                 throw new \Exception('Parameters should be non empty array');
  214.             }
  215.             if (empty($params['locations'] || !is_array($params['locations']))) {
  216.                 throw new \Exception('Locations should be non empty array');
  217.             }
  218.             $model = isset($params['model']) ? $params['model'] : 'mix';
  219.             $redisKey md5('generate_city_report-' $params['from_date'] . '-' $params['to_date'] . '-' $params['hours'] . '-' implode('_'$params['locations'])) . '-' implode('_'$params['parameters']) . '-' $model;
  220.             $data $this->redisCache->get($redisKey);
  221.             if (!$data) {
  222.                 $cities = new \Pimcore\Model\DataObject\City\Listing();
  223.                 if (!empty($params['locations'])) {
  224.                     $cities->setCondition('o_id IN (?)', [$params['locations']]);
  225.                 }
  226.                 $cities->load();
  227.                 if ($cities->getCount() > 0) {
  228.                     $params['coordinates'] = []; // Initialize an empty array for coordinates
  229.                     $result = [];
  230.                     $citiesArr = [];
  231.                     foreach ($cities as $city) {
  232.                         $params['coordinates'][] = [$city->getLatitude(), $city->getLongitude()];
  233.                         // Append the coordinates for each city
  234.                         $long number_format($city->getLongitude(), 6'.''');
  235.                         $lat number_format($city->getLatitude(), 6'.''');
  236.                         $citiesArr[$lat '|' $long]["en"] =  $city->getCityName("en");
  237.                         $citiesArr[$lat '|' $long]["ar"] =  $city->getCityName("ar");
  238.                     }
  239.                     $result $this->meteomaticsWeatherService->getReportForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $model$params['parameters'], $this->translator$citiesArr$params);
  240.                     $response[] = $result;
  241.                     $jsonResponse = ['success' => true'data' => $response];
  242.                     $this->redisCache->set($redisKey$jsonResponseREDIS_CACHE_TIME);
  243.                     return $this->json($jsonResponse);
  244.                 } else {
  245.                     return $this->json(['success' => true'message' => $this->translator->trans('no_city_found')]);
  246.                 }
  247.             } else {
  248.                 return $this->json($data);
  249.             }
  250.         } catch (\Exception $ex) {
  251.             $this->logger->error($ex->getMessage());
  252.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  253.         }
  254.     }
  255.     /**
  256.      * @Route("/api/public/update-report", methods={"POST"})
  257.      */
  258.     public function updateReport(Request $request)
  259.     {
  260.         try {
  261.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  262.             if ($permissions['success'] !== true) {
  263.                 return $this->json($permissions);
  264.             }
  265.             $user $permissions['user'];
  266.             $params  json_decode($request->getContent(), true);
  267.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  268.             // Perform parameter validation here
  269.             // || !isset($params['locations'])
  270.             if (!isset($params['data'])  || !isset($params['start_date']) || !isset($params['end_date']) || !isset($params['lang'])) {
  271.                 return $this->json(['success' => false'message' =>  $this->translator->trans('missing_required_parameters')]);
  272.             }
  273.             if (isset($params['organizations'])) {
  274.                 if (!is_array($params['organizations'])) {
  275.                     throw new \Exception($this->translator->trans('Organizations should be non empty array'), 400);
  276.                 }
  277.             }
  278.             if (isset($params['channels'])) {
  279.                 if (!is_array($params['channels']) || empty($params['channels'])) {
  280.                     throw new \Exception($this->translator->trans('Channels should be non empty array'), 400);
  281.                 }
  282.                 if (in_array('email'$params['channels'])) {
  283.                     if (!isset($params['emails']) || !is_array($params['emails']) || empty($params['emails'])) {
  284.                         throw new \Exception($this->translator->trans('Emails should be non empty array'), 400);
  285.                     }
  286.                 }
  287.             }
  288.             $result $this->reportModel->editReport($user$params$this->translator$this->logger);
  289.             return $this->json($result);
  290.         } catch (\Exception $ex) {
  291.             $this->logger->error($ex->getMessage());
  292.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  293.         }
  294.     }
  295.     /**
  296.      * @Route("/api/public/get-city-list", name="public-city-listing")
  297.      */
  298.     public function getCityListAction(Request $request)
  299.     {
  300.         try {
  301.             $result = [];
  302.             $lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
  303.             $params  json_decode($request->getContent(), true);
  304.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  305.             $reportTypeId $params['report_type_id'] ?? null;
  306.             $cities = new \Pimcore\Model\DataObject\City\Listing();
  307.             if ($reportTypeId) {
  308.                 $cities->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" $reportTypeId "', ',', '|'), '(,|$)')");
  309.             } else {
  310.                 $db \Pimcore\Db::get();
  311.                 $selectedLocalities $db->fetchAllAssociative("SELECT oo_id  FROM `object_query_ReportType` WHERE (`isAutomaticReport` = 0)");
  312.                 $ooIds array_column($selectedLocalities'oo_id');
  313.                 $cities->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" implode(','$ooIds) . "', ',', '|'), '(,|$)')");
  314.             }
  315.             $cities->load();
  316.             if ($cities->getCount() > 0) {
  317.                 foreach ($cities as $city) {
  318.                     $result[] = [
  319.                         "id" => $city->getId(),
  320.                         "name" => $city->getCityName($lang),
  321.                         "nameEn" => $city->getCityName('en'),
  322.                         "nameAr" => $city->getCityName('ar'),
  323.                         "lat" => $city->getLatitude(),
  324.                         "long" => $city->getLongitude(),
  325.                         "googlePlaceName" => $city->getGooglePlaceName(),
  326.                     ];
  327.                 }
  328.                 return $this->json(["success" => true"data" => $result]);
  329.             }
  330.             return $this->json(["success" => false"message" => $this->translator->trans("no_city_is_available")]);
  331.         } catch (\Exception $ex) {
  332.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  333.         }
  334.     }
  335.     /**
  336.      * @Route("/api/public/list-report", name="public-report-listing")
  337.      */
  338.     public function getReportListAction(Request $requestPaginatorInterface $paginator)
  339.     {
  340.         try {
  341.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  342.             if ($permissions['success'] !== true) {
  343.                 return $this->json($permissions);
  344.             }
  345.             $user $permissions['user'];
  346.             $params  json_decode($request->getContent(), true);
  347.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  348.             if (!isset($params['page']) || !isset($params['limit'])) {
  349.                 throw new \Exception('Missing required params: page or limit');
  350.             }
  351.             $report_type = isset($params['report_type']) ? $params['report_type'] : null;
  352.             $lang = isset($params['lang']) ? $params['lang'] : DEFAULT_LOCALE;
  353.             $isPublicReports = isset($params['publicReports']) ? $params['publicReports'] : false// sending this flag from public portal to get all reports accordong to our needs
  354.             $page $params['page'];
  355.             $limit $params['limit'];
  356.             $result $this->reportModel->reportList($params$page$limit$this->translator$paginator$report_type$user$lang$isPublicReports);
  357.             return $this->json($result);
  358.         } catch (\Exception $ex) {
  359.             $this->logger->error($ex->getMessage());
  360.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  361.         }
  362.     }
  363.     /**
  364.      * @Route("/api/public/generate-report-pdf", name="public-report-pdf")
  365.      */
  366.     public function generateReportPdf(Request $request)
  367.     {
  368.         try {
  369.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  370.             if ($permissions['success'] !== true) {
  371.                 return $this->json($permissions);
  372.             }
  373.             $user $permissions['user'];
  374.             $params  json_decode($request->getContent(), true);
  375.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  376.             return $this->getPdfReport($request$user'pdf/report_pdf_template.html.twig'$this->translator'_manned_forecast_report.pdf');
  377.         } catch (\Exception $ex) {
  378.             $this->logger->error($ex->getMessage());
  379.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  380.         }
  381.     }
  382.     /**
  383.      * @Route("/api/public/get-report-types", name="public-report-types-listing")
  384.      */
  385.     public function getReportTypes(Request $request)
  386.     {
  387.         try {
  388.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  389.             if ($permissions['success'] !== true) {
  390.                 return $this->json($permissions);
  391.             }
  392.             $params  json_decode($request->getContent(), true);
  393.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  394.             if (!isset($params['automatic'])) {
  395.                 throw new \Exception('missing_required_parameters');
  396.             }
  397.             $result = [];
  398.             $automatic $params['automatic'] ? true false;
  399.             $reportTypes = new \Pimcore\Model\DataObject\ReportType\Listing();
  400.             $reportTypes->setCondition('isAutomaticReport = ?', [$automatic]);
  401.             $reportTypes->load();
  402.             if ($reportTypes->getCount() > 0) {
  403.                 foreach ($reportTypes as $reportType) {
  404.                     $result[] = [
  405.                         "id" => $reportType->getId(),
  406.                         "key" => $reportType->getReportKey(),
  407.                         "nameEn" => $reportType->getName('en'),
  408.                         "nameAr" => $reportType->getName('ar'),
  409.                         "descriptionEn" => $reportType->getDescription('en'),
  410.                         "descriptionAr" => $reportType->getDescription('ar'),
  411.                         "titleEn" => $reportType->getTitle('en'),
  412.                         "titleAr" => $reportType->getTitle('ar'),
  413.                         "automatic" => $reportType->getIsAutomaticReport()
  414.                     ];
  415.                 }
  416.                 return $this->json(["success" => true"data" => $result]);
  417.             }
  418.             return $this->json(["success" => false"message" => $this->translator->trans("no_reportType_is_available")]);
  419.         } catch (\Exception $ex) {
  420.             $this->logger->error($ex->getMessage());
  421.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  422.         }
  423.     }
  424.     /**
  425.      * @Route("/api/public/get-weather-params-list", name="public-weather-params-listing")
  426.      */
  427.     public function getWeatherParamsListAction(Request $request)
  428.     {
  429.         try {
  430.             $result = [];
  431.             $lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
  432.             $params  json_decode($request->getContent(), true);
  433.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  434.             if (!isset($params['report_type_id'])) {
  435.                 return $this->json(['success' => false'message' =>  $this->translator->trans('missing_required_parameters')]);
  436.             }
  437.             $reportTypeId $params['report_type_id'];
  438.             $parameters = new \Pimcore\Model\DataObject\ReportWeatherParameters\Listing();
  439.             $parameters->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" $reportTypeId "', ',', '|'), '(,|$)')");
  440.             $parameters->load();
  441.             if ($parameters->getCount() > 0) {
  442.                 foreach ($parameters as $paramter) {
  443.                     $result[] = [
  444.                         "id" => $paramter->getId(),
  445.                         "nameEn" => $paramter->getName('en'),
  446.                         "nameAr" => $paramter->getName('ar'),
  447.                         "meteoMaticsKey" => $paramter->getMeteoMaticsKey(),
  448.                         "units" => $paramter->getUnits(),
  449.                         "unitTitle" => $paramter->getUnitTitle()
  450.                     ];
  451.                 }
  452.                 return $this->json(["success" => true"data" => $result]);
  453.             }
  454.             return $this->json(["success" => false"message" => $this->translator->trans("no_weather_parameter_is_available")]);
  455.         } catch (\Exception $ex) {
  456.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  457.         }
  458.     }
  459.     /**
  460.      * @Route("/api/public/generate-excel", name="public-generate-excel")
  461.      */
  462.     public function generateExcelReport(Request $request)
  463.     {
  464.         $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  465.         if ($permissions['success'] !== true) {
  466.             return $this->json($permissions);
  467.         }
  468.         $user $permissions['user'];
  469.         $params  json_decode($request->getContent(), true);
  470.         $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  471.         if (!isset($params['id'])) {
  472.             throw new \Exception('missing_required_parameters');
  473.         }
  474.         $report Report::getById($params['id'], true);
  475.         if (!$report instanceof Report) {
  476.             throw new \Exception('no_report_found');
  477.         }
  478.         // Replace this with the actual data you want to use
  479.         $jsonData json_decode($report->getJsonData(), true);
  480.         // Create a new PhpSpreadsheet instance
  481.         $spreadsheet = new Spreadsheet();
  482.         // Create a worksheet
  483.         $sheet $spreadsheet->getActiveSheet();
  484.         // Determine headers dynamically based on the first item in the data
  485.         $firstItem reset($jsonData);
  486.         $parameters $firstItem['parameters'] ?? [];
  487.         $headers = ['City''Lat''Lon''Date']; // Initialize headers with common columns
  488.         // Extract parameter names and add them to headers
  489.         foreach ($parameters as $parameter) {
  490.             $headers[] = $parameter['parameter'];
  491.         }
  492.         // Add headers to the worksheet
  493.         foreach ($headers as $index => $header) {
  494.             $sheet->setCellValueByColumnAndRow($index 11$header);
  495.         }
  496.         // Initialize row counter
  497.         $row 2;
  498.         foreach ($jsonData as $item) {
  499.             // Extract city-related data
  500.             $cityData = [$item['city'] ?? ''$item['lat'] ?? ''$item['lon'] ?? ''];
  501.             // Loop through each date for all parameters
  502.             foreach ($item['parameters'][0]['dates'] as $dateIndex => $date) {
  503.                 // Initialize row data with city-related data and date
  504.                 $rowData array_merge($cityData, [date('Y-m-d'strtotime($date['date']))]);
  505.                 // Loop through each parameter
  506.                 foreach ($item['parameters'] as $parameter) {
  507.                     // Check if the value is set for the current date, otherwise set it to 0
  508.                     $value = isset($parameter['dates'][$dateIndex]['value']) ? $parameter['dates'][$dateIndex]['value'] : 0;
  509.                     // Add parameter value for the current date to the row data
  510.                     $rowData[] = $value;
  511.                 }
  512.                 // Set cell values explicitly
  513.                 foreach ($rowData as $colIndex => $cellValue) {
  514.                     $sheet->setCellValueByColumnAndRow($colIndex 1$row$cellValue);
  515.                 }
  516.                 // Increment the row counter
  517.                 $row++;
  518.             }
  519.         }
  520.         // Save the Excel file to a temporary file
  521.         $tempFile tempnam(sys_get_temp_dir(), 'weather_report');
  522.         $writer = new Xlsx($spreadsheet);
  523.         $writer->save($tempFile);
  524.         // Store the file in Pimcore Assets
  525.         $assetFolder '/report/ExcelReports'// Change this to your actual asset folder path
  526.         $filename $user->getId() . '_' time() . '_' 'weather_report.xlsx';
  527.         $assetPath =  API_BASE_URL '/' $assetFolder '/' $filename;
  528.         // Create a new asset
  529.         $asset = new \Pimcore\Model\Asset();
  530.         $asset->setFilename($filename);
  531.         $asset->setData(file_get_contents($tempFile));
  532.         $asset->setParent(\Pimcore\Model\Asset\Service::createFolderByPath($assetFolder));
  533.         $asset->save();
  534.         // Remove the temporary file
  535.         unlink($tempFile);
  536.         $report->setAsset($asset);
  537.         $report->setIsHistorical(true);
  538.         $report->save();
  539.         // Return the path to the stored Excel file in Pimcore
  540.         return $this->json(['success' => true'data' => $assetPath]);
  541.     }
  542.     /**
  543.      * @Route("/api/public/generate-historical-report", methods={"POST"})
  544.      */
  545.     public function generateHistoricalReport(Request $request): JsonResponse
  546.     {
  547.         try {
  548.             $response = [];
  549.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  550.             if ($permissions['success'] !== true) {
  551.                 return $this->json($permissions);
  552.             }
  553.             $params json_decode($request->getContent(), true);
  554.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  555.             if (
  556.                 !isset($params['from_date']) ||
  557.                 !isset($params['to_date']) ||
  558.                 !isset($params['hours']) ||
  559.                 !isset($params['parameters'])  ||
  560.                 !isset($params['locations'])
  561.             ) {
  562.                 throw new \Exception('Missing required parameters');
  563.             }
  564.             if (empty($params['parameters'] || !is_array($params['parameters']))) {
  565.                 throw new \Exception('Parameters should be non empty array');
  566.             }
  567.             if (empty($params['locations'] || !is_array($params['locations']))) {
  568.                 throw new \Exception('Locations should be non empty array');
  569.             }
  570.             if ($params['to_date'] > date('Y-m-d'strtotime(Carbon::now()))) {
  571.                 $daysadd date('Y-m-d'strtotime(Carbon::now()->addDays('17')));
  572.                 if ($params['to_date'] >= $daysadd) {
  573.                     throw new \Exception('End date limit exceeded');
  574.                 }
  575.             }
  576.             $model = isset($params['model']) ? $params['model'] : 'mix';
  577.             $redisKey md5('generate_city_report-' $params['from_date'] . '-' $params['to_date'] . '-' $params['hours'] . '-' implode('_'$params['locations'])) . '-' implode('_'$params['parameters']) . '-' $model;
  578.             $data $this->redisCache->get($redisKey);
  579.             if (!$data) {
  580.                 $cities = new \Pimcore\Model\DataObject\Location\Listing();
  581.                 if (!empty($params['locations'])) {
  582.                     $cities->setCondition('o_id IN (?)', [$params['locations']]);
  583.                 }
  584.                 $cities->load();
  585.                 if ($cities->getCount() > 0) {
  586.                     $params['coordinates'] = []; // Initialize an empty array for coordinates
  587.                     $result = [];
  588.                     $citiesArr = [];
  589.                     foreach ($cities as $city) {
  590.                         $cityLocations json_decode($city->getCoordinates(), true);
  591.                         foreach ($cityLocations as $coordinates) {
  592.                             $long number_format($coordinates[1], 6'.''');
  593.                             $lat number_format($coordinates[0], 6'.''');
  594.                             $params['coordinates'][] = $coordinates;
  595.                             $citiesArr[$lat '|' $long] =  $city->getName();
  596.                         }
  597.                     }
  598.                     $result $this->meteomaticsWeatherService->getReportForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $model$params['parameters'], $this->translator$citiesArr$params);
  599.                     $response[] = $result;
  600.                     $jsonResponse = ['success' => true'data' => $response];
  601.                     $this->redisCache->set($redisKey$jsonResponseREDIS_CACHE_TIME);
  602.                     return $this->json($jsonResponse);
  603.                 } else {
  604.                     return $this->json(['success' => true'message' => $this->translator->trans('no_city_found')]);
  605.                 }
  606.             } else {
  607.                 return $this->json($data);
  608.             }
  609.         } catch (\Exception $ex) {
  610.             $this->logger->error($ex->getMessage());
  611.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  612.         }
  613.     }
  614.     /**
  615.      * @Route("/api/public/get-latest-report", name="public-get-latest-report")
  616.      */
  617.     public function getLatestReport(Request $request)
  618.     {
  619.         try {
  620.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  621.             if ($permissions['success'] !== true) {
  622.                 return $this->json($permissions);
  623.             }
  624.             $params  json_decode($request->getContent(), true);
  625.             $reportType = (isset($params['report_type']) && !empty($params['report_type'])) ? $params['report_type'] : 'ten-day-forecast-report';
  626.             $result $this->reportModel->getLatestReport($reportType$this->translatorfalse);
  627.             return $this->json($result);
  628.         } catch (\Exception $ex) {
  629.             $this->logger->error($ex->getMessage());
  630.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  631.         }
  632.     }
  633.      /**
  634.      * @Route("/api/public/get-latest-weather-report", name="public-get-latest-weather-report")
  635.      */
  636.     public function getLatestPublicWeatherReport(Request $request)
  637.     {
  638.         try {
  639.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  640.             if ($permissions['success'] !== true) {
  641.                 return $this->json($permissions);
  642.             }
  643.             $params  json_decode($request->getContent(), true);
  644.             $result $this->reportModel->getLatestPublicWeatherReport($params$this->translator);
  645.             return $this->json($result);
  646.         } catch (\Exception $ex) {
  647.             $this->logger->error($ex->getMessage());
  648.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  649.         }
  650.     }
  651.     /**
  652.      * @Route("/api/public/get-automatic-reports", name="public_get_automatic_reports")
  653.      */
  654.     public function getAutomaticReports(Request $requestPaginatorInterface $paginator)
  655.     {
  656.         try {
  657.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  658.             if ($permissions['success'] !== true) {
  659.                 return $this->json($permissions);
  660.             }
  661.             $user $permissions['user'];
  662.             $params  json_decode($request->getContent(), true);
  663.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  664.             if (!isset($params['page']) || !isset($params['limit']) || !isset($params['lang'])) {
  665.                 throw new \Exception('Missing required parameters');
  666.             }
  667.             $search = isset($params['search']) ? $params['search'] : null;
  668.             $orderKey = isset($params['orderKey']) ? $params['orderKey'] : 'createdOn';
  669.             $order = isset($params['order']) ? $params['order'] : 'desc';
  670.             $result $this->reportModel->listAutomaticPublicReports($params$user$search$orderKey$order$this->translator$paginator);
  671.             return $this->json($result);
  672.         } catch (\Exception $ex) {
  673.             $this->logger->error($ex->getMessage());
  674.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  675.         }
  676.     }
  677.     /**
  678.      * @Route("/api/public/generate-automatic-report-pdf", name="public-automatic-report-pdf")
  679.      */
  680.     public function generateAutomaticReportPdf(Request $request)
  681.     {
  682.         try {
  683.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  684.             if ($permissions['success'] !== true) {
  685.                 return $this->json($permissions);
  686.             }
  687.             $user $permissions['user'];
  688.             $result $this->reportModel->generatePdfReport($request$user$this->snappy$this->translator);
  689.             return  $this->json($result);
  690.         } catch (\Exception $ex) {
  691.             $this->logger->error($ex->getMessage());
  692.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  693.         }
  694.     }
  695.     public function getPdfReport($request$user$template$translator$report_type)
  696.     {
  697.         $params  json_decode($request->getContent(), true);
  698.         if (!isset($params['id'])) {
  699.             return $this->json(["success" => false"message" => $translator->trans("missing_required_parameters")]);
  700.         }
  701.         $report Report::getById($params['id'], true);
  702.         $lang = isset($params['lang']) ? $params['lang'] : "en";
  703.         if (!$report instanceof Report) {
  704.             return $this->json(["success" => false"message" => $translator->trans("no_report_found")]);
  705.         }
  706.         $asset $lang == 'ar' $report->getAssetAr() : $report->getAsset();
  707.         if ($asset) {
  708.             $pdfasset API_BASE_URL $asset->getPath() . $asset->getFilename();
  709.             return $this->json(['success' => true'data' => $pdfasset]);
  710.         }
  711.         //$template=$report->getReportType()?->getKey() == 'MannForecastReport'?'pdf/report_pdf_template.html.twig':'pdf/automatic_report_pdf_template.html.twig';
  712.         $fileName '_custom_weather_report.pdf';
  713.         $reportPath '/report/ReportPdf';
  714.         if ($report->getReportType()?->getKey() == 'MannForecastReport') {
  715.             $template =  'pdf/report_pdf_template.html.twig';
  716.         } elseif ($report->getReportType()?->getKey() == 'advance-custom-weather-report') {
  717.             $template 'pdf/advance_custom_report_pdf_template.html.twig';
  718.             $fileName '_advance_custom_weather_report.pdf';
  719.             $reportPath '/report/advanceCustomReportPdf';
  720.         } else {
  721.             $template 'pdf/automatic_report_pdf_template.html.twig';
  722.         }
  723.         $parameter = [
  724.             'data' => $report,
  725.             'reportTitleEn' => $report->getReportTitle('en'),
  726.             'reportTitleAr' => $report->getReportTitle('ar'),
  727.             'reportDescriptionEn' => $report->getDescription('en'),
  728.             'reportDescriptionAr' => $report->getDescription('ar'),
  729.             'reportDisclaimerEn' => $report->getReportDisclaimer('en'), // new 
  730.             'reportDisclaimerAr' => $report->getReportDisclaimer('ar'), // new 
  731.             'additionalNoteEn' => $report->getAdditionalNote('en'), // new 
  732.             'additionalNoteAr' => $report->getAdditionalNote('ar'), // new 
  733.             'template' => $template,
  734.             'lang' => $lang
  735.         ];
  736.         // return $this->render('pdf/automatic_report_pdf_template_copy.html.twig',$parameter);
  737.         $pdf \App\Lib\Utility::generatePdf($parameter$this->snappy);
  738.         // $tempFilePath = tempnam(sys_get_temp_dir(), 'image_');
  739.         // file_put_contents($tempFilePath, $pdf);
  740.         // Create a BinaryFileResponse and set headers
  741.         //    $response = new BinaryFileResponse($tempFilePath);
  742.         //    $response->headers->set('Content-Type', 'application/pdf');
  743.         //    $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, 'image.pdf');
  744.         // Return the response
  745.         //    return $response;
  746.         $asset \App\Lib\Utility::createAsset($pdf$user->getId() . '_' time() . $report_type,  $reportPath);
  747.         $pdfasset '';
  748.         if ($asset instanceof Asset) {
  749.             $pdfasset API_BASE_URL $asset->getPath() . $asset->getFilename();
  750.         }
  751.         if ($lang == 'ar') {
  752.             $report->setAssetAr($asset);
  753.         } else {
  754.             $report->setAsset($asset);
  755.         }
  756.         $report->save();
  757.         return $this->json(['success' => true'data' => $pdfasset]);
  758.     }
  759.     /**
  760.      * @Route("/api/public/get-today-weather-report", name="public_get_today_weather_report")
  761.      */
  762.     public function getTodayWeatherReports(Request $requestPaginatorInterface $paginator)
  763.     {
  764.         try {
  765.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  766.             if ($permissions['success'] !== true) {
  767.                 return $this->json($permissions);
  768.             }
  769.             $user $permissions['user'];
  770.             $params  json_decode($request->getContent(), true);
  771.             if (!isset($params['page']) || !isset($params['limit']) || !isset($params['lang'])) {
  772.                 throw new \Exception('Missing required parameters');
  773.             }
  774.             $result $this->reportModel->getTodayWeatherReports($params$this->translator$paginator);
  775.             return $this->json($result);
  776.         } catch (\Exception $ex) {
  777.             $this->logger->error($ex->getMessage());
  778.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  779.         }
  780.     }
  781.     /**
  782.      * @Route("/api/public/get-report-weather-symbols", name="public_get_report_weather_symbols")
  783.      */
  784.     public function getReportWeatherSymbols(Request $request): JsonResponse
  785.     {
  786.         try {
  787.             $permissions $this->publicUserPermissionService->isAuthorized($request$this->translator);
  788.             if ($permissions['success'] !== true) {
  789.                 return $this->json($permissions);
  790.             }
  791.             $user $permissions['user'];
  792.             $data = [];
  793.             $weatherSymbols = new ReportWeatherSymbols\Listing();
  794.             foreach ($weatherSymbols as $weatherSymbol) {
  795.                 if ($weatherSymbol) {
  796.                     $weatherSymbolNames $weatherSymbol->getWeatherSymbols();
  797.                     $weatherSymbolIcons $weatherSymbol->getWeatherIcons();
  798.                     if ($weatherSymbolNames) {
  799.                         foreach ($weatherSymbolNames as $weatherSymbolName) {
  800.                             $response['symbols'][] = [
  801.                                 'nameEn' => $weatherSymbolName->getSymbolName('en'),
  802.                                 'nameAr' => $weatherSymbolName->getSymbolName('ar'),
  803.                             ];
  804.                         }
  805.                     }
  806.                     if ($weatherSymbolIcons) {
  807.                         foreach ($weatherSymbolIcons as $weatherSymbolIcon) {
  808.                             $response['icons'][] = [
  809.                                 'iconValue' => $weatherSymbolIcon->getIconValue(),
  810.                             ];
  811.                         }
  812.                     }
  813.                 }
  814.                 $data[] = $response;
  815.             }
  816.             return $this->json(['success' => true'data' => $data]);
  817.         } catch (\Exception $ex) {
  818.             $this->logger->error($ex->getMessage());
  819.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  820.         }
  821.     }
  822.     /**
  823.      * @Route("/api/public/get-forecast-cities", methods={"POST"})
  824.      */
  825.     public function getForecastCities(Request $request): Response
  826.     {
  827.         try {
  828.             $params json_decode($request->getContent(), true);
  829.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  830.             // check user credentials and expiry
  831.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  832.             if ($response['success'] !== true) {
  833.                 return $this->json($response);
  834.             }
  835.             $forecastCityModel = new WeatherForecastCityModel();
  836.             $cities $forecastCityModel->getWeatherForecastCities();
  837.             return $this->json(['success' => true'data' => $cities]);
  838.         } catch (\Exception $ex) {
  839.             $this->logger->error($ex->getMessage());
  840.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  841.         }
  842.     }
  843.     /**
  844.      * @Route("/api/public/get-regions-bbox", name="get-regions-bbox")
  845.      */
  846.     public function getRegionsBbox(Request $request)
  847.     {
  848.         try {
  849.             $params json_decode($request->getContent(), true);
  850.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  851.             // check user credentials and expiry
  852.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  853.             if ($response['success'] !== true) {
  854.                 return $this->json($response);
  855.             }
  856.             $data REGIONS_BBOX;
  857.             return $this->json(['success' => true'data' => $data]);
  858.         } catch (\Exception $ex) {
  859.             $this->logger->error($ex->getMessage());
  860.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  861.         }
  862.     }
  863.     /**
  864.      * @Route("/api/public/get-station-data", methods={"GET"})
  865.      */
  866.     public function getWeatherStationDataAction(Request $request)
  867.     {
  868.         try {
  869.             $params json_decode($request->getContent(), true);
  870.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  871.             // check user credentials and expiry
  872.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  873.             if ($response['success'] !== true) {
  874.                 return $this->json($response);
  875.             }
  876.             $typeName $request->get('type_name');
  877.             $parameters $request->get('parameters');
  878.             $dateTime $request->get('date_time');
  879.             $bBox $request->get('b_box');
  880.             if (!$typeName) {
  881.                 throw new \InvalidArgumentException("Missing mandatory parameter: type_name");
  882.             }
  883.             if (!$parameters) {
  884.                 throw new \InvalidArgumentException("Missing mandatory parameter: parameters");
  885.             }
  886.             if (!$dateTime) {
  887.                 throw new \InvalidArgumentException("Missing mandatory parameter: date_time");
  888.             }
  889.             if (!$bBox) {
  890.                 throw new \InvalidArgumentException("Missing mandatory parameter: b_box");
  891.             }
  892.             $result $this->meteomaticsWeatherService->getWeatherStationData($typeName$parameters$dateTime$bBox);
  893.             return $result;
  894.         } catch (\Exception $ex) {
  895.             return $this->json(['success' => false'message' => $ex->getMessage()]);
  896.         }
  897.     }
  898.     /**
  899.      * @Route("/api/public/daily-forecast", methods={"POST"})
  900.      */
  901.     public function dailyForecast(Request $request): JsonResponse
  902.     {
  903.         try {
  904.             $params json_decode($request->getContent(), true);
  905.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  906.             // check user credentials and expiry
  907.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  908.             if ($response['success'] !== true) {
  909.                 return $this->json($response);
  910.             }
  911.             $requiredParameters = ['coordinates''from_date''to_date''model'];
  912.             foreach ($requiredParameters as $param) {
  913.                 if (!isset($params[$param])) {
  914.                     $missingParams[] = $param;
  915.                 }
  916.             }
  917.             if (!empty($missingParams)) {
  918.                 // Throw an exception with a message that includes the missing parameters
  919.                 $parameterList implode(", "$missingParams);
  920.                 return $this->json(['success' => false'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  921.             }
  922.             $result $this->meteomaticsWeatherService->getForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $params['model'], $this->translator);
  923.             return $this->json($result);
  924.         } catch (\Exception $ex) {
  925.             $this->logger->error($ex->getMessage());
  926.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  927.         }
  928.     }
  929.     /**
  930.      * @Route("/api/public/weather/{path}", name="api_meteomatics", requirements={"path"=".+"}, methods={"GET"})
  931.      */
  932.     public function getDynamicWeatherData(Request $requeststring $path): Response
  933.     {
  934.         try {
  935.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  936.             if ($response['success'] !== true) {
  937.                 return $this->json($response);
  938.             }
  939.             $user $response['user'];
  940.             $queryParams $request->query->all();
  941.             $weatherData $this->meteomaticApiService->getDynamicWeatherData($path$queryParams$user);
  942.             return $weatherData;
  943.         } catch (\Exception $ex) {
  944.             $this->logger->error($ex->getMessage());
  945.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  946.         }
  947.     }
  948.     /**
  949.      * @Route("/api/public/create-manned-alert-subscription", methods={"POST"})
  950.      */
  951.     public function mannedAlertSubscription(Request $request): JsonResponse
  952.     {
  953.         try {
  954.             $response $this->publicUserPermissionService->isAuthorized($request$this->translator);
  955.             if ($response['success'] !== true) {
  956.                 return $this->json($response);
  957.             }
  958.             $user $response['user'];
  959.             $params json_decode($request->getContent(), true);
  960.             $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
  961.             // $requiredParameters = ['region_id', 'governorate_id', 'alert_type_id'];
  962.             // foreach ($requiredParameters as $param) {
  963.             //     if (!isset($params[$param]) || empty($params[$param])) {
  964.             //         $missingParams[] = $param;
  965.             //     }
  966.             // }
  967.             // if (!empty($missingParams)) {
  968.             //     // Throw an exception with a message that includes the missing parameters
  969.             //     $parameterList = implode(", ", $missingParams);
  970.             //     return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
  971.             // }
  972.             $result $this->customNotificationService->mannedAlertSubscription($user$params$this->translator);
  973.             return $this->json($result);
  974.         } catch (\Exception $ex) {
  975.             $this->logger->error($ex->getMessage());
  976.             return $this->json(['success' => false'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
  977.         }
  978.     }
  979. }