<?php
namespace App\Controller;
use App\C2IntegrationBundle\Service\C2Service;
use Carbon\Carbon;
use Knp\Snappy\Pdf;
use Knp\Snappy\Image;
use Pimcore\Model\Asset;
use App\Service\RedisCache;
use App\Service\CfoReportPayloadBuilder;
use App\Model\ReportLogModel;
use App\Service\EmailService;
use App\Service\ReportService;
use DateTime;
use Pimcore\Log\ApplicationLogger;
use App\Model\EwsNotificationModel;
use App\Service\NotificationService;
use Pimcore\Model\DataObject\Report;
use App\Service\MeteomaticApiService;
use App\Model\WeatherForecastCityModel;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use App\Service\CustomNotificationService;
use App\Service\MeteomaticsWeatherService;
use Pimcore\Controller\FrontendController;
use Knp\Component\Pager\PaginatorInterface;
use App\Service\PublicUserPermissionService;
use App\Service\NCMWeatherAPIService;
use GuzzleHttp\Client;
use App\Model\ReportingPortalModel;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Pimcore\Model\DataObject\ReportWeatherSymbols;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Contracts\Translation\TranslatorInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Templating\EngineInterface;
use App\Service\InsuranceIndustryService;
use App\Model\WeatherStationModel;
use App\Service\WeatherStationService;
use Pimcore\Model\DataObject\HistoricalDataParameters;
use App\Model\AgricultureModel;
use App\Service\ChillUnitService;
use Pimcore\Model\DataObject;
use App\Model\LocationModel;
use App\Model\WeatherParameterModel;
use Pimcore\Model\DataObject\WeatherParameterLocationTags;
use GuzzleHttp\Exception\RequestException;
use App\Service\Translation\TranslationServiceInterface;
use App\Model\MarineReportModel;
class PublicApiController extends FrontendController
{
private $ewsNotificationModel;
private $reportModel;
private $c2Service;
private $reportingPortalModel;
private $weatherStationModel;
private $agricultureModel;
private $chillUnitService;
private $locationModel;
private $weatherParameterModel;
private $httpClient;
private $marineReportModel;
public function __construct(
private TokenStorageInterface $tokenStorageInterface,
private JWTTokenManagerInterface $jwtManager,
private PublicUserPermissionService $publicUserPermissionService,
protected TranslatorInterface $translator,
private ApplicationLogger $logger,
private MeteomaticApiService $meteomaticApiService,
private \Doctrine\DBAL\Connection $connection,
private RedisCache $redisCache,
private MeteomaticsWeatherService $meteomaticsWeatherService,
private Pdf $snappy,
private CustomNotificationService $customNotificationService,
private ReportService $reportService,
private NotificationService $notificationService,
private Image $snappyImage,
private EmailService $emailService,
private EngineInterface $templating,
private NCMWeatherAPIService $ncmWeatherApiService,
private InsuranceIndustryService $insuranceIndustryService,
private WeatherStationService $weatherStationService,
private CfoReportPayloadBuilder $cfoReportPayloadBuilder,
private TranslationServiceInterface $marineTranslator,
) {
header('Content-Type: application/json; charset=UTF-8');
// header("Access-Control-Allow-Origin: *");
$this->meteomaticApiService = $meteomaticApiService;
$this->publicUserPermissionService = $publicUserPermissionService;
$this->ewsNotificationModel = new EwsNotificationModel();
$this->reportModel = new ReportLogModel();
$this->c2Service = new C2Service();
$this->templating = $templating;
$this->reportingPortalModel = new ReportingPortalModel();
$this->weatherStationModel = new WeatherStationModel();
$this->agricultureModel = new AgricultureModel();
$this->chillUnitService = new ChillUnitService();
$this->locationModel = new LocationModel();
$this->weatherParameterModel = new WeatherParameterModel();
$this->marineReportModel = new MarineReportModel();
$this->httpClient = new Client([
'verify' => false // Disable SSL verification
]);
}
/**
* @Route("/api/public/{startdate}/{enddate}/{resolution}/{parameter}/{coordinate}/{format}", name="api_public_route_query", methods={"GET"})
*/
public function publicRouteQueryData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$startDate = $request->get('startdate');
$endDate = $request->get('enddate');
$resolution = $request->get('resolution');
$parameter = $request->get('parameter');
$coordinate = $request->get('coordinate');
$format = $request->get('format');
// Optional Parameter
$source = $request->get('source');
$onInvalid = $request->get('on_invalid');
$model = $request->get('model');
if (!$startDate) {
throw new \InvalidArgumentException("Missing mandatory parameter: start date");
}
if (!$endDate) {
throw new \InvalidArgumentException("Missing mandatory parameter: end date");
}
if (!$resolution) {
throw new \InvalidArgumentException("Missing mandatory parameter: resolution");
}
if (!$parameter) {
throw new \InvalidArgumentException("Missing mandatory parameter: parameters");
}
if (!$coordinate) {
throw new \InvalidArgumentException("Missing mandatory parameter: coordinate");
}
if (!$format) {
throw new \InvalidArgumentException("Missing mandatory parameter: format");
}
$startDate = new DateTime($startDate);
$endDate = new DateTime($endDate);
$user = $response['user'];
$parametersArray = explode(',', $parameter);
// Varify user allowed permissions
// $reslult = $this->publicUserPermissionService->publicUserPermissionCheck($user, $parametersArray, $this->translator);
// if ($reslult['success'] !== true) {
// return $this->json($reslult);
// }
$response = $this->meteomaticApiService->publicRouteQuery(
$startDate,
$endDate,
$resolution,
$parametersArray,
$coordinate,
$format,
$model,
$source,
$onInvalid
);
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/cfo-report", name="public_cfo_report", methods={"POST"})
* @Route("/api/public/forecast-report", name="public_cfo_forecast_report", methods={"POST"})
*/
public function getCfoReport(Request $request): JsonResponse
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$params = json_decode($request->getContent(), true) ?: [];
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$reportType = '10-day-forecast-report';
$ccode = $params['ccode'] ?? null;
$isCfo = $this->parseRequestBoolParam($params, true, 'isCFO', 'isCfo', 'is_cfo');
$latest = $this->reportingPortalModel->getLatestReport([
'reportType' => $reportType,
]);
if (!is_array($latest) || !isset($latest['success']) || $latest['success'] !== true || !isset($latest['data'])) {
return $this->json(['success' => false, 'message' => 'Failed to fetch latest report']);
}
$latestData = $latest['data'];
$jsonDataFull = isset($latestData['jsonData']) && is_array($latestData['jsonData']) ? $latestData['jsonData'] : [];
if ($jsonDataFull === []) {
return $this->json(['success' => false, 'message' => 'Empty jsonData in latest report']);
}
$filterByNames = [];
if (isset($params['filterByNames']) && is_array($params['filterByNames'])) {
$filterByNames = $params['filterByNames'];
} elseif (isset($params['filter_by_names']) && is_array($params['filter_by_names'])) {
$filterByNames = $params['filter_by_names'];
}
$hasNameFilter = $filterByNames !== [];
$jsonDataForMerge = $hasNameFilter
? $this->filterJsonDataByNames($jsonDataFull, $filterByNames)
: $jsonDataFull;
$latestForMerge = $latest;
if ($hasNameFilter) {
$filteredLatestData = $latestData;
$filteredLatestData['jsonData'] = $jsonDataForMerge;
$latestForMerge['data'] = $filteredLatestData;
}
$reportId = $latestData['id'] ?? 0;
$redisKey = CfoReportPayloadBuilder::redisKey($reportType, $ccode, $reportId, $isCfo);
// Cache-aside: the cached payload is already normalized (weatherinfo flags + current-param
// fallbacks applied at write time), so a cache hit can return it directly without re-running
// normalizeJsonDataCurrentFlags(). On miss we build, normalize once, then store.
// Skip cache when filterByNames is set — cached payload is the full report, not a name-filtered subset.
$cachedFinalData = null;
if (!$hasNameFilter) {
try {
$cachedFinalData = $this->redisCache->get($redisKey);
} catch (\Throwable $redisEx) {
$this->logger->warning('CFO report cache read failed; building without cache: ' . $redisEx->getMessage());
}
}
$cacheLooksValid = is_array($cachedFinalData)
&& isset($cachedFinalData['jsonData'])
&& is_array($cachedFinalData['jsonData'])
&& $cachedFinalData['jsonData'] !== [];
if ($cacheLooksValid) {
// Cache hit: payload was normalized before storage — return as-is.
$finalData = $cachedFinalData;
$mergedJsonData = $finalData['jsonData'];
} else {
$finalData = null;
$builtFromMerge = false;
try {
$built = $this->cfoReportPayloadBuilder->buildMergedFinalDataFromLatest($ccode, $latestForMerge, $isCfo);
if (isset($built['success']) && $built['success'] === true && isset($built['data'])) {
$finalData = $built['data'];
$builtFromMerge = true;
} else {
$this->logger->warning('CFO report merge failed; falling back to report data: ' . ($built['message'] ?? 'Unknown error'));
}
} catch (\Throwable $cfoEx) {
$this->logger->warning('CFO report merge failed; falling back to report data: ' . $cfoEx->getMessage());
}
if ($finalData === null) {
$finalData = $latestData;
$finalData['jsonData'] = $jsonDataForMerge;
}
// Normalize once, before caching, so subsequent cache hits skip this step entirely.
$mergedJsonData = $this->cfoReportPayloadBuilder->normalizeJsonDataCurrentFlags(
$finalData['jsonData'],
$isCfo
);
$finalData['jsonData'] = $mergedJsonData;
// Only cache successful merges (not the report-data fallback) and not name-filtered subsets.
if ($builtFromMerge && !$hasNameFilter) {
try {
$this->redisCache->set($redisKey, $finalData, CFO_REPORT_CACHE_TTL);
} catch (\Throwable $redisEx) {
$this->logger->warning('CFO report cache write failed; returning fresh data anyway: ' . $redisEx->getMessage());
}
}
}
$searchTerm = isset($params['search']) ? trim($params['search']) : null;
if ($searchTerm !== null && $searchTerm !== '') {
$searchTermLower = mb_strtolower($searchTerm);
$filteredJsonData = [];
foreach ($mergedJsonData as $cityData) {
$cityEn = $cityData['cityEn'] ?? '';
$cityAr = $cityData['cityAr'] ?? '';
if (mb_strpos(mb_strtolower($cityEn), $searchTermLower) !== false ||
mb_strpos(mb_strtolower($cityAr), $searchTermLower) !== false) {
$filteredJsonData[] = $cityData;
}
}
$mergedJsonData = $filteredJsonData;
}
$searchByPhenomenon = isset($params['search_by_phenomenon']) ? trim($params['search_by_phenomenon']) : null;
if ($searchByPhenomenon !== null && $searchByPhenomenon !== '') {
$phenomenonLower = mb_strtolower($searchByPhenomenon);
$filteredJsonData = [];
foreach ($mergedJsonData as $cityData) {
$currentParamsRow = $cityData['currentParameters'] ?? [];
$phenomenonAr = $currentParamsRow['currentWeather_PhenomenonAr'] ?? '';
$phenomenonEn = $currentParamsRow['currentWeather_PhenomenonEn'] ?? '';
if (mb_strpos(mb_strtolower($phenomenonEn), $phenomenonLower) !== false ||
mb_strpos(mb_strtolower($phenomenonAr), $phenomenonLower) !== false) {
$filteredJsonData[] = $cityData;
}
}
$mergedJsonData = $filteredJsonData;
}
$finalData['jsonData'] = $mergedJsonData;
return $this->json([
'success' => true,
'data' => $finalData,
]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/wms/tile", name="api_public_wms_tile", methods={"GET"})
*/
public function getPublicWmsTile(Request $request): Response
{
try {
$layers = $request->query->get('layers');
$time = $request->query->get('time');
$bbox = $request->query->get('bbox');
if (empty($layers) || empty($time) || empty($bbox)) {
return $this->json([
'success' => false,
'message' => 'Missing required parameters: layers, time, bbox'
], 400);
}
$format = $request->query->get('format', 'image/webp');
$width = (int) $request->query->get('width', 256);
$height = (int) $request->query->get('height', 256);
$crs = $request->query->get('crs', 'EPSG:3857');
$version = $request->query->get('version', '1.3.0');
$service = $request->query->get('service', 'WMS');
$wmsRequest = $request->query->get('request', 'GetMap');
$styles = $request->query->get('styles', '');
$transparent = $request->query->get('transparent', 'true');
$model = $request->query->get('model');
$webpQuality = $request->query->get('webp_quality_factor');
// Build query string for upstream WMS
$queryParams = [
'service' => $service,
'request' => $wmsRequest,
'layers' => $layers,
'styles' => $styles,
'format' => $format,
'transparent' => $transparent,
'version' => $version,
'time' => $time,
'width' => $width,
'height' => $height,
'crs' => $crs,
'bbox' => $bbox,
];
if (!empty($model)) {
$queryParams['model'] = $model;
}
if (!empty($webpQuality)) {
$queryParams['webp_quality_factor'] = $webpQuality;
}
// Ensure RFC3986 encoding for characters like "/" and ":"
$paramString = http_build_query($queryParams, '', '&', PHP_QUERY_RFC3986);
// Fetch from Meteomatics service (auth handled by service)
$binary = $this->meteomaticsWeatherService->getWms(['param' => $paramString]);
// Determine content type
$contentType = strtolower($format);
if (strpos($contentType, 'image/') !== 0) {
$contentType = 'image/' . ltrim($contentType, '/');
}
$response = new Response($binary);
$response->headers->set('Content-Type', $contentType);
$response->headers->set('Cache-Control', 'public, max-age=300');
return $response;
} catch (\Throwable $ex) {
return $this->json(['success' => false, 'message' => $ex->getMessage()], 500);
}
}
/**
* @Route("/api/public/get-report-detail", name="public_get_report_detail")
*/
public function getReportDetails(Request $request)
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$user = $response['user'];
// $params = json_decode($request->getContent(), true);
$requestUri = $request->getRequestUri();
// Extract the last segment from the URL
$segments = explode('/', trim($requestUri, '/'));
$action = end($segments);
$action = str_replace("-", "_", $action);
$params[] = $action;
// $reslult = $this->publicUserPermissionService->publicUserPermissionCheck($user, $params, $this->translator);
// if ($reslult['success'] !== true) {
// return $this->json($reslult);
// }
$latestReport = Report::getList([
"limit" => 1,
"orderKey" => "createdOn",
"order" => "desc"
]);
if ($latestReport->getCount() <= 0) {
throw new \Exception('no_latest_report_found');
} else {
$data = [];
foreach ($latestReport as $report) {
$data = [
'name' => $report->getCreatedBy()?->getName(),
'email' => $report->getCreatedBy()?->getEmail(),
'jsonData' => json_decode($report->getJsonData(), true),
'createdOn' => $report->getCreatedOn()
];
}
return $this->json(['success' => true, 'data' => $data]);
}
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/ews-analytics", methods={"POST"})
*/
public function ewsAnalyticsAction(Request $request): JsonResponse
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
$result = $this->ewsNotificationModel->ewsAnalytics($params, $this->connection, $lang);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/generate-report", methods={"POST"})
*/
public function generateReport(Request $request): JsonResponse
{
try {
$response = [];
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (
!isset($params['from_date']) ||
!isset($params['to_date']) ||
!isset($params['hours']) ||
!isset($params['parameters']) ||
!isset($params['locations'])
) {
throw new \Exception('Missing required parameters');
}
if (empty($params['parameters'] || !is_array($params['parameters']))) {
throw new \Exception('Parameters should be non empty array');
}
if (empty($params['locations'] || !is_array($params['locations']))) {
throw new \Exception('Locations should be non empty array');
}
$model = isset($params['model']) ? $params['model'] : 'mix';
$redisKey = md5('generate_city_report-' . $params['from_date'] . '-' . $params['to_date'] . '-' . $params['hours'] . '-' . implode('_', $params['locations'])) . '-' . implode('_', $params['parameters']) . '-' . $model;
$data = $this->redisCache->get($redisKey);
if (!$data) {
$cities = new \Pimcore\Model\DataObject\City\Listing();
if (!empty($params['locations'])) {
$cities->setCondition('o_id IN (?)', [$params['locations']]);
}
$cities->load();
if ($cities->getCount() > 0) {
$params['coordinates'] = []; // Initialize an empty array for coordinates
$result = [];
$citiesArr = [];
foreach ($cities as $city) {
$params['coordinates'][] = [$city->getLatitude(), $city->getLongitude()];
// Append the coordinates for each city
$long = number_format($city->getLongitude(), 6, '.', '');
$lat = number_format($city->getLatitude(), 6, '.', '');
$citiesArr[$lat . '|' . $long]["en"] = $city->getCityName("en");
$citiesArr[$lat . '|' . $long]["ar"] = $city->getCityName("ar");
}
$result = $this->meteomaticsWeatherService->getReportForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $model, $params['parameters'], $this->translator, $citiesArr, $params);
$response[] = $result;
$jsonResponse = ['success' => true, 'data' => $response];
$this->redisCache->set($redisKey, $jsonResponse, REDIS_CACHE_TIME);
return $this->json($jsonResponse);
} else {
return $this->json(['success' => true, 'message' => $this->translator->trans('no_city_found')]);
}
} else {
return $this->json($data);
}
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/update-report", methods={"POST"})
*/
public function updateReport(Request $request)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// Perform parameter validation here
// || !isset($params['locations'])
if (!isset($params['data']) || !isset($params['start_date']) || !isset($params['end_date']) || !isset($params['lang'])) {
return $this->json(['success' => false, 'message' => $this->translator->trans('missing_required_parameters')]);
}
if (isset($params['organizations'])) {
if (!is_array($params['organizations'])) {
throw new \Exception($this->translator->trans('Organizations should be non empty array'), 400);
}
}
if (isset($params['channels'])) {
if (!is_array($params['channels']) || empty($params['channels'])) {
throw new \Exception($this->translator->trans('Channels should be non empty array'), 400);
}
if (in_array('email', $params['channels'])) {
if (!isset($params['emails']) || !is_array($params['emails']) || empty($params['emails'])) {
throw new \Exception($this->translator->trans('Emails should be non empty array'), 400);
}
}
}
$result = $this->reportModel->editReport($user, $params, $this->translator, $this->logger);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-city-list", name="public-city-listing")
*/
public function getCityListAction(Request $request)
{
try {
$result = [];
$lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$reportTypeId = $params['report_type_id'] ?? null;
$cities = new \Pimcore\Model\DataObject\City\Listing();
$cities->setOrderKey('cityName');
$cities->setOrder("ASC");
if ($reportTypeId) {
$cities->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" . $reportTypeId . "', ',', '|'), '(,|$)')");
} else {
$db = \Pimcore\Db::get();
$selectedLocalities = $db->fetchAllAssociative("SELECT oo_id FROM `object_query_ReportType` WHERE (`isAutomaticReport` = 0)");
$ooIds = array_column($selectedLocalities, 'oo_id');
$cities->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" . implode(',', $ooIds) . "', ',', '|'), '(,|$)')");
}
$cities->load();
if ($cities->getCount() > 0) {
foreach ($cities as $city) {
$result[] = [
"id" => $city->getId(),
"name" => $city->getCityName($lang),
"nameEn" => $city->getCityName('en'),
"nameAr" => $city->getCityName('ar'),
"lat" => $city->getLatitude(),
"long" => $city->getLongitude(),
"googlePlaceName" => $city->getGooglePlaceName(),
];
}
return $this->json(["success" => true, "data" => $result]);
}
return $this->json(["success" => false, "message" => $this->translator->trans("no_city_is_available")]);
} catch (\Exception $ex) {
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/list-report", name="public-report-listing")
*/
public function getReportListAction(Request $request, PaginatorInterface $paginator)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['page']) || !isset($params['limit'])) {
throw new \Exception('Missing required params: page or limit');
}
$report_type = isset($params['report_type']) ? $params['report_type'] : null;
$lang = isset($params['lang']) ? $params['lang'] : DEFAULT_LOCALE;
$isPublicReports = isset($params['publicReports']) ? $params['publicReports'] : false; // sending this flag from public portal to get all reports accordong to our needs
$page = $params['page'];
$limit = $params['limit'];
$result = $this->reportModel->reportList($params, $page, $limit, $this->translator, $paginator, $report_type, $user, $lang, $isPublicReports);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/generate-report-pdf", name="public-report-pdf")
*/
public function generateReportPdf(Request $request)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
return $this->getPdfReport($request, $user, 'pdf/report_pdf_template.html.twig', $this->translator, '_manned_forecast_report.pdf');
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-report-types", name="public-report-types-listing")
*/
public function getReportTypes(Request $request)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['automatic'])) {
throw new \Exception('missing_required_parameters');
}
$result = [];
$automatic = $params['automatic'] ? true : false;
$reportTypes = new \Pimcore\Model\DataObject\ReportType\Listing();
$reportTypes->setCondition('isAutomaticReport = ?', [$automatic]);
$reportTypes->load();
if ($reportTypes->getCount() > 0) {
foreach ($reportTypes as $reportType) {
$result[] = [
"id" => $reportType->getId(),
"key" => $reportType->getReportKey(),
"nameEn" => $reportType->getName('en'),
"nameAr" => $reportType->getName('ar'),
"descriptionEn" => $reportType->getDescription('en'),
"descriptionAr" => $reportType->getDescription('ar'),
"titleEn" => $reportType->getTitle('en'),
"titleAr" => $reportType->getTitle('ar'),
"automatic" => $reportType->getIsAutomaticReport()
];
}
return $this->json(["success" => true, "data" => $result]);
}
return $this->json(["success" => false, "message" => $this->translator->trans("no_reportType_is_available")]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-weather-params-list", name="public-weather-params-listing")
*/
public function getWeatherParamsListAction(Request $request)
{
try {
$result = [];
$lang = ($request->headers->has('lang')) ? $request->headers->get('lang') : "en";
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['report_type_id'])) {
return $this->json(['success' => false, 'message' => $this->translator->trans('missing_required_parameters')]);
}
$reportTypeId = $params['report_type_id'];
$parameters = new \Pimcore\Model\DataObject\ReportWeatherParameters\Listing();
$parameters->setCondition("reportType REGEXP CONCAT('(^|,)', REPLACE('" . $reportTypeId . "', ',', '|'), '(,|$)')");
$parameters->load();
if ($parameters->getCount() > 0) {
foreach ($parameters as $paramter) {
$result[] = [
"id" => $paramter->getId(),
"nameEn" => $paramter->getName('en'),
"nameAr" => $paramter->getName('ar'),
"meteoMaticsKey" => $paramter->getMeteoMaticsKey(),
"units" => $paramter->getUnits(),
"unitTitle" => $paramter->getUnitTitle()
];
}
return $this->json(["success" => true, "data" => $result]);
}
return $this->json(["success" => false, "message" => $this->translator->trans("no_weather_parameter_is_available")]);
} catch (\Exception $ex) {
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/generate-excel", name="public-generate-excel")
*/
public function generateExcelReport(Request $request)
{
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['id'])) {
throw new \Exception('missing_required_parameters');
}
$report = Report::getById($params['id'], true);
if (!$report instanceof Report) {
throw new \Exception('no_report_found');
}
// Replace this with the actual data you want to use
$jsonData = json_decode($report->getJsonData(), true);
// Create a new PhpSpreadsheet instance
$spreadsheet = new Spreadsheet();
// Create a worksheet
$sheet = $spreadsheet->getActiveSheet();
// Determine headers dynamically based on the first item in the data
$firstItem = reset($jsonData);
$parameters = $firstItem['parameters'] ?? [];
$headers = ['City', 'Lat', 'Lon', 'Date']; // Initialize headers with common columns
// Extract parameter names and add them to headers
foreach ($parameters as $parameter) {
$headers[] = $parameter['parameter'];
}
// Add headers to the worksheet
foreach ($headers as $index => $header) {
$sheet->setCellValueByColumnAndRow($index + 1, 1, $header);
}
// Initialize row counter
$row = 2;
foreach ($jsonData as $item) {
// Extract city-related data
$cityData = [$item['city'] ?? '', $item['lat'] ?? '', $item['lon'] ?? ''];
// Loop through each date for all parameters
foreach ($item['parameters'][0]['dates'] as $dateIndex => $date) {
// Initialize row data with city-related data and date
$rowData = array_merge($cityData, [date('Y-m-d', strtotime($date['date']))]);
// Loop through each parameter
foreach ($item['parameters'] as $parameter) {
// Check if the value is set for the current date, otherwise set it to 0
$value = isset($parameter['dates'][$dateIndex]['value']) ? $parameter['dates'][$dateIndex]['value'] : 0;
// Add parameter value for the current date to the row data
$rowData[] = $value;
}
// Set cell values explicitly
foreach ($rowData as $colIndex => $cellValue) {
$sheet->setCellValueByColumnAndRow($colIndex + 1, $row, $cellValue);
}
// Increment the row counter
$row++;
}
}
// Save the Excel file to var/export directory
$exportDir = PIMCORE_PROJECT_ROOT . '/var/export/';
if (!is_dir($exportDir)) {
@mkdir($exportDir, 0755, true);
}
$filename = $user->getId() . '_weather_report';
$timestampedFilename = $filename . '_' . time() . '.xlsx';
$exportPath = $exportDir . $timestampedFilename;
$writer = new Xlsx($spreadsheet);
$writer->save($exportPath);
// Return download URL using download-excel.php
$baseUrl = $_ENV['BASE_URL_DEMO_AJWAA_API'] ?? API_BASE_URL ?? '';
$downloadUrl = rtrim($baseUrl, '/') . '/download-excel.php?file=' . urlencode($timestampedFilename);
return $this->json(['success' => true, 'data' => $downloadUrl]);
}
/**
* @Route("/api/public/generate-historical-report", methods={"POST"})
*/
public function generateHistoricalReport(Request $request): JsonResponse
{
try {
$response = [];
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (
!isset($params['from_date']) ||
!isset($params['to_date']) ||
!isset($params['hours']) ||
!isset($params['parameters']) ||
!isset($params['locations'])
) {
throw new \Exception('Missing required parameters');
}
if (empty($params['parameters'] || !is_array($params['parameters']))) {
throw new \Exception('Parameters should be non empty array');
}
if (empty($params['locations'] || !is_array($params['locations']))) {
throw new \Exception('Locations should be non empty array');
}
if ($params['to_date'] > date('Y-m-d', strtotime(Carbon::now()))) {
$daysadd = date('Y-m-d', strtotime(Carbon::now()->addDays('17')));
if ($params['to_date'] >= $daysadd) {
throw new \Exception('End date limit exceeded');
}
}
$model = isset($params['model']) ? $params['model'] : 'mix';
$redisKey = md5('generate_city_report-' . $params['from_date'] . '-' . $params['to_date'] . '-' . $params['hours'] . '-' . implode('_', $params['locations'])) . '-' . implode('_', $params['parameters']) . '-' . $model;
$data = $this->redisCache->get($redisKey);
if (!$data) {
$cities = new \Pimcore\Model\DataObject\Location\Listing();
if (!empty($params['locations'])) {
$cities->setCondition('o_id IN (?)', [$params['locations']]);
}
$cities->load();
if ($cities->getCount() > 0) {
$params['coordinates'] = []; // Initialize an empty array for coordinates
$result = [];
$citiesArr = [];
foreach ($cities as $city) {
$cityLocations = json_decode($city->getCoordinates(), true);
foreach ($cityLocations as $coordinates) {
$long = number_format($coordinates[1], 6, '.', '');
$lat = number_format($coordinates[0], 6, '.', '');
$params['coordinates'][] = $coordinates;
$citiesArr[$lat . '|' . $long] = $city->getName();
}
}
$result = $this->meteomaticsWeatherService->getReportForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $model, $params['parameters'], $this->translator, $citiesArr, $params);
$response[] = $result;
$jsonResponse = ['success' => true, 'data' => $response];
$this->redisCache->set($redisKey, $jsonResponse, REDIS_CACHE_TIME);
return $this->json($jsonResponse);
} else {
return $this->json(['success' => true, 'message' => $this->translator->trans('no_city_found')]);
}
} else {
return $this->json($data);
}
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-latest-report", name="public-get-latest-report")
*/
public function getLatestReport(Request $request)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$params = json_decode($request->getContent(), true);
$reportType = (isset($params['report_type']) && !empty($params['report_type'])) ? $params['report_type'] : 'ten-day-forecast-report';
$result = $this->reportModel->getLatestReport($reportType, $this->translator, false);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-automatic-reports", name="public_get_automatic_reports")
*/
public function getAutomaticReports(Request $request, PaginatorInterface $paginator)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['page']) || !isset($params['limit']) || !isset($params['lang'])) {
throw new \Exception('Missing required parameters');
}
$search = isset($params['search']) ? $params['search'] : null;
$orderKey = isset($params['orderKey']) ? $params['orderKey'] : 'createdOn';
$order = isset($params['order']) ? $params['order'] : 'desc';
$result = $this->reportModel->listAutomaticReports($params, $user, $search, $orderKey, $order, $this->translator, $paginator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/generate-automatic-report-pdf", name="public-automatic-report-pdf")
*/
public function generateAutomaticReportPdf(Request $request)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$result = $this->reportModel->generatePdfReport($request, $user, $this->snappy, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
public function getPdfReport($request, $user, $template, $translator, $report_type)
{
$params = json_decode($request->getContent(), true);
if (!isset($params['id'])) {
return $this->json(["success" => false, "message" => $translator->trans("missing_required_parameters")]);
}
$report = Report::getById($params['id'], true);
$lang = isset($params['lang']) ? $params['lang'] : "en";
if (!$report instanceof Report) {
return $this->json(["success" => false, "message" => $translator->trans("no_report_found")]);
}
$asset = $lang == 'ar' ? $report->getAssetAr() : $report->getAsset();
if ($asset) {
$pdfasset = API_BASE_URL . $asset->getPath() . $asset->getFilename();
return $this->json(['success' => true, 'data' => $pdfasset]);
}
//$template=$report->getReportType()?->getKey() == 'MannForecastReport'?'pdf/report_pdf_template.html.twig':'pdf/automatic_report_pdf_template.html.twig';
$fileName = '_custom_weather_report.pdf';
$reportPath = '/report/ReportPdf';
if ($report->getReportType()?->getKey() == 'MannForecastReport') {
$template = 'pdf/report_pdf_template.html.twig';
} elseif ($report->getReportType()?->getKey() == 'advance-custom-weather-report') {
$template = 'pdf/advance_custom_report_pdf_template.html.twig';
$fileName = '_advance_custom_weather_report.pdf';
$reportPath = '/report/advanceCustomReportPdf';
} else {
$template = 'pdf/automatic_report_pdf_template.html.twig';
}
$parameter = [
'data' => $report,
'reportTitleEn' => $report->getReportTitle('en'),
'reportTitleAr' => $report->getReportTitle('ar'),
'reportDescriptionEn' => $report->getDescription('en'),
'reportDescriptionAr' => $report->getDescription('ar'),
'reportDisclaimerEn' => $report->getReportDisclaimer('en'), // new
'reportDisclaimerAr' => $report->getReportDisclaimer('ar'), // new
'additionalNoteEn' => $report->getAdditionalNote('en'), // new
'additionalNoteAr' => $report->getAdditionalNote('ar'), // new
'template' => $template,
'lang' => $lang
];
// return $this->render('pdf/automatic_report_pdf_template_copy.html.twig',$parameter);
$pdf = \App\Lib\Utility::generatePdf($parameter, $this->snappy);
// $tempFilePath = tempnam(sys_get_temp_dir(), 'image_');
// file_put_contents($tempFilePath, $pdf);
// Create a BinaryFileResponse and set headers
// $response = new BinaryFileResponse($tempFilePath);
// $response->headers->set('Content-Type', 'application/pdf');
// $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, 'image.pdf');
// Return the response
// return $response;
$asset = \App\Lib\Utility::createAsset($pdf, $user->getId() . '_' . time() . $report_type, $reportPath);
$pdfasset = '';
if ($asset instanceof Asset) {
$pdfasset = API_BASE_URL . $asset->getPath() . $asset->getFilename();
}
if ($lang == 'ar') {
$report->setAssetAr($asset);
} else {
$report->setAsset($asset);
}
$report->save();
return $this->json(['success' => true, 'data' => $pdfasset]);
}
/**
* @Route("/api/public/get-today-weather-report", name="public_get_today_weather_report")
*/
public function getTodayWeatherReports(Request $request, PaginatorInterface $paginator)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$params = json_decode($request->getContent(), true);
if (!isset($params['page']) || !isset($params['limit']) || !isset($params['lang'])) {
throw new \Exception('Missing required parameters');
}
$result = $this->reportModel->getTodayWeatherReports($params, $this->translator, $paginator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-report-weather-symbols", name="public_get_report_weather_symbols")
*/
public function getReportWeatherSymbols(Request $request): JsonResponse
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$data = [];
$weatherSymbols = new ReportWeatherSymbols\Listing();
foreach ($weatherSymbols as $weatherSymbol) {
if ($weatherSymbol) {
$weatherSymbolNames = $weatherSymbol->getWeatherSymbols();
$weatherSymbolIcons = $weatherSymbol->getWeatherIcons();
if ($weatherSymbolNames) {
foreach ($weatherSymbolNames as $weatherSymbolName) {
$response['symbols'][] = [
'nameEn' => $weatherSymbolName->getSymbolName('en'),
'nameAr' => $weatherSymbolName->getSymbolName('ar'),
];
}
}
if ($weatherSymbolIcons) {
foreach ($weatherSymbolIcons as $weatherSymbolIcon) {
$response['icons'][] = [
'iconValue' => $weatherSymbolIcon->getIconValue(),
];
}
}
}
$data[] = $response;
}
return $this->json(['success' => true, 'data' => $data]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/get-forecast-cities", methods={"POST"})
* @Route("/api/public/get-cities", name="get-wso-cities")
*/
public function getForecastCities(Request $request): Response
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$forecastCityModel = new WeatherForecastCityModel();
$cities = $forecastCityModel->getWeatherForecastCities($params);
return $this->json(['success' => true, 'data' => $cities]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-regions-bbox", name="get-regions-bbox")
*/
public function getRegionsBbox(Request $request)
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$data = REGIONS_BBOX;
return $this->json(['success' => true, 'data' => $data]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-station-data", methods={"GET"})
*/
public function getWeatherStationDataAction(Request $request)
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$typeName = $request->get('type_name');
$parameters = $request->get('parameters');
$dateTime = $request->get('date_time');
$bBox = $request->get('b_box');
if (!$typeName) {
throw new \InvalidArgumentException("Missing mandatory parameter: type_name");
}
if (!$parameters) {
throw new \InvalidArgumentException("Missing mandatory parameter: parameters");
}
if (!$dateTime) {
throw new \InvalidArgumentException("Missing mandatory parameter: date_time");
}
if (!$bBox) {
throw new \InvalidArgumentException("Missing mandatory parameter: b_box");
}
$result = $this->meteomaticsWeatherService->getWeatherStationData($typeName, $parameters, $dateTime, $bBox);
return $result;
} catch (\Exception $ex) {
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/daily-forecast", methods={"POST"})
*/
public function dailyForecast(Request $request): JsonResponse
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$requiredParameters = ['coordinates', 'from_date', 'to_date', 'model'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$result = $this->meteomaticsWeatherService->getForecastData($params['coordinates'], $params['from_date'], $params['to_date'], $params['hours'], $params['model'], $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/weather/{path}", name="api_meteomatics", requirements={"path"=".+"}, methods={"GET"})
*/
public function getDynamicWeatherData(Request $request, string $path): Response
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$user = $response['user'];
$queryParams = $request->query->all();
$weatherData = $this->meteomaticApiService->getDynamicWeatherData($path, $queryParams, $user);
return $weatherData;
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/create-manned-alert-subscription", methods={"POST"})
*/
public function mannedAlertSubscription(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$user = $response['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// $requiredParameters = ['region_id', 'governorate_id', 'alert_type_id'];
// foreach ($requiredParameters as $param) {
// if (!isset($params[$param]) || empty($params[$param])) {
// $missingParams[] = $param;
// }
// }
// if (!empty($missingParams)) {
// // Throw an exception with a message that includes the missing parameters
// $parameterList = implode(", ", $missingParams);
// return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
// }
$result = $this->customNotificationService->mannedAlertSubscription($user, $params, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/upload-bulk-locations", methods={"POST"})
*/
public function uploadBulkLocations(Request $request): JsonResponse
{
try {
$lang = $request->request->get('lang');
$email = $request->request->get('email', 'umer.wasi@centricdxb.com');
$name = $request->request->get('name', 'User');
$reason = $request->request->get('request_reason', 'N/A');
$file = $request->files->get('file');
$this->translator->setlocale(isset($lang) ? $lang : DEFAULT_LOCALE);
if (!$file || !$file->isValid()) {
return new JsonResponse(['success' => false, 'message' => 'Invalid or missing file'], 400);
}
// Upload file to c2service and get asset ID
$assetId = $this->c2Service->uploadToC2service($file);
if (!$assetId) {
throw new \Exception('Failed to upload to c2service');
}
$html = $this->templating->render('web2print/_request_location.html.twig', ['name' => $name, 'reason' => $reason]);
$result = $this->c2Service->sendWeatherDashboardEmail($_ENV['WEATHER_DASHBOARD_LOCATIONS'], $email, $html, '', $assetId);
return $this->json(['success' => true, 'message' => $this->translator->trans('file_successfully_submitted')]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/get-token", methods={"POST"})
*/
public function getToken(Request $request): JsonResponse
{
try {
$result = $this->meteomaticApiService->getToken();
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/get-solar-power", methods={"POST"})
*/
public function getSolarPowerAction(Request $request)
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$mandatoryParams = ['latitude', 'longitude', 'hour', 'specification', 'interval_in_hours', 'start_date', 'end_date', 'unit'];
foreach ($mandatoryParams as $param) {
if (!isset($params[$param]) || empty($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
throw new \InvalidArgumentException(sprintf($this->translator->trans("missing_or_empty_mandatory_parameter: %s"), $parameterList));
}
// Extract the necessary parameters for getWeatherWarnings function
$coordinates = [[$params['latitude'], $params['longitude']]];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$specification = $params['specification'];
$intervalInHours = $params['interval_in_hours'];
$hour = $params['hour'];
$unit = $params['unit'];
// Call the getWindPower function with validated parameters
$result = $this->meteomaticsWeatherService->getSolarPower($coordinates, $startDate, $endDate, $intervalInHours, $hour, $unit, $specification, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/air-density", methods={"POST"})
*/
public function airdensityData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'coordinates', 'level', 'unit', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$coordinates = $params['coordinates'];
$level = $params['level'];
$unit = $params['unit'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getAirdensity(
$hour,
$startDate,
$endDate,
$coordinates,
$level,
$unit,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/get-metar-data", methods={"POST"})
*/
public function getMetarData(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['startDate', 'endDate', 'metar', 'duration'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$startDate = $params['startDate'];
$endDate = $params['endDate'];
$metar = $params['metar'];
$duration = $params['duration'];
$parameters = $params['parameter'] ?? null;
$genExcel = $request->get('gen_excel', false);
$metarData = $this->meteomaticsWeatherService->getMetarData($startDate, $endDate, $metar, $duration, $this->translator, $parameters, $genExcel);
return $this->json(['success' => true, 'message' => $this->translator->trans("excel_file_downloaded_successfully"), 'data' => $metarData]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/frost-thaw-depth", methods={"POST"})
*/
public function frostThawAndDepthData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'unit', 'coordinates', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$unit = $params['unit'];
$coordinates = $params['coordinates'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getFrostThawAndDepth(
$hour,
$startDate,
$endDate,
$unit,
$coordinates,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/get-hail-index", methods={"POST"})
*/
public function getHailIndexAction(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$mandatoryParams = ['coordinates', 'start_date', 'end_date', 'duration', 'interval_type'];
foreach ($mandatoryParams as $param) {
if (!isset($params[$param]) || empty($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
// Extract the necessary parameters for getWeatherWarnings function
$coordinates = $params['coordinates'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$intervalType = $params['interval_type'];
$duration = $params['duration'] ?? '5';
$format = $params['format'] ?? 'json';
// Call the getWeatherWarnings function with validated parameters
$result = $this->meteomaticsWeatherService->getHailIndex($coordinates, $startDate, $endDate, $duration, $intervalType, $format, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/weather/soil-moisture-index", methods={"POST"})
*/
public function soilMoistureIndexData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'coordinates', 'level', 'unit', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$coordinates = $params['coordinates'];
$level = $params['level'];
$unit = $params['unit'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getSoilMoistureIndex(
$hour,
$startDate,
$endDate,
$coordinates,
$level,
$unit,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/get-moving-average", methods={"POST"})
*/
public function getMovingAverage(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$requiredParameters = ['start_from', 'days', 'location', "name"];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
switch ($params['name']) {
case 'temperature_day':
$data = $this->insuranceIndustryService->mmTemperatureDay($params['start_from'], $params['days'], $params['location']);
break;
case 'temperature_night':
$data = $this->insuranceIndustryService->mmTemperatureNight($params['start_from'], $params['days'], $params['location']);
break;
case 'wind_speed':
$data = $this->insuranceIndustryService->mmWindSpeed($params['start_from'], $params['days'], $params['location']);
break;
case 'soil_water_content':
$data = $this->insuranceIndustryService->mmSoilWaterContent($params['start_from'], $params['days'], $params['location']);
break;
default:
// Handle invalid function name
return $this->json(['success' => false, 'message' => 'Invalid name']);
}
return $this->json(['success' => true, 'data' => $data]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/weather/heat-index", methods={"POST"})
*/
public function heatIndexData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'coordinates', 'unit', 'format', 'model'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$coordinates = $params['coordinates'];
$unit = $params['unit'];
$format = $params['format'];
$model = $params['model'];
$response = $this->meteomaticsWeatherService->getHeatIndex(
$hour,
$startDate,
$endDate,
$coordinates,
$unit,
$format,
$model
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/get-seasonal-average", methods={"POST"})
*/
public function getSeasonalAverager(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$requiredParameters = ['date', 'day_time', 'parameter', 'location'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$data = $this->insuranceIndustryService->seasonalAverage($params['date'], $params['day_time'], $params['parameter'], $params['location']);
return $this->json(['success' => true, 'data' => $data]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/weather/get-threats-table", methods={"POST"})
*/
public function getThreatTable(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$requiredParameters = ['date', 'day_deep', 'location'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$data = $this->insuranceIndustryService->threatTable($params['date'], $params['day_deep'], $params['location']);
return $this->json(['success' => true, 'data' => $data]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/weather/high-low-tide-times", methods={"POST"})
*/
public function highLowTideTimesData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'coordinates', 'model', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$coordinates = $params['coordinates'];
$model = $params['model'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getHighLowTideTimes(
$hour,
$startDate,
$endDate,
$coordinates,
$model,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/tidal-amplitude", methods={"POST"})
*/
public function tidalAmplitudeData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'coordinates', 'unit', 'model', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$coordinates = $params['coordinates'];
$unit = $params['unit'];
$model = $params['model'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getTidalAmplitudes(
$hour,
$startDate,
$endDate,
$coordinates,
$unit,
$model,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/significant-wave-height", methods={"POST"})
*/
public function significantWaveHeightData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'coordinates', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$coordinates = $params['coordinates'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getSignificantWaveHeight(
$hour,
$startDate,
$endDate,
$coordinates,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/surge-amplitude", methods={"POST"})
*/
public function surgeAmplitudeData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['hour', 'start_date', 'end_date', 'coordinates', 'unit', 'model', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$hour = $params['hour'];
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$coordinates = $params['coordinates'];
$unit = $params['unit'];
$model = $params['model'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getSurgeAmplitude(
$hour,
$startDate,
$endDate,
$coordinates,
$unit,
$model,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/fog", methods={"POST"})
*/
public function fogData(Request $request): JsonResponse
{
try {
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['start_date', 'end_date', 'coordinates', 'format'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$startDate = $params['start_date'];
$endDate = $params['end_date'];
$interval = $params['interval'];
$unit = $params['unit'];
$coordinates = $params['coordinates'];
$format = $params['format'];
$response = $this->meteomaticsWeatherService->getFog(
$coordinates,
$startDate,
$endDate,
$interval,
$unit,
$this->translator,
$format
);
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/weather/generic-api", methods={"POST"})
*/
public function fetchMeteomaticData(Request $request): JsonResponse
{
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['format'])) {
throw new \InvalidArgumentException('Missing "format" parameter');
}
if ($params['format'] == "json") {
if (
!isset($params['startdate']) ||
!isset($params['enddate']) ||
!isset($params['resolution']) ||
!isset($params['parameters']) ||
!isset($params['lat']) ||
!isset($params['lon']) ||
!isset($params['format'])
) {
throw new \Exception('Missing required parameters');
}
// date_default_timezone_set('UTC');
//$hour = $params['hour'];
$format = $params['format'];
$startDate = $params['startdate'];
$endDate = $params['enddate'];
$resolution = $params['resolution'];
$parameters = $params['parameters'];
$model = $params['model'];
$lat = $params['lat'];
$lon = $params['lon'];
$response = $this->meteomaticApiService->timeSeriesQuery(
$startDate,
$endDate,
$resolution,
$parameters,
$model,
$lat,
$lon,
$format,
$this->translator
);
} else {
$mandatoryParams = ['version', 'request', 'layers', 'crs', 'bbox', 'format', 'width', 'height', 'tiled'];
foreach ($mandatoryParams as $param) {
if (!isset($params[$param]) || empty($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
throw new \InvalidArgumentException(sprintf($this->translator->trans("missing_or_empty_mandatory_parameter: %s"), $parameterList));
}
header('Content-Type: image/png');
$result = $this->meteomaticsWeatherService->getWeatherMap($params['version'], $params['request'], $params['layers'], $params['crs'], $params['bbox'], $params['format'], $params['width'], $params['height'], $params['tiled']);
echo $result;
exit;
}
// You can return or process the $data as needed
// For demonstration purposes, we will just return a JSON response
return $this->json($response);
}
/**
* @Route("/api/public/weather/top-ten-weather-station", methods={"POST"})
*/
public function topTenWeatherStation(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
// $this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['parameter', 'from_date', 'to_date'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$lang = (isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$result = $this->weatherStationModel->getTopTenWeatherStations($params['parameter'], $params['from_date'], $params['to_date'], $lang);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/weather/get-historical-data-parameters", methods={"POST"})
*/
public function getHistoricalDataParameters(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$data = [];
$historicalDataParameters = new HistoricalDataParameters\Listing();
foreach ($historicalDataParameters as $key => $historicalDataParameter) {
if ($historicalDataParameter) {
$data[] = [
"id" => $historicalDataParameter->getId(),
"key" => $historicalDataParameter->getParameterKey(),
"unit" => $historicalDataParameter->getUnit('en'),
"unit_ar" => $historicalDataParameter->getUnit('ar'),
"name" => $historicalDataParameter->getName('en'),
"name_ar" => $historicalDataParameter->getName('ar')
];
}
}
return $this->json(['success' => true, 'data' => $data]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("api/public/weather-data/{start_date}/{end_date}/{resolution}/{parameter}/{coordinate}/{format}", name="api_dynamic_temperature_weather_data", methods={"GET"})
*/
public function getDynamicTemperatureWeatherData(
Request $request,
string $start_date,
string $end_date,
string $resolution,
string $parameter,
string $coordinate,
string $format
): Response {
try {
// Check user authorization
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$user = $response['user'];
// Optional query parameters
$queryParams = $request->query->all();
// Build Meteomatics-style path
// Example: 2025-12-06T00:00:00Z--2025-12-07T00:00:00Z:PT1H/t_2m:C,t_20m:C/.../json
$path = sprintf(
"%s--%s:%s/%s/%s",
$start_date,
$end_date,
$resolution,
$parameter,
$coordinate
);
// Add format at the end
$path .= '/' . $format;
// Call Meteomatics API service
$weatherData = $this->meteomaticApiService->getDynamicWeatherData($path, $queryParams, $user);
return $weatherData;
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json([
'success' => false,
'message' => $this->translator->trans(USER_ERROR_MESSAGE)
]);
}
}
/**
* @Route("/api/public/get-alert-type", methods={"POST"})
*/
public function getAlertTypeAction(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$result = $this->ewsNotificationModel->getAlertTypes();
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-alert-action", methods={"POST"})
*/
public function getAlertActionAction(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$result = $this->ewsNotificationModel->getAlertActions();
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-phenomena-list-by-alerts", methods={"POST"})
*/
public function getPhenomenaListByAlertsAction(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['alert_id']) && !empty($params['alert_id'])) {
throw new \Exception('Missing required alert id');
}
$alertType = $params['alert_id'];
// $result = $this->ewsNotificationModel->getPhenomenaListByAlertIds($alertType);
$result = $this->ewsNotificationModel->getAlertStatuses($params);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-regions-list", methods={"POST"})
*/
public function getRegionsListAction(Request $request): JsonResponse
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$search = (isset($params['search']) && !empty($params['search'])) ? $params['search'] : null;
$id = (isset($params['id']) && !empty($params['id'])) ? $params['id'] : null;
$result = $this->ncmWeatherApiService->getRegionsByName($search, $id, isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
return $this->json($result);
} catch (\Exception $ex) {
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-governorates-list", methods={"POST"})
*/
public function getGovernoratesListAction(Request $request): JsonResponse
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$result = $this->ewsNotificationModel->getGovernoratesByParams($params);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-municipality-list", methods={"POST"})
*/
public function getMunicipalityListAction(Request $request): JsonResponse
{
try {
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
// check user credentials and expiry
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
if (!isset($params['governorate_id'])) {
throw new \Exception('Missing required governorate id');
}
$governorateId = $params['governorate_id'];
$search = (isset($params['search']) && !empty($params['search'])) ? $params['search'] : null;
$result = $this->ewsNotificationModel->getMunicipalityByParams($governorateId, $search, $params['lang']);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/list-tbase-crops", methods={"POST"})
*/
public function listTbaseCropsAction(Request $request, PaginatorInterface $paginator)
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$crops = $this->agricultureModel->getTbaseCrops($params, $this->translator, $paginator);
return $this->json(['success' => true, 'data' => $crops]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/get-chill-units", methods={"POST"})
*/
public function getChillUnitsAction(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$isAccumulated = $params['isAccumulated'] ?? false;
$latitude = $params['latitude'] ?? null;
$longitude = $params['longitude'] ?? null;
$coordinate = "$latitude,$longitude";
$parametersArray = ['t_min_2m_1h:C', 't_max_2m_1h:C'];
$startDate = new DateTime($params['startDate']);
$endDate = new DateTime($params['endDate']);
$resolution = 'PT1H';
$format = 'json';
$model = 'mix';
$source = '';
$onInvalid = '';
$response = $this->meteomaticApiService->publicRouteQuery(
$startDate,
$endDate,
$resolution,
$parametersArray,
$coordinate,
$format,
$model,
$source,
$onInvalid,
);
$hourlyData = $this->chillUnitService->transformMeteomaticsResponse($response['data']);
if ($isAccumulated) {
$result = $this->chillUnitService->calculateAccumulated($hourlyData);
} else {
$result = $this->chillUnitService->calculate($hourlyData);
}
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/get-water-requirements", methods={"POST"})
*/
public function getWaterRequirementAction(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$regionIds = [];
$latitude = $params['latitude'] ?? null;
$longitude = $params['longitude'] ?? null;
$coordinate = "$latitude,$longitude";
$governorateArr = \App\Lib\Utility::processLocationCoordinates([[$latitude, $longitude]]);
foreach ($governorateArr as $governorateName) {
if ($governorateName['en']) {
$governorate = DataObject\Governorate::getByName($governorateName['en'],'en',true);
if ($governorate instanceof DataObject\Governorate) {
// Assuming getRegion() returns a Region DataObject
$region = $governorate->getRegionId();
$regionIds[] = $region->getId();
}
}
}
$parametersArray = ['evapotranspiration_24h:mm'];
$startDate = new DateTime();
$endDate = new DateTime();
$resolution = 'PT24H';
$format = 'json';
$model = 'mix';
$source = '';
$onInvalid = '';
$kcKeys = $params['kcKeys'] ?? ['kcInitial', 'kcMid', 'kcEnd'];
$cropNames = $params['cropNames'] ?? [];
$response = $this->meteomaticApiService->publicRouteQuery(
$startDate,
$endDate,
$resolution,
$parametersArray,
$coordinate,
$format,
$model,
$source,
$onInvalid,
);
$meteoData = $response['data']['data'][0]['coordinates'];
$cropsData = $this->agricultureModel->getCropsWithRegion($regionIds, $cropNames, $kcKeys, $meteoData);
return $this->json($cropsData);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/calculate-gdd-and-gts", methods={"POST"})
*/
public function calculateGDDandGTSAction(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = [
'coordinates',
'cropIds',
'startDate',
'endDate'
];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$params['meteomaticApiService'] = $this->meteomaticApiService;
$gddAndGtsData = $this->agricultureModel->calculateGDDandGTS($params,$this->translator);
return $this->json($gddAndGtsData);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/crops", methods={"POST"})
*/
public function cropsAction(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$result = $this->agricultureModel->getCrops($request, $params, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/list-location", methods={"POST"})
*/
public function listLocation(Request $request, PaginatorInterface $paginator): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale($params['lang'] ?? DEFAULT_LOCALE);
$result = $this->locationModel->locationListing(
$request,
$user,
$params,
$paginator,
$this->translator
);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json([
'success' => false,
'message' => $ex->getMessage()
]);
}
}
/**
* @Route("/api/public/list-risk-category", methods={"POST"})
*/
public function getRiskCategories(Request $request, PaginatorInterface $paginator)
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = [];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
// Throw an exception with a message that includes the missing parameters
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$result = $this->weatherParameterModel->riskCategoryFetch($params, $paginator, $user);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/locations-for-map", methods={"POST"})
*/
public function getLocationsForMaps(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$parameter = $params['parameter'] ?? null;
$duration = $params['duration'] ?? null;
$dateTime = $params['datetime'] ?? null;
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!$parameter || !$duration || !$dateTime) {
return new JsonResponse(['success' => false, 'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
}
$results = $this->weatherParameterModel->getLocationsForMaps($params, $parameter, $duration, $dateTime, $user, $this->translator);
return $this->json(['success' => true, 'data' => $results]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/locations-by-dates", methods={"POST"})
*/
public function getLocationsByDates(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$parameter = $params['parameter'] ?? null;
$duration = $params['duration'] ?? null;
$dateTime = $params['datetime'] ?? null;
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!$parameter || !$duration || !$dateTime) {
return new JsonResponse(['success' => false, 'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
}
$results = $this->weatherParameterModel->getLocationsbyDates($parameter, $duration, $dateTime, $this->translator);
return $this->json(['success' => true, "lastUpdated" => $results['last_updated_at'], 'data' => $results['data']]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/locations-by-tags", methods={"POST"})
*/
public function getLocationsByTags(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$parameter = $params['parameter'] ?? null;
$duration = $params['duration'] ?? null;
$dateTime = $params['datetime'] ?? null;
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!$parameter || !$duration || !$dateTime) {
return $this->json(['success' => false, 'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
}
$tags = [];
$tagListing = new WeatherParameterLocationTags\Listing();
$tagListing->setCondition("`default` = ?", [true]);
foreach ($tagListing as $tag) {
$tags[] = [
'id' => $tag->getId(),
'nameEn' => $tag->getNameEn(),
'nameAr' => $tag->getNameAr(),
];
}
$desiredOrder = ['High risk', 'Medium risk', 'Low risk'];
usort($tags, function ($a, $b) use ($desiredOrder) {
$posA = array_search($a['nameEn'], $desiredOrder);
$posB = array_search($b['nameEn'], $desiredOrder);
return $posA <=> $posB;
});
$results = $this->weatherParameterModel->getLocationsByTags($parameter, $duration, $dateTime, $tags, $this->translator);
return $this->json(['success' => true, 'data' => $results]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/locations-by-risk", methods={"POST"})
*/
public function getLocationsByRisk(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$parameter = $params['parameter'] ?? null;
$duration = $params['duration'] ?? null;
$dateTime = $params['datetime'] ?? null;
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!$parameter || !$duration || !$dateTime) {
return $this->json(['success' => false, 'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
}
$results = $this->weatherParameterModel->getLocationsByRiskCat($params, $parameter, $duration, $dateTime, $user, $this->translator);
return $this->json(['success' => true, 'data' => $results]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/locations-by-amana", methods={"POST"})
*/
public function getLocationsByAmana(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$parameter = $params['parameter'] ?? null;
$duration = $params['duration'] ?? null;
$dateTime = $params['datetime'] ?? null;
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!$parameter || !$duration || !$dateTime) {
return new JsonResponse(['success' => false, 'message' => $this->translator->trans('missing_parameter_or_duration_or_date')], 400);
}
$results = $this->weatherParameterModel->getLocationsByAmanaId($params, $parameter, $duration, $dateTime, $this->translator);
return $this->json(['success' => true, 'data' => $results]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/weather-reports/list", name="ncm_weather_reports_list", methods={"GET"})
*/
public function listReports(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$user = $response['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$folder = Asset::getByPath("/weather-reports");
if (!$folder) {
return new JsonResponse([
'status' => 'error',
'message' => 'No weather reports found.'
], 404);
}
$reports = [];
foreach ($folder->getChildren() as $asset) {
if ($asset instanceof Asset) {
$title = $asset->getMetadata('title', 'ar');
$reports[] = [
'name' => $asset->getFilename(),
'link' => $asset->getFullPath(),
'title' => ($title !== null && $title !== '') ? $title : null,
];
}
}
return new JsonResponse([
'status' => 'success',
'reports' => $reports
]);
} catch (\Throwable $e) {
return new JsonResponse([
'status' => 'error',
'message' => $e->getMessage()
], 500);
}
}
/**
* @Route("/api/public/create-location", methods={"POST"})
*/
public function createLocationPublic(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['coordinates'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param]) || empty($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
//location address components
// Validate and geocode coordinates
try {
$geocodingUrl = sprintf(
'https://maps.googleapis.com/maps/api/geocode/json?key=%s&latlng=%s,%s&language=%s',
$_ENV['GOOGLE_API_KEY'],
$params['coordinates'][0][0],
$params['coordinates'][0][1],
$params['lang'] ?? 'en'
);
$response = $this->httpClient->get($geocodingUrl);
$response = json_decode($response->getBody()->getContents(), true);
// Check if geocoding was successful
if (!isset($response['status']) || $response['status'] !== 'OK' || empty($response['results'])) {
return $this->json([
'success' => false,
'message' => $this->translator->trans("Invalid coordinates")
]);
}
$params['address_components'] = $response['results'][0]['address_components'] ?? [];
$params['name'] = $this->extractLocality($response);
} catch (\Exception $e) {
return $this->json([
'success' => false,
'message' => $this->translator->trans("Invalid coordinates")
]);
}
$result = $this->locationModel->createLocation($request, $params, $user, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
private function extractLocality(array $response): string
{
if ($response['status'] === 'OK') {
foreach ($response['results'] as $result) {
foreach ($result['address_components'] as $component) {
if (in_array('locality', $component['types'])) {
return $component['long_name'];
}
}
}
}
return '';
}
/**
* @Route("/api/public/bulk-location-upload", methods={"POST"})
*/
public function bulkLocationUpload(Request $request): JsonResponse
{
try {
// $response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
// if ($response['success'] !== true) {
// return $this->json($response);
// }
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false, 'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json(['success' => false, 'message' => 'Invalid User']);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json(['success' => false, 'message' => 'User not found']);
}
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json(['success' => false, 'message' => 'Invalid Consumer Key']);
}
$lang = $request->request->get('lang', 'en');
$this->translator->setlocale($lang);
// Get uploaded file
$file = $request->files->get('file');
if (!$file || !$file->isValid()) {
return $this->json(['success' => false, 'message' => $this->translator->trans('Invalid or missing file')]);
}
// Validate file extension
$allowedExtensions = ['xlsx', 'xls'];
$extension = strtolower($file->getClientOriginalExtension());
if (!in_array($extension, $allowedExtensions)) {
return $this->json(['success' => false, 'message' => $this->translator->trans('Invalid file format. Please upload Excel file (.xlsx or .xls)')]);
}
// Parse Excel file
$locationData = $this->parseExcelFile($file);
if (empty($locationData)) {
return $this->json(['success' => false, 'message' => $this->translator->trans('No valid data found in the Excel file')]);
}
if (count($locationData) > 2500) {
return $this->json(['success' => false, 'message' => $this->translator->trans('Maximum 2500 locations allowed per upload')]);
}
// Get address_components for each location using Google Geocoding API
$invalidCoordinates = [];
foreach ($locationData as $index => &$location) {
try {
$geocodingUrl = sprintf(
'https://maps.googleapis.com/maps/api/geocode/json?key=%s&latlng=%s,%s&language=%s',
$_ENV['GOOGLE_API_KEY'],
$location['lat'],
$location['lng'],
$lang
);
$response = $this->httpClient->get($geocodingUrl);
$response = json_decode($response->getBody()->getContents(), true);
if (isset($response['status']) && $response['status'] === 'OK' && !empty($response['results'])) {
$location['address_components'] = $response['results'][0]['address_components'] ?? [];
// If name is not set, try to extract locality
if (empty($location['locationName'])) {
$location['locationName'] = $this->extractLocality($response);
}
} else {
// Mark as invalid coordinates
$invalidCoordinates[] = [
'row' => $index + 1,
'locationName' => $location['locationName'] ?? 'Unknown',
'lat' => $location['lat'],
'lng' => $location['lng']
];
$location['address_components'] = [];
}
} catch (\Exception $e) {
$location['address_components'] = [];
}
}
unset($location); // Break reference
// If there are invalid coordinates, return error with details
if (!empty($invalidCoordinates) && count($invalidCoordinates) === count($locationData)) {
return $this->json([
'success' => false,
'message' => $this->translator->trans('All coordinates are invalid'),
'invalid_coordinates' => $invalidCoordinates
]);
}
// Prepare params for bulk location creation
$params = ['data' => $locationData];
$result = $this->locationModel->createBulkLocations($request, $params, $user, $this->translator);
// Add invalid coordinates info to result if any
if (!empty($invalidCoordinates)) {
$result['invalid_coordinates'] = $invalidCoordinates;
}
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* Parse Excel file and extract location data
*/
private function parseExcelFile($file): array
{
$locationData = [];
try {
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file->getPathname());
$worksheet = $spreadsheet->getActiveSheet();
$rows = $worksheet->toArray();
if (empty($rows)) {
throw new \Exception('Excel file is empty');
}
// Find the header row (skip instruction rows)
$headerRowIndex = null;
$headers = null;
$normalizedHeaders = null;
// Possible header column names to detect
$possibleLocationNames = ['locationname', 'location', 'name', 'sitename', 'site', 'placename', 'place', 'title', 'label'];
$possibleLatNames = ['lat', 'latitude', 'lattitude', 'y'];
$possibleLngNames = ['lng', 'long', 'longitude', 'lon', 'x'];
// Search first 10 rows to find the header row
$maxSearchRows = min(10, count($rows));
for ($i = 0; $i < $maxSearchRows; $i++) {
$row = $rows[$i];
// Normalize this row's values
$normalized = array_map(function($h) {
$h = strtolower(trim($h ?? ''));
return preg_replace('/[\s_\-]+/', '', $h);
}, $row);
// Check if this row contains header-like columns
$hasLocationCol = false;
$hasLatCol = false;
$hasLngCol = false;
foreach ($normalized as $col) {
if (in_array($col, $possibleLocationNames)) $hasLocationCol = true;
if (in_array($col, $possibleLatNames)) $hasLatCol = true;
if (in_array($col, $possibleLngNames)) $hasLngCol = true;
}
// If this row has all required column headers, use it as the header row
if ($hasLocationCol && $hasLatCol && $hasLngCol) {
$headerRowIndex = $i;
$headers = $row;
$normalizedHeaders = $normalized;
break;
}
}
if ($headerRowIndex === null) {
throw new \Exception('Could not find header row with required columns (Location Name, Latitude, Longitude). Please ensure your Excel has these column headers.');
}
// Find column indexes with expanded possible names
$locationNameIndex = $this->findColumnIndex($normalizedHeaders, [
'locationname', 'location', 'name', 'sitename', 'site', 'placename', 'place',
'title', 'label', 'اسم', 'اسمالموقع', 'الموقع'
]);
$latIndex = $this->findColumnIndex($normalizedHeaders, [
'lat', 'latitude', 'lattitude', 'y', 'خطالعرض', 'عرض'
]);
$lngIndex = $this->findColumnIndex($normalizedHeaders, [
'lng', 'long', 'longitude', 'lon', 'x', 'خطالطول', 'طول'
]);
$tagIndex = $this->findColumnIndex($normalizedHeaders, [
'tag', 'tags', 'tagname', 'tagnames', 'locationtag', 'locationtags',
'category', 'categories', 'group', 'groups',
'تاج', 'علامة', 'فئة'
]);
$metaDataIndex = $this->findColumnIndex($normalizedHeaders, [
'metadata', 'meta', 'description', 'desc', 'notes', 'note', 'details', 'info',
'بيانات', 'وصف', 'ملاحظات'
]);
// Parse data rows (starting after the header row)
for ($i = $headerRowIndex + 1; $i < count($rows); $i++) {
$row = $rows[$i];
$locationName = trim($row[$locationNameIndex] ?? '');
$lat = $row[$latIndex] ?? null;
$lng = $row[$lngIndex] ?? null;
// Skip empty rows
if (empty($locationName) && ($lat === null || $lat === '') && ($lng === null || $lng === '')) {
continue;
}
// Validate that we have all required data
if (empty($locationName) || $lat === null || $lat === '' || $lng === null || $lng === '') {
continue; // Skip incomplete rows
}
$location = [
'locationName' => $locationName,
'lat' => is_numeric($lat) ? floatval($lat) : $lat,
'lng' => is_numeric($lng) ? floatval($lng) : $lng,
];
// Add tags if present
if ($tagIndex !== null && !empty($row[$tagIndex])) {
$tagValue = trim($row[$tagIndex]);
// Split by comma if multiple tags
$location['tagNames'] = array_map('trim', explode(',', $tagValue));
}
// Add metadata if present
if ($metaDataIndex !== null && !empty($row[$metaDataIndex])) {
$location['metaData'] = trim($row[$metaDataIndex]);
}
$locationData[] = $location;
}
} catch (\Exception $e) {
throw new \Exception('Error parsing Excel file: ' . $e->getMessage());
}
return $locationData;
}
/**
* Find column index by possible header names
*/
private function findColumnIndex(array $headers, array $possibleNames): ?int
{
foreach ($possibleNames as $name) {
$index = array_search($name, $headers);
if ($index !== false) {
return $index;
}
}
return null;
}
/**
* @Route("/api/public/list-location-tags", name="list_location_tags_wso", methods={"POST"})
*/
public function listLocationTags(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale($params['lang'] ?? DEFAULT_LOCALE);
$result = $this->locationModel->listTags($request, $user, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/create-tag", name="public-create-tag", methods={"POST"})
*/
public function createTags(Request $request): JsonResponse
{
try {
$response = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($response['success'] !== true) {
return $this->json($response);
}
$applicationName = $request->headers->get('X-App-Name');
$applicationConsumer = $request->headers->get('X-App-Consumer-Key');
if (!$applicationName || !$applicationConsumer) {
return $this->json(['success' => false,'message' => 'Missing required headers']);
}
$user = DataObject\Customer::getByEmail($applicationName, true);
if (!$user) {
return $this->json([
'success' => false,
'message' => 'Invalid User'
]);
}
$application = DataObject\WSO2Applications::getByUser($user, true);
if (!$application) {
return $this->json([
'success' => false,
'message' => 'User not found'
]);
}
// 5. Consumer key validation
if ($application->getConsumerKey() !== $applicationConsumer) {
return $this->json([
'success' => false,
'message' => 'Invalid Consumer Key'
]);
}
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
$requiredParameters = ['tag_name'];
foreach ($requiredParameters as $param) {
if (!isset($params[$param])) {
$missingParams[] = $param;
}
}
if (!empty($missingParams)) {
$parameterList = implode(", ", $missingParams);
return $this->json(['success' => false, 'message' => sprintf($this->translator->trans("missing_required_parameters: %s"), $parameterList)]);
}
$result = $this->locationModel->createTags($request, $params, $user, $this->translator);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $this->translator->trans(USER_ERROR_MESSAGE)]);
}
}
/**
* @Route("/api/public/list-reports", name="public-reports-listing")
*/
public function getReportsListAction(Request $request, PaginatorInterface $paginator)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$params = json_decode($request->getContent(), true);
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['page']) || !isset($params['limit'])) {
throw new \Exception('Missing required params: page or limit');
}
$report_type = isset($params['report_type']) ? $params['report_type'] : null;
$lang = isset($params['lang']) ? $params['lang'] : DEFAULT_LOCALE;
$isPublicReports = isset($params['publicReports']) ? $params['publicReports'] : false; // sending this flag from public portal to get all reports accordong to our needs
$page = $params['page'];
$limit = $params['limit'];
$result = $this->reportingPortalModel->getListReport($params);
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/report/{url}", name="public-report-url")
*/
public function getReportByUrlAction(Request $request, PaginatorInterface $paginator)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
$user = $permissions['user'];
$url = $request->get('url');
$reportTypes = [
"red-sea-report",
"arabian-gulf-report",
"10-day-forecast-report",
"mashaer-weather-report",
"custom-weather-report",
"advance-custom-weather-report"
];
$params = json_decode($request->getContent(), true);
if (!in_array($url, $reportTypes)) {
return $this->json(['success' => false, 'message' => 'Invalid report type']);
}else{
$params['report_type'] =[
$url
];
}
$this->translator->setlocale(isset($params["lang"]) ? $params["lang"] : DEFAULT_LOCALE);
if (!isset($params['page']) || !isset($params['limit'])) {
throw new \Exception('Missing required params: page or limit');
}
// For red-sea-report, arabian-gulf-report, 10-day-forecast-report, mashaer-weather-report, custom-weather-report and advance-custom-weather-report: filter by id (query or body) so only nested report items with this id are shown
$filterId = null;
if (in_array($url, ['red-sea-report', 'arabian-gulf-report', '10-day-forecast-report', 'mashaer-weather-report', 'custom-weather-report', 'advance-custom-weather-report'], true)) {
$filterId = $request->query->get('id');
if (null === $filterId && isset($params['id'])) {
$filterId = $params['id'];
}
}
$result = $this->reportingPortalModel->getListReport($params);
if (in_array($url, ['red-sea-report', 'arabian-gulf-report', '10-day-forecast-report', 'mashaer-weather-report', 'custom-weather-report', 'advance-custom-weather-report'], true) && $filterId !== null) {
$filteredData = [];
if (isset($result['data']) && is_array($result['data'])) {
foreach ($result['data'] as $mainDataItem) {
if (isset($mainDataItem['report']) && is_array($mainDataItem['report'])) {
$filteredReports = array_filter($mainDataItem['report'], function ($reportItem) use ($filterId) {
return isset($reportItem['id']) && (string) $reportItem['id'] === (string) $filterId;
});
$mainDataItem['report'] = array_values($filteredReports);
}
if (!empty($mainDataItem['report'])) {
$filteredData[] = $mainDataItem;
}
}
}
$result['data'] = $filteredData;
}
return $this->json($result);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @param list<array<string, mixed>> $jsonData
* @param list<mixed> $filterByNames
* @return list<array<string, mixed>>
*/
private function filterJsonDataByNames(array $jsonData, array $filterByNames): array
{
$needles = [];
foreach ($filterByNames as $name) {
if (!is_string($name) && !is_numeric($name)) {
continue;
}
$trimmed = trim((string) $name);
if ($trimmed !== '') {
$needles[] = mb_strtolower($trimmed);
}
}
if ($needles === []) {
return $jsonData;
}
$filteredJsonData = [];
foreach ($jsonData as $cityData) {
if (!is_array($cityData)) {
continue;
}
$haystacks = [
$cityData['cityEn'] ?? '',
$cityData['cityAr'] ?? '',
$cityData['governorateEn'] ?? '',
$cityData['governorateAr'] ?? '',
];
$matched = false;
foreach ($needles as $needle) {
foreach ($haystacks as $haystack) {
$haystackLower = mb_strtolower((string) $haystack);
if ($haystackLower !== '' && mb_strpos($haystackLower, $needle) !== false) {
$matched = true;
break 2;
}
}
}
if ($matched) {
$filteredJsonData[] = $cityData;
}
}
return $filteredJsonData;
}
/**
* @param string ...$keys Request parameter keys to check (first match wins)
*/
private function parseRequestBoolParam(array $params, bool $default, string ...$keys): bool
{
foreach ($keys as $key) {
if (!array_key_exists($key, $params)) {
continue;
}
$value = $params[$key];
if (is_bool($value)) {
return $value;
}
if (is_int($value) || is_float($value)) {
return (int) $value === 1;
}
if (is_string($value)) {
$normalized = strtolower(trim($value));
if (in_array($normalized, ['1', 'true', 'yes', 'on'], true)) {
return true;
}
if (in_array($normalized, ['0', 'false', 'no', 'off'], true)) {
return false;
}
}
}
return $default;
}
/**
* @Route("/api/public/get-marine-report", name="get-marine-report")
*/
public function getPortWeatherListAction(Request $request, PaginatorInterface $paginator)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
return $this->json($this->marineReportModel->getMarineReport());
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/ncm/marine/get-marine-report", name="get-marine-report-user")
*/
public function getPortWeatherListUserAction(Request $request)
{
try {
return $this->json($this->marineReportModel->getMarineReport());
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/public/get-marine-description", name="get-marine-description")
*/
public function getMarineDescriptionAction(Request $request)
{
try {
$permissions = $this->publicUserPermissionService->isAuthorized($request, $this->translator);
if ($permissions['success'] !== true) {
return $this->json($permissions);
}
return $this->json($this->marineReportModel->getMarineDescription($this->marineTranslator));
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* @Route("/api/ncm/marine/get-marine-description", name="get-marine-description-user")
*/
public function getMarineDescriptionUserAction(Request $request)
{
try {
return $this->json($this->marineReportModel->getMarineDescription($this->marineTranslator));
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
/**
* Combined marine report + description. Fully public: no API-key and no
* user token (the /api/public path is PUBLIC_ACCESS and no isAuthorized()
* check is performed).
*
* @Route("/api/public/get-marine-forecast", name="get-marine-forecast")
*/
public function getMarineForecastAction(Request $request)
{
try {
return $this->json([
'success' => true,
'data' => $this->marineReportModel->getMarineForecast($this->marineTranslator),
]);
} catch (\Exception $ex) {
$this->logger->error($ex->getMessage());
return $this->json(['success' => false, 'message' => $ex->getMessage()]);
}
}
}