<?php
namespace App\Model;
use Symfony\Component\Security\Core\User\UserInterface;
use Pimcore\Model\DataObject\CustomNotification;
use Pimcore\Model\DataObject\EwsNotification;
use Symfony\Component\HttpFoundation\Request;
use App\Service\MeteomaticsWeatherService;
use Pimcore\Model\DataObject\Dashboard;
use Pimcore\Model\DataObject\Customer;
use Pimcore\Model\DataObject\Location;
use Pimcore\Model\DataObject;
use App\Model\LocationModel;
use GuzzleHttp\Client;
use DateTimeZone;
use Pimcore\Db;
use DateTime;
class CalendarModel
{
private $apiBaseUrl = MATEOMATICS_API_URL;
private $username = MATEOMATICS_API_USERNAME;
private $password = MATEOMATICS_API_PASSWORD;
// public function getCalendarNotification(MeteomaticsWeatherService $mateoMaticsService, $user, $customNotificationIds, $startDate, $endDate, $hour, $page, $size, $title, $paginator, $translator): array
// {
// $pageSize = isset($size) ? $size : LIMIT_PER_PAGE;
// $page = isset($page) ? $page : 1;
// $qualifiedLocations = [];
// $locationModel = new LocationModel();
// $ewsNotificationModel = new EwsNotificationModel();
// $options = [];
// $calculateOption = [];
// $customNotificationListing = new DataObject\CustomNotification\Listing();
// foreach ($customNotificationListing->getClass()->getFieldDefinitions() as $fieldDefionition) {
// if ($fieldDefionition->getName() == "calculate") {
// $options = $fieldDefionition->getOptions();
// }
// }
// if ($options) {
// foreach ($options as $optionKey => $option) {
// $calculateOption[$option['value']] = $option['key'];
// }
// }
// $customNotification = new DataObject\CustomNotification\Listing();
// $customNotification->addConditionParam('o_id IN (' . $customNotificationIds . ')');
// $customNotification->filterByUser($user);
// //$customNotification->setLimit(10);
// $customNotification->setOrderKey("o_id");
// $customNotification->setOrder("desc");
// if (!empty($title)) {
// $customNotification->addConditionParam("title like '%$title%' ");
// }
// $paginator = $paginator->paginate(
// $customNotification,
// $page,
// $pageSize
// );
// $customNotifications = $paginator->count();
// if (!$customNotifications) {
// // throw new \Exception("You do not have any notification configured for this location");
// return ['success' => false, 'message' => $translator->trans("you_do_not_have_any_notification_configured_for_this_location")];
// }
// $resultArr = [];
// $resultArr1 = [];
// foreach ($paginator as $customNotification) {
// $user = $customNotification->getUser();
// $location = $customNotification->getLocation();
// if ($location instanceof DataObject\Location) {
// $coOrdinates = json_decode($location->getCoOrdinates(), true);
// if ($coOrdinates && count($coOrdinates)) {
// if (!$customNotification->getAlert()) {
// continue;
// }
// $parameter = $customNotification->getAlert()->getMeteoMaticsKey();
// $alertName = $customNotification->getAlert()->getName("en");
// $alertNameAr = $customNotification->getAlert()->getName("ar");
// if (!empty($customNotification->getWeatherModel())) {
// $model = $customNotification->getWeatherModel();
// } else {
// $model = "mix";
// }
// $startDate = date('Y-m-d\T00:00:00.v\Z', strtotime($startDate));
// $endDate = date('Y-m-d\T23:59:59.v\Z', strtotime($endDate));
// p_r($startDate);
// p_r($endDate);
// $response = $mateoMaticsService->getTempratureByParamsHourly($coOrdinates, $startDate, $endDate, $parameter, $hour, $model);
// $qualifiedLocations = $response['data'][0]['coordinates'][0]['dates'];
// if (is_array($response) && isset($response['data'][0]['parameter']) && $response['data'][0]['parameter'] = $parameter) {
// foreach ($qualifiedLocations as $key => $qualifiedLocation) {
// if ($customNotification->getCalculate() == "range") {
// $value2 = [];
// $value2[0] = $customNotification->getMinValue();
// $value2[1] = $customNotification->getMaxValue();
// } else {
// $value2 = $customNotification->getMaxValue();
// }
// $value = $qualifiedLocation['value'];
// $resultArr[$qualifiedLocation["date"]][$alertName] = $qualifiedLocation;
// if (\App\Lib\Utility::compareValues($customNotification->getCalculate(), $value, $value2)) {
// $resultArr1[] = [
// 'custom_notification_id' => $customNotification->getId(),
// 'custom_notification_id' => $customNotification->getId(),
// "custom_notification_color" => $customNotification->getColor(),
// "date" => $qualifiedLocation['date'],
// "location_name" => $location->getName(),
// "location_title" => $location->getTitle(),
// "custom_notification_title" => $customNotification->getTitle(),
// "location_id" => $location->getId(),
// "parameter" => $parameter,
// "name" => $alertName,
// "nameAr" => $alertNameAr,
// "calculation_type" => $customNotification->getCalculate(),
// "calculation_type_label" => isset($calculateOption[$customNotification->getCalculate()]) ? $calculateOption[$customNotification->getCalculate()] : "",
// "user_value" => $value2,
// 'received_value' => $value,
// "matched" => true
// ];
// } else {
// $resultArr1[] = [
// 'custom_notification_id' => $customNotification->getId(),
// "custom_notification_color" => $customNotification->getColor(),
// "date" => $qualifiedLocation['date'],
// "location_name" => $location->getName(),
// "location_title" => $location->getTitle(),
// "custom_notification_title" => $customNotification->getTitle(),
// "location_id" => $location->getId(),
// "parameter" => $parameter,
// "name" => $alertName,
// "nameAr" => $alertNameAr,
// "calculation_type" => $customNotification->getCalculate(),
// "calculation_type_label" => isset($calculateOption[$customNotification->getCalculate()]) ? $calculateOption[$customNotification->getCalculate()] : "",
// "user_value" => $value2,
// 'received_value' => $value,
// "matched" => false
// ];
// }
// }
// }
// }
// }
// }
// $rawArr = array_values($resultArr1);
// $organizedData = [];
// $matchedAlert = [];
// $timezone = new \DateTimeZone("Asia/Riyadh");
// foreach ($rawArr as $entry) {
// $notification = $entry;
// // Parse the date with DateTime and adjust timezone
// $notificationDate = new \DateTime($notification['date'], new \DateTimeZone("UTC"));
// $notificationDate->modify('-6 hours');
// $notificationDate->setTimezone($timezone);
// // Format date components for use in organizedData
// $notification['date'] = $notificationDate->format("Y-m-d\TH:00:00\Z");
// $notificationId = $notification['custom_notification_id'];
// $date = $notificationDate->format("Y-m-d");
// $time = $notificationDate->format("H:i");
// $day = $notificationDate->format("D");
// if (!isset($matchedAlert[$date . $notificationId]) || $notification['matched'] == true) {
// $matchedAlert[$date . $notificationId] = $notification['matched'];
// }
// // Initialize the main array element for this notification ID if not already done
// if (!isset($organizedData[$notificationId])) {
// $organizedData[$notificationId] = [
// "custom_notification_title" => $notification['custom_notification_title'],
// "location_title" => $notification['location_title'],
// "alerts" => [],
// "user_value" => $notification['user_value'], // Static value, change as needed
// "calculation_type" => $notification['calculation_type'],
// "calculation_type_label" => $notification['calculation_type_label'],
// "parameterName" => $notification['parameter'],
// "parameterTitleEn" => $notification['name'],
// "parameterTitleAr" => $notification['nameAr'],
// ];
// }
// // Initialize the date array element if not already done
// if (!isset($organizedData[$notificationId]['alerts'][$date])) {
// $organizedData[$notificationId]['alerts'][$date] = [
// 'date' => $date,
// 'day' => $day,
// 'rawDate' => $notification['date'],
// 'data' => []
// ];
// }
// $organizedData[$notificationId]['alerts'][$date]["isAlertPresent"] = $matchedAlert[$date . $notificationId];
// // Append time data to the corresponding date
// $organizedData[$notificationId]['alerts'][$date]['data'][] = [
// 'fromInterval' => $notification['date'],
// 'toInterval' => $notification['date'],
// 'data' => $notification
// ];
// }
// return ["success" => true, "data" => array_values($organizedData), "paginationVariables" => $paginator->getPaginationData()];
// }
public function getCalendarNotification(MeteomaticsWeatherService $mateoMaticsService, $user, $customNotificationIds, $startDate, $endDate, $hour, $page, $size, $title, $paginator, $translator, $tagIds = '', $location = '', $locationTagName): array
{
// Set timezone to Asia/Riyadh
$timezone = new \DateTimeZone("Asia/Riyadh");
// Convert start and end dates to Asia/Riyadh timezone
$startDateObj = new \DateTime($startDate, $timezone);
$endDateObj = new \DateTime($endDate, $timezone);
$pageSize = isset($size) ? $size : LIMIT_PER_PAGE;
$page = isset($page) ? $page : 1;
$qualifiedLocations = [];
$locationModel = new LocationModel();
$ewsNotificationModel = new EwsNotificationModel();
$options = [];
$calculateOption = [];
$customNotificationListing = new DataObject\CustomNotification\Listing();
foreach ($customNotificationListing->getClass()->getFieldDefinitions() as $fieldDefionition) {
if ($fieldDefionition->getName() == "calculate") {
$options = $fieldDefionition->getOptions();
}
}
if ($options) {
foreach ($options as $optionKey => $option) {
$calculateOption[$option['value']] = $option['key'];
}
}
// Check if $customNotificationIds is empty and return a message if so
if (empty($customNotificationIds)) {
return ['success' => false, 'message' => $translator->trans("you_do_not_have_any_notification_configured")];
}
$customNotification = new DataObject\CustomNotification\Listing();
$customNotification->addConditionParam('o_id IN (' . $customNotificationIds . ')');
$customNotification->filterByUser($user);
$customNotification->setOrderKey("o_id");
$customNotification->setOrder("desc");
if (!empty($title)) {
$customNotification->addConditionParam("title like '%$title%' ");
}
if (!empty($tagIds)) {
$customNotification->addConditionParam('tag__id IN (' . $tagIds . ')');
}
// filter for location title
if (!empty($location)) {
$db = \Pimcore\Db::get();
$locationIds = $db->fetchFirstColumn(
"SELECT l.oo_id FROM object_query_location AS l WHERE l.title LIKE :location;",
[
'location' => '%' . $location . '%',
]
);
if (!empty($locationIds)) {
// Combine conditions with OR
$conditions = [];
if (!empty($locationIds)) {
$conditions[] = 'location__id IN (' . implode(",", $locationIds) . ')';
}
if (!empty($tagIds)) {
$conditions[] = 'tag__id IN (' . implode(",", $tagIds) . ')';
}
$customNotification->addConditionParam(implode(" OR ", $conditions));
} else {
return ['success' => false, 'message' => $translator->trans("you_do_not_have_any_notification_configured_for_this_location")];
}
}
// filter for location name
if (!empty($locationTagName)) {
$db = \Pimcore\Db::get();
$tagIds = $db->fetchFirstColumn(
"SELECT ooo_id
FROM object_localized_data_Tags
WHERE language = :language AND TagName LIKE :tagName",
[
'language' => $translator->getLocale(),
'tagName' => '%' . $location . '%'
]
);
if (!empty($tagIds)) {
// Combine conditions with OR
$conditions = [];
if (!empty($locationIds)) {
$conditions[] = 'location__id IN (' . implode(",", $locationIds) . ')';
}
if (!empty($tagIds)) {
$conditions[] = 'tag__id IN (' . implode(",", $tagIds) . ')';
}
$customNotification->addConditionParam(implode(" OR ", $conditions));
} else {
return ['success' => false, 'message' => $translator->trans("you_do_not_have_any_notification_configured_for_this_location")];
}
}
$paginator = $paginator->paginate(
$customNotification,
$page,
$pageSize
);
$customNotifications = $paginator->count();
if (!$customNotifications) {
return ['success' => false, 'message' => $translator->trans("you_do_not_have_any_notification_configured_for_this_location")];
}
$resultArr = [];
$resultArr1 = [];
$comparableStartDate = $startDateObj;
$comparableEndDate = $endDateObj;
$startDateFormatted = $startDateObj->format('Y-m-d\T00:00:00.v\Z');
$endDateObj->modify("+3 hours");
$endDateFormatted = $endDateObj->format('Y-m-d\T00:00:00.v\Z');
foreach ($paginator as $customNotification) {
$user = $customNotification->getUser();
$location = $customNotification->getLocation();
if ($location instanceof DataObject\Location) {
$coOrdinates = json_decode($location->getCoOrdinates(), true);
if ($coOrdinates && count($coOrdinates)) {
if (!$customNotification->getAlert()) {
continue;
}
$parameter = $customNotification->getAlert()->getMeteoMaticsKey();
$alertName = $customNotification->getAlert()->getName("en");
$alertNameAr = $customNotification->getAlert()->getName("ar");
$model = !empty($customNotification->getWeatherModel()) ? $customNotification->getWeatherModel() : "mix";
// Format dates for Meteomatics request with Asia/Riyadh timezone
/*$startDateFormatted = $startDateObj->format('Y-m-d\T00:00:00.v\Z');
$endDateObj->modify("+3 hours");
$endDateFormatted = $endDateObj->format('Y-m-d\T00:00:00.v\Z');*/
$response = $mateoMaticsService->getTempratureByParamsHourly($coOrdinates, $startDateFormatted, $endDateFormatted, $parameter, $hour, $model, $timezone);
$qualifiedLocations = $response['data'][0]['coordinates'][0]['dates'];
if (is_array($response) && isset($response['data'][0]['parameter']) && $response['data'][0]['parameter'] == $parameter) {
foreach ($qualifiedLocations as $key => $qualifiedLocation) {
$qualifiedDate = new \DateTime($qualifiedLocation["date"], $timezone);
// Check if the qualified date falls within the start and end dates
// var_dump("Qualified-Data : ". $qualifiedDate->format("Y-m-d")." --- ".$comparableEndDate->format("Y-m-d"));
if ($qualifiedDate < $comparableStartDate || $qualifiedDate > $comparableEndDate) {
continue; // Skip if date is out of the specified range
}
if ($customNotification->getCalculate() == "range") {
$value2 = [];
$value2[0] = $customNotification->getMinValue();
$value2[1] = $customNotification->getMaxValue();
} else {
$value2 = $customNotification->getMaxValue();
}
$value = $qualifiedLocation['value'];
$resultArr[$qualifiedLocation["date"]][$alertName] = $qualifiedLocation;
if (\App\Lib\Utility::compareValues($customNotification->getCalculate(), $value, $value2)) {
$resultArr1[] = [
'custom_notification_id' => $customNotification->getId(),
"custom_notification_color" => $customNotification->getColor(),
'model' => $customNotification->getWeatherModel(),
'unit' => $customNotification->getUnits(),
'unit_en' => $customNotification->getAlert()?->getUnitTitle(),
'unit_ar' => (\App\Lib\Utility::getArabicTranslationUnits($customNotification->getAlert()?->getUnitTitle())),
"date" => $qualifiedLocation['date'],
"location_name" => $location->getName(),
"location_title" => $location->getTitle(),
"custom_notification_title" => $customNotification->getTitle(),
"location_id" => $location->getId(),
"parameter" => $parameter,
"name" => $alertName,
"nameAr" => $alertNameAr,
"calculation_type" => $customNotification->getCalculate(),
'calculculation_type_ar' => (\App\Lib\Utility::getArabicTranslation($customNotification->getCalculate(), CUSTOM_NOTIFICATION_CONDITION) ? \App\Lib\Utility::getArabicTranslation($customNotification->getCalculate(), CUSTOM_NOTIFICATION_CONDITION) : ''),
"calculation_type_label" => isset($calculateOption[$customNotification->getCalculate()]) ? $calculateOption[$customNotification->getCalculate()] : "",
"calculation_type_label" => $calculateOption[$customNotification->getCalculate()] ?? "",
"user_value" => $value2,
'received_value' => $value,
"matched" => true
];
} else {
$resultArr1[] = [
'custom_notification_id' => $customNotification->getId(),
"custom_notification_color" => $customNotification->getColor(),
'model' => $customNotification->getWeatherModel(),
'unit' => $customNotification->getUnits(),
'unit_en' => $customNotification->getAlert()?->getUnitTitle(),
'unit_ar' => (\App\Lib\Utility::getArabicTranslationUnits($customNotification->getAlert()?->getUnitTitle())),
"date" => $qualifiedLocation['date'],
"location_name" => $location->getName(),
"location_title" => $location->getTitle(),
"custom_notification_title" => $customNotification->getTitle(),
"location_id" => $location->getId(),
"parameter" => $parameter,
"name" => $alertName,
"nameAr" => $alertNameAr,
"calculation_type" => $customNotification->getCalculate(),
'calculculation_type_ar' => (\App\Lib\Utility::getArabicTranslation($customNotification->getCalculate(), CUSTOM_NOTIFICATION_CONDITION) ? \App\Lib\Utility::getArabicTranslation($customNotification->getCalculate(), CUSTOM_NOTIFICATION_CONDITION) : ''),
"calculation_type_label" => isset($calculateOption[$customNotification->getCalculate()]) ? $calculateOption[$customNotification->getCalculate()] : "",
"calculation_type_label" => $calculateOption[$customNotification->getCalculate()] ?? "",
"user_value" => $value2,
'received_value' => $value,
"matched" => false
];
}
}
}
}
}
}
$rawArr = array_values($resultArr1);
$organizedData = [];
$matchedAlert = [];
$timezone = new \DateTimeZone("Asia/Riyadh");
foreach ($rawArr as $entry) {
$notification = $entry;
// Parse the date with DateTime and adjust timezone
$notificationDate = new \DateTime($notification['date'], $timezone);
$notification['date'] = $notificationDate->format("Y-m-d\TH:00:00\Z");
$notificationId = $notification['custom_notification_id'];
$date = $notificationDate->format("Y-m-d");
$time = $notificationDate->format("H:i");
$day = $notificationDate->format("D");
if (!isset($matchedAlert[$date . $notificationId]) || $notification['matched'] == true) {
$matchedAlert[$date . $notificationId] = $notification['matched'];
}
// Initialize the main array element for this notification ID if not already done
if (!isset($organizedData[$notificationId])) {
$organizedData[$notificationId] = [
"custom_notification_title" => $notification['custom_notification_title'],
"location_title" => $notification['location_title'],
"tag_name" => $customNotification->getTag() ? $customNotification->getTag()->getTagName() : "",
"alerts" => [],
"user_value" => $notification['user_value'], // Static value, change as needed
"calculation_type" => $notification['calculation_type'],
'calculculation_type_ar' => (\App\Lib\Utility::getArabicTranslation($customNotification->getCalculate(), CUSTOM_NOTIFICATION_CONDITION) ? \App\Lib\Utility::getArabicTranslation($customNotification->getCalculate(), CUSTOM_NOTIFICATION_CONDITION) : ''),
"calculation_type_label" => $notification['calculation_type_label'],
"parameterName" => $notification['parameter'],
"parameterTitleEn" => $notification['name'],
"parameterTitleAr" => $notification['nameAr'],
'unit' => $notification['unit'],
'unit_en' => $notification['unit_en'],
'unit_ar' => $notification['unit_ar'],
];
}
// Initialize the date array element if not already done
if (!isset($organizedData[$notificationId]['alerts'][$date])) {
$organizedData[$notificationId]['alerts'][$date] = [
'date' => $date,
'day' => $day,
'rawDate' => $notification['date'],
'data' => []
];
}
$organizedData[$notificationId]['alerts'][$date]["isAlertPresent"] = $matchedAlert[$date . $notificationId];
// Append time data to the corresponding date
$organizedData[$notificationId]['alerts'][$date]['data'][] = [
'fromInterval' => $notification['date'],
'toInterval' => $notification['date'],
'data' => $notification
];
}
return ["success" => true, "data" => array_values($organizedData), "paginationVariables" => $paginator->getPaginationData()];
}
// public function getAdvanceCalendarNotification(MeteomaticsWeatherService $mateoMaticsService, $user, $advanceCustomNotificationIds, $startDate, $endDate, $hour, $page, $size, $title, $paginator, $translator): array
// {
// $qualifiedLocations = [];
// $advanceCustomNotifications = new DataObject\AdvanceCustomNotification\Listing();
// $advanceCustomNotifications->addConditionParam('o_id IN (' . $advanceCustomNotificationIds . ')');
// $advanceCustomNotifications->addConditionParam('owner__id = ? OR user LIKE ? ', [$user->getId(), '%,' . $user->getId() . ',%']);
// $advanceCustomNotifications->setOrderKey("o_id");
// $advanceCustomNotifications->setOrder("desc");
// if (!empty($title)) {
// $advanceCustomNotifications->addConditionParam("notificationName like '%$title%' ");
// }
// $totalAdvanceCustomNotifications = $advanceCustomNotifications->count();
// if (!$totalAdvanceCustomNotifications) {
// // throw new \Exception("You do not have any notification configured for this location");
// return ['success' => false, 'message' => $translator->trans("you_do_not_have_any_advance_custom_notification_configured")];
// }
// $resultArr = [];
// $resultArr1 = [];
// foreach ($advanceCustomNotifications as $advanceCustomNotification) {
// $finalResult = false;
// $data = [];
// $groupData = [];
// $rules = $advanceCustomNotification->getNotificationConfig();
// $groupConditions = [];
// $ruleCondition = [];
// $ruleValues = [];
// $groupRuleCondition = [];
// $groupRuleValues = [];
// $groupValues = [];
// $sequence = [];
// if ($rules) {
// foreach ($rules as $ruleConfig) {
// if ($ruleConfig->getRuleType() == 'rule') {
// if ($ruleConfig->getRulecondition() != null) {
// $ruleCondition[] = $ruleConfig->getRulecondition();
// }
// try {
// $result = $this->getMeteomaticData($ruleConfig, $startDate, $endDate);
// if (!empty($result)) {
// $data[] = $result;
// $ruleValues[] = true;
// $sequence[] = [
// 'name' => $ruleConfig->getName(),
// 'condition' => $ruleConfig->getRuleCondition(),
// 'type' => 'rule',
// 'value' => true
// ];
// } else {
// $ruleValues[] = false;
// $sequence[] = [
// 'name' => $ruleConfig->getName(),
// 'condition' => $ruleConfig->getRuleCondition(),
// 'type' => 'rule',
// 'value' => false
// ];
// }
// $alertName = $result['alertName'];
// $qualifiedLocations = $result['data']['data'][0]['coordinates'][0]['dates'];
// if (is_array($result) && isset($result['data']['data'][0]['parameter']) && $result['data']['data'][0]['parameter'] = $result['parameterKey']) {
// foreach ($qualifiedLocations as $key => $qualifiedLocation) {
// if ($ruleConfig->getCondition() == "range") {
// $value2 = [];
// $value2[0] = $ruleConfig->getConditionValueMin();
// $value2[1] = $ruleConfig->getConditionValueMax();
// } else {
// $value2 = $ruleConfig->getConditionValueMin();
// }
// $value = $qualifiedLocation['value'];
// $resultArr[$qualifiedLocation["date"]][$alertName] = $qualifiedLocation;
// if ($result['comparedValue']) {
// $resultArr1[] = [
// "type" => "rule",
// 'name' => $ruleConfig->getName(),
// 'rule_condition' => $ruleConfig->getRuleCondition(),
// 'advance_custom_notification_id' => $advanceCustomNotification->getId(),
// "date" => $qualifiedLocation['date'],
// "location_id" => $ruleConfig->getLocation()?->getId(),
// "location_name" => $ruleConfig->getLocation()?->getName(),
// "location_title" => $ruleConfig->getLocation()?->getTitle(),
// "advance_custom_notification_title" => $advanceCustomNotification->getNotificationName("en"),
// "parameter" => $ruleConfig->getParameter()->getParamName("en"),
// "calculation_type" => $ruleConfig->getCondition(),
// "calculation_type_label" => isset($calculateOption[$ruleConfig->getCondition()]) ? $calculateOption[$ruleConfig->getCondition()] : "",
// "user_value" => $value2,
// 'received_value' => $value,
// "matched" => true
// ];
// } else {
// $resultArr1[] = [
// "type" => "rule",
// 'name' => $ruleConfig->getName(),
// 'rule_condition' => $ruleConfig->getRuleCondition(),
// 'advance_custom_notification_id' => $advanceCustomNotification->getId(),
// "date" => $qualifiedLocation['date'],
// "location_id" => $ruleConfig->getLocation()->getId(),
// "location_name" => $ruleConfig->getLocation()?->getName(),
// "location_title" => $ruleConfig->getLocation()?->getTitle(),
// "advance_custom_notification_title" => $advanceCustomNotification->getNotificationName("en"),
// "parameter" => $ruleConfig->getParameter()->getParamName("en"),
// "calculation_type" => $ruleConfig->getCondition(),
// "calculation_type_label" => isset($calculateOption[$ruleConfig->getCondition()]) ? $calculateOption[$ruleConfig->getCondition()] : "",
// "user_value" => $value2,
// 'received_value' => $value,
// "matched" => false
// ];
// }
// }
// }
// if (!empty($result)) {
// $data[] = $result;
// $ruleValues[] = true;
// $sequence[] = [
// 'name' => $ruleConfig->getName(),
// 'condition' => $ruleConfig->getRuleCondition(),
// 'type' => 'rule',
// 'value' => true
// ];
// } else {
// $ruleValues[] = false;
// $sequence[] = [
// 'name' => $ruleConfig->getName(),
// 'condition' => $ruleConfig->getRuleCondition(),
// 'type' => 'rule',
// 'value' => false
// ];
// }
// } catch (\Exception $e) {
// $msg = $e->getMessage();
// // $output->write("<fg=red>$msg</>");
// continue;
// // return Command::FAILURE;
// }
// } else {
// if ($ruleConfig->getRulecondition() != null) {
// $groupRuleCondition[$ruleConfig->getName()][] = $ruleConfig->getRulecondition();
// }
// $groupConditions[$ruleConfig->getName()] = $ruleConfig->getGroupcondition();
// try {
// $result = $this->getMeteomaticData($ruleConfig, $startDate, $endDate);
// if (!empty($result)) {
// $groupData[$ruleConfig->getName()][] = $result;
// $groupRuleValues[$ruleConfig->getName()][] = true;
// } else {
// $groupRuleValues[$ruleConfig->getName()][] = false;
// }
// $alertName = $result['alertName'];
// $qualifiedLocations = $result['data']['data'][0]['coordinates'][0]['dates'];
// if (is_array($result) && isset($result['data']['data'][0]['parameter']) && $result['data']['data'][0]['parameter'] = $result['parameterKey']) {
// foreach ($qualifiedLocations as $key => $qualifiedLocation) {
// if ($ruleConfig->getCondition() == "range") {
// $value2 = [];
// $value2[0] = $ruleConfig->getConditionValueMin();
// $value2[1] = $ruleConfig->getConditionValueMax();
// } else {
// $value2 = $ruleConfig->getConditionValueMin();
// }
// $value = $qualifiedLocation['value'];
// $resultArr[$qualifiedLocation["date"]][$alertName] = $qualifiedLocation;
// if ($result['comparedValue']) {
// $resultArr1[] = [
// "type" => "Group",
// 'name' => $ruleConfig->getName(),
// 'rule_condition' => $ruleConfig->getRuleCondition(),
// 'group_condition' => $ruleConfig->getGroupCondition(),
// 'advance_custom_notification_id' => $advanceCustomNotification->getId(),
// "date" => $qualifiedLocation['date'],
// "location_id" => $ruleConfig->getLocation()?->getId(),
// "location_name" => $ruleConfig->getLocation()?->getName(),
// "location_title" => $ruleConfig->getLocation()?->getTitle(),
// "advance_custom_notification_title" => $advanceCustomNotification->getNotificationName("en"),
// "parameter" => $ruleConfig->getParameter()->getParamName("en"),
// "calculation_type" => $ruleConfig->getCondition(),
// "calculation_type_label" => isset($calculateOption[$ruleConfig->getCondition()]) ? $calculateOption[$ruleConfig->getCondition()] : "",
// "user_value" => $value2,
// 'received_value' => $value,
// "matched" => true
// ];
// } else {
// $resultArr1[] = [
// "type" => "Group",
// 'name' => $ruleConfig->getName(),
// 'rule_condition' => $ruleConfig->getRuleCondition(),
// 'group_condition' => $ruleConfig->getGroupCondition(),
// 'advance_custom_notification_id' => $advanceCustomNotification->getId(),
// "date" => $qualifiedLocation['date'],
// "location_id" => $ruleConfig->getLocation()->getId(),
// "location_name" => $ruleConfig->getLocation()?->getName(),
// "location_title" => $ruleConfig->getLocation()?->getTitle(),
// "advance_custom_notification_title" => $advanceCustomNotification->getNotificationName("en"),
// "parameter" => $ruleConfig->getParameter()->getParamName("en"),
// "calculation_type" => $ruleConfig->getCondition(),
// "calculation_type_label" => isset($calculateOption[$ruleConfig->getCondition()]) ? $calculateOption[$ruleConfig->getCondition()] : "",
// "user_value" => $value2,
// 'received_value' => $value,
// "matched" => false
// ];
// }
// }
// }
// if (!empty($result)) {
// $data[] = $result;
// $ruleValues[] = true;
// $sequence[] = [
// 'name' => $ruleConfig->getName(),
// 'condition' => $ruleConfig->getRuleCondition(),
// 'type' => 'rule',
// 'value' => true
// ];
// } else {
// $ruleValues[] = false;
// $sequence[] = [
// 'name' => $ruleConfig->getName(),
// 'condition' => $ruleConfig->getRuleCondition(),
// 'type' => 'rule',
// 'value' => false
// ];
// }
// } catch (\Exception $e) {
// $msg = $e->getMessage();
// // $output->write("<fg=red>$msg</>");
// continue;
// // return Command::FAILURE;
// }
// }
// }
// }
// if ($groupRuleValues) {
// foreach ($groupRuleValues as $group => $values) {
// if (isset($groupRuleCondition[$group])) {
// $result = \App\Lib\Utility::evaluateConditions($values, $groupRuleCondition[$group]);
// $groupValues[$group] = $result;
// $sequence[] = [
// 'name' => $group,
// 'condition' => $groupConditions[$group],
// 'type' => 'group',
// 'value' => $groupValues[$group]
// ];
// if ($result) {
// $data = array_merge($data, array_values($groupData[$group]));
// }
// } else {
// $groupValues[$group] = $values[0];
// $sequence[] = [
// 'name' => $group,
// 'condition' => $groupConditions[$group],
// 'type' => 'group',
// 'value' => $values[0]
// ];
// if ($values[0]) {
// foreach (array_values($groupData[$group]) as $dataArray) {
// foreach ($dataArray as $dateKey => $value) {
// array_push($data, [$dateKey => $value]);
// }
// }
// }
// }
// }
// }
// $result = !empty($sequence) ? $sequence[0]['value'] : null;
// if (count($sequence) > 1) {
// // Start from the second element since the first one has no preceding condition
// for ($i = 1; $i < count($sequence); $i++) {
// $currentElement = $sequence[$i];
// switch ($currentElement['condition']) {
// case "AND":
// $result = $result && $currentElement['value'];
// break;
// case "OR":
// $result = $result || $currentElement['value'];
// break;
// }
// }
// }
// if ($result) {
// $finalResult = true;
// } else {
// $finalResult = false;
// }
// }
// $rawArr = array_values($resultArr1);
// $organizedData = [];
// $matchedAlert = [];
// foreach ($rawArr as $entry) {
// $notification = $entry;
// $notificationId = $notification['advance_custom_notification_id'];
// $date = date("Y-m-d", strtotime($notification['date']));
// $time = date("H:i", strtotime($notification['date']));
// $day = date("D", strtotime($notification['date']));
// if (!isset($matchedAlert[$date . $notificationId]) || $notification['matched'] == true) {
// $matchedAlert[$date . $notificationId] = $notification['matched'];
// }
// // Initialize the main array element for this notification ID if not already done
// if (!isset($organizedData[$notificationId])) {
// $organizedData[$notificationId] = [
// "advance_custom_notification_id" => $notification['advance_custom_notification_id'],
// "advance_custom_notification_title" => $notification['advance_custom_notification_title'],
// // "location_title" => $notification['location_title'],
// "alerts" => [],
// "user_value" => $notification['user_value'], // Static value, change as needed
// "calculation_type" => $notification['calculation_type'],
// "calculation_type_label" => $notification['calculation_type_label'],
// "parameterName" => $notification['parameter'],
// 'finalResult' => $finalResult
// ];
// }
// // Initialize the date array element if not already done
// if (!isset($organizedData[$notificationId]['alerts'][$date])) {
// $organizedData[$notificationId]['alerts'][$date] = [
// 'date' => $date,
// 'day' => $day,
// 'rawDate' => $notification['date'],
// 'data' => []
// ];
// }
// $organizedData[$notificationId]['alerts'][$date]["isAlertPresent"] = $matchedAlert[$date . $notificationId];
// // Append time data to the corresponding date
// $organizedData[$notificationId]['alerts'][$date]['data'][] = [
// 'fromInterval' => $notification['date'],
// 'toInterval' => $notification['date'],
// 'data' => $notification,
// ];
// }
// return ["success" => true, "data" => array_values($organizedData)];
// }
// public function getAdvanceCalendarNotification(MeteomaticsWeatherService $mateoMaticsService, $user, $advanceCustomNotificationIds, $startDate, $endDate, $hour, $page, $size, $title, $paginator, $translator): array
// {
// $qualifiedLocations = [];
// $advanceCustomNotifications = new DataObject\AdvanceCustomNotification\Listing();
// $advanceCustomNotifications->addConditionParam('o_id IN (' . $advanceCustomNotificationIds . ')');
// $advanceCustomNotifications->filterByUser($user);
// $advanceCustomNotifications->setOrderKey("o_id");
// $advanceCustomNotifications->setOrder("desc");
// if (!empty($title)) {
// $advanceCustomNotifications->addConditionParam("notificationName like '%$title%' ");
// }
// $totalAdvanceCustomNotifications = $advanceCustomNotifications->count();
// if (!$totalAdvanceCustomNotifications) {
// return ['success' => false, 'message' => $translator->trans("you_do_not_have_any_advance_custom_notification_configured")];
// }
// $resultArr1 = [];
// foreach ($advanceCustomNotifications as $advanceCustomNotification) {
// $rules = $advanceCustomNotification->getNotificationConfig();
// $ruleDates = [];
// if ($rules) {
// $data = [];
// $ruleDates = [];
// foreach ($rules as $ruleConfig) {
// $ruleId = $ruleConfig->getName() . '-' . $ruleConfig->getLocation()?->getName('en') . '-' . $ruleConfig->getParameter()?->getParamName("en") . '-' . $ruleConfig->getCondition();
// $ruleDetails = [
// 'ruleId' => $ruleId,
// 'ruleName' => $ruleConfig->getName(),
// 'ruleType' => $ruleConfig->getRuleType(),
// 'location' => $ruleConfig->getLocation()?->getName('en'),
// 'model' => $ruleConfig->getModelParam(),
// 'parameter' => $ruleConfig->getParameter()?->getParamName("en"),
// 'parameterKey' => $ruleConfig->getParameter()?->getParamKey(),
// 'timeInterval' => $ruleConfig->getTimeInterval(),
// 'condition' => $ruleConfig->getCondition(),
// 'conditionValueMax' => $ruleConfig->getConditionValueMax(),
// 'conditionValueMin' => $ruleConfig->getConditionValueMin(),
// ];
// $data[] = $ruleDetails;
// }
// return ["success" => true, "data" => $data];
// }
// }
// return ["success" => true, "data" => $resultArr1];
// }
/**
* The main function that fetches, paginates, and processes notifications.
*/
public function getAdvanceCalendarNotification(
MeteomaticsWeatherService $mateoMaticsService,
$user,
$advanceCustomNotificationIds,
$startDate,
$endDate,
$hour,
$page,
$size,
$title,
$paginator,
$translator,
$location = '',
$locationTagName
): array {
// -----------------------------------------------------------
// 1) Basic validations
// -----------------------------------------------------------
if (empty($advanceCustomNotificationIds)) {
return [
'success' => false,
'message' => $translator->trans("you_do_not_have_any_advance_custom_notification_configured")
];
}
// We use Asia/Riyadh as per your requirement
$timezone = new DateTimeZone("Asia/Riyadh");
$startDateObj = new DateTime($startDate, $timezone);
$endDateObj = new DateTime($endDate, $timezone);
// -----------------------------------------------------------
// 2) Build the DataObject query
// -----------------------------------------------------------
$advanceCustomNotifications = new DataObject\AdvanceCustomNotification\Listing();
$advanceCustomNotifications->addConditionParam('o_id IN (' . $advanceCustomNotificationIds . ')');
// Only those owned by the user or shared with them
$advanceCustomNotifications->addConditionParam(
'owner__id = ? OR user LIKE ?',
[$user->getId(), '%,' . $user->getId() . ',%']
);
// Optional: Filter by title
if (!empty($title)) {
$advanceCustomNotifications->addConditionParam("notificationName like '%$title%' ");
}
// Optional: Filter by location Tag Name
if (!empty($locationTagName)) {
$db = \Pimcore\Db::get();
$tagIds = $db->fetchFirstColumn(
"SELECT ooo_id
FROM object_localized_data_Tags
WHERE language = :language AND TagName LIKE :tagName",
[
'language' => $translator->getLocale(),
'tagName' => '%' . $locationTagName . '%'
]
);
if (!empty($tagIds)) {
$condition = 'locationTag__id IN (' . implode(",", $tagIds) . ')';
$advanceCustomNotifications->addConditionParam($condition);
}
}
// Optional: Filter by location
if (!empty($location)) {
$advanceCustomNotifications->addConditionParam("locationNames like '%$location%' ");
}
// Sorting
$advanceCustomNotifications->setOrderKey("o_id");
$advanceCustomNotifications->setOrder("desc");
$totalAdvanceCustomNotifications = $advanceCustomNotifications->count();
if (!$totalAdvanceCustomNotifications) {
return [
'success' => false,
'message' => $translator->trans("you_do_not_have_any_advance_custom_notification_configured")
];
}
// -----------------------------------------------------------
// 3) Pagination
// -----------------------------------------------------------
$pageSize = $size ?? LIMIT_PER_PAGE; // Adjust to your default
$page = $page ?? 1;
$paginator = $paginator->paginate($advanceCustomNotifications, $page, $pageSize);
// -----------------------------------------------------------
// 4) Main loop over notifications
// -----------------------------------------------------------
$alertsData = [];
foreach ($paginator as $advanceCustomNotification) {
$rules = $advanceCustomNotification->getNotificationConfig();
if (!$rules) {
// No rules, skip
continue;
}
// We'll accumulate day-based data:
$ruleDates = [];
// We'll also keep a sequence of T/F for each rule/group for top-level combination (AND/OR).
$sequence = [];
// Handling groups
$groupRuleValues = []; // groupName => [bool, bool, ...]
$groupRuleCondition = []; // groupName => e.g. ['AND','OR',...]
$groupConditions = []; // groupName => 'AND' or 'OR'
$groupArr = [];
$ruleIndex = 1;
$groupIndex = 0;
// ---------------------------------------------
// 4a) Process each rule in the notification
// ---------------------------------------------
foreach ($rules as $key => $ruleConfig) {
$name = 'Rule' . $ruleIndex;
// Call YOUR getMeteomaticData
// We pass in the same $timezone used above
try {
$result = $this->getMeteomaticData($ruleConfig, $startDateObj, $endDateObj, $timezone);
} catch (Exception $e) {
// Handle/log error
continue;
}
// If 'comparedValue' is not empty => that means the condition was matched at some level
// (per your custom compareValueofCustomNotification logic).
$isMatched = !empty($result['comparedValue']);
// Distinguish single rule vs. group
if ($ruleConfig->getRuleType() === 'group') {
$groupIndex++;
if ($ruleConfig->getRulecondition() != null) {
$groupRuleCondition[$ruleConfig->getName()][] = $ruleConfig->getRulecondition();
}
$groupArr[] = $ruleConfig->getName();
$groupConditions[$ruleConfig->getName()] = $ruleConfig->getGroupCondition();
// Store the sub-rule’s boolean
$groupRuleValues[$ruleConfig->getName()][] = $isMatched;
} else {
$ruleIndex++;
// Add a top-level entry for single rule
$sequence[] = [
'name' => $ruleConfig->getName(),
'condition' => $ruleConfig->getRuleCondition(),
'type' => 'rule',
'value' => $isMatched
];
}
// --------------------------------------------------
// Build day-by-day intervals from the returned data
// --------------------------------------------------
$datesData = $result['data']['data'][0]['coordinates'][0]['dates'] ?? [];
$ruleId = $this->generateRuleId($ruleConfig, $key);
$intervalsPerDay = $this->buildDayIntervals($datesData, $ruleConfig);
// Insert these intervals into $ruleDates
foreach ($intervalsPerDay as $day => $intervals) {
if (!isset($ruleDates[$day])) {
$ruleDates[$day] = [];
}
// Build a standard data structure about this rule
$ruleDetails = [
'ruleIndex' => ($ruleConfig->getRuleType() === 'group') ? $groupIndex : $ruleIndex,
'name' => ($ruleConfig->getRuleType() === 'group')
? "Rule{$groupIndex}"
: $name,
'ruleName' => $ruleConfig->getName(),
'advanceCustomNotificationTitle' => $advanceCustomNotification->getNotificationName('en'),
'ruleId' => $ruleId,
'ruleType' => $ruleConfig->getRuleType(),
'location' => $ruleConfig->getLocation()?->getTitle('en'),
'severity_code' => (
\App\Lib\Utility::getSeverityCode($advanceCustomNotification->getSeverity(), CUSTOM_NOTIFICATION_CONFIG_COLORS)
?: ''
),
'severity' => $advanceCustomNotification->getSeverity(),
'severityAr' => (
\App\Lib\Utility::getArabicTranslation($advanceCustomNotification->getSeverity(), CUSTOM_NOTIFICATION_CONFIG_COLORS)
?: ''
),
'model' => $ruleConfig->getModelParam(),
'modelEn' => (
\App\Lib\Utility::getArabicTranslationByKey('value', $ruleConfig->getModelParam(), CUSTOM_NOTIFICATION_MODEL_TYPE, 'en')
?: ''
),
'modelAr' => (
\App\Lib\Utility::getArabicTranslationByKey('value', $ruleConfig->getModelParam(), CUSTOM_NOTIFICATION_MODEL_TYPE, 'ar')
?: ''
),
'unit' => $ruleConfig->getParameterUnitKey(),
'unitAr' => \App\Lib\Utility::getArabicTranslationUnits($ruleConfig->getParameterUnitKey()),
'parameterKey' => $ruleConfig->getParameter()?->getParamKey(),
'parameter' => $ruleConfig->getParameter()?->getParamName('en'),
'parameterAr' => $ruleConfig->getParameter()?->getParamName('ar'),
'condition' => $ruleConfig->getCondition(),
'conditionAr' => (
\App\Lib\Utility::getArabicTranslation($ruleConfig->getCondition(), CUSTOM_NOTIFICATION_CONDITION)
?: ''
),
'timeInterval' => $ruleConfig->getTimeInterval(),
'conditionValueMax' => $ruleConfig->getConditionValueMax(),
'conditionValueMin' => $ruleConfig->getConditionValueMin(),
'timeInDays' => $ruleConfig->getTimeInDays(),
'ruleCondition' => $ruleConfig->getRuleCondition(),
'groupCondition' => $ruleConfig->getGroupCondition(),
'modelValue' => $ruleConfig->getModelValue(),
'heightOrDepth' => $ruleConfig->getHeightOrDepth(),
'rawDate' => isset($intervals[0]) ? $intervals[0]['time'] : null,
'intervals' => $intervals
];
// If it's a group rule, nest it inside a group array
if ($ruleConfig->getRuleType() === 'group') {
$groupExists = false;
foreach ($ruleDates[$day] as &$existingGroup) {
if (isset($existingGroup['groupName']) && $existingGroup['groupName'] === $ruleConfig->getName()) {
$existingGroup['rules'][] = $ruleDetails;
$groupExists = true;
break;
}
}
if (!$groupExists) {
$ruleDates[$day][] = [
'groupName' => $ruleConfig->getName(),
'rules' => [$ruleDetails],
];
}
} else {
// It's a normal rule
$ruleExists = false;
foreach ($ruleDates[$day] as &$existingRuleData) {
if (isset($existingRuleData['ruleId']) && $existingRuleData['ruleId'] === $ruleId) {
$existingRuleData['intervals'] = array_merge($existingRuleData['intervals'], $intervals);
$ruleExists = true;
break;
}
}
if (!$ruleExists) {
$ruleDates[$day][] = $ruleDetails;
}
}
}
} // end foreach $rules
// ---------------------------------------------
// 4b) Evaluate group booleans & push to $sequence
// ---------------------------------------------
if (!empty($groupRuleValues)) {
foreach ($groupRuleValues as $groupName => $values) {
if (isset($groupRuleCondition[$groupName])) {
// Evaluate using your custom group logic
$wholeGroupResult = \App\Lib\Utility::evaluateConditions(
$values,
$groupRuleCondition[$groupName]
);
$sequence[] = [
'name' => $groupName,
'condition' => $groupConditions[$groupName] ?? null,
'type' => 'group',
'value' => $wholeGroupResult
];
} else {
// No explicit condition set => just take the first
$sequence[] = [
'name' => $groupName,
'condition' => $groupConditions[$groupName] ?? null,
'type' => 'group',
'value' => $values[0]
];
}
}
}
// ---------------------------------------------
// 4c) Combine top-level booleans with AND/OR
// ---------------------------------------------
$finalRuleOrGroupResult = $this->evaluateSequence($sequence);
// ---------------------------------------------
// 4d) Build final day-based array
// ---------------------------------------------
$daysData = [];
foreach ($ruleDates as $day => $rulesOnDay) {
// Check if ANY interval is matched => finalResult = true
$dayHasMatched = $this->hasAnyMatched($rulesOnDay);
// If you need to combine with $finalRuleOrGroupResult, do so here, e.g.:
// $final = $dayHasMatched && $finalRuleOrGroupResult;
// For now, we'll just rely on "any match" => true
$daysData[] = [
'finalResult' => $dayHasMatched,
'date' => $day,
'data' => $rulesOnDay
];
}
// Add this notification's days to $alertsData
$alertsData[] = $daysData;
}
// -----------------------------------------------------------
// 5) Return data + pagination variables
// -----------------------------------------------------------
return [
'success' => true,
'data' => $alertsData,
'paginationVariables' => $paginator->getPaginationData()
];
}
/**
* YOUR real getMeteomaticData() method (replaces the placeholder).
*/
public function getMeteomaticData($rule, $startDate, $endDate, $timezone = null)
{
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
// Just reuse your code as-is; below is copied from your snippet:
$startDateObj = $startDate;
$endDateObj = $endDate;
if ($timezone) {
$startDateUtc = $startDateObj->setTimezone($timezone)->format('Y-m-d\TH:i:s.v\Z');
$endDateUtc = $endDateObj->setTimezone($timezone)->format('Y-m-d\TH:i:s.v\Z');
} else {
$startDateUtc = $startDateObj->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d\TH:i:s.v\Z');
$endDateUtc = $endDateObj->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d\TH:i:s.v\Z');
}
// Rule parameters
$duration = $rule->getTimeInterval();
$param = $rule->getParameter()->getParamKey();
$paramName = $rule->getParameter()->getParamName("en");
$unit = $rule->getParameterUnitKey();
$coordinates = json_decode($rule->getLocation()->getCoordinates(), true);
$heightDepth = $rule->getHeightOrDepth();
$durationInterval = 1;
if (stripos($rule->getTimeInDays(), 'h') !== false) {
$hours = (int) filter_var($rule->getTimeInDays(), FILTER_SANITIZE_NUMBER_INT);
$durationInterval = $hours;
} else {
$days = (int) filter_var($rule->getTimeInDays(), FILTER_SANITIZE_NUMBER_INT);
$durationInterval = $days * 24;
}
if ($durationInterval==0) {
$durationInterval=24;
}
// $resolution = 'PT'.$durationInterval.'H';
$resolution = 'PT1H'; // Hourly resolution
$model = $rule->getModelParam() !== "model"
? "mix&calibrated=true"
: ($rule->getModelValue() ?: 'mix');
// Build parameter string
$parametersStr = $param;
if ($heightDepth) {
$parametersStr .= '_' . $heightDepth;
}
if ($duration) {
$parametersStr .= '_' . $duration . 'h';
}
if ($unit) {
$parametersStr .= ':' . $unit;
}
// Format coordinates
$formattedCoordinates = (count($coordinates) > 1)
? implode('+', array_map(fn($coord) => implode(',', $coord), $coordinates))
: implode(',', $coordinates[0]);
// Construct API URL
$url = "{$this->apiBaseUrl}/{$startDateUtc}--{$endDateUtc}:{$resolution}/{$parametersStr}/{$formattedCoordinates}/json?source={$model}&use_decluttered=true";
// Make API request via Guzzle
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
// Compare values using your existing utility method
$ruleValue = \App\Lib\Utility::compareValueofCustomNotification(
$data,
$rule->getCondition(),
$rule->getConditionValueMin(),
$rule->getConditionValueMax(),
$paramName,
$rule->getLocation()->getName(),
$unit
);
return [
"data" => $data,
'comparedValue' => $ruleValue,
"parameterKey" => $parametersStr,
'alertName' => $paramName
];
}
/**
* Break down the 'dates' array from Meteomatics into day-based intervals.
*/
private function buildDayIntervals(array $datesData, $ruleConfig): array
{
$intervalsPerDay = [];
foreach ($datesData as $date) {
if (!isset($date['date']) || !isset($date['value'])) {
continue;
}
$time = $date['date'];
$value = $date['value'];
$day = (new DateTime($time))->format('Y-m-d');
if (!isset($intervalsPerDay[$day])) {
$intervalsPerDay[$day] = [];
}
// Evaluate 'matched' for each hourly interval
$matched = \App\Lib\Utility::isWeatherConditionMatched(
$ruleConfig->getConditionValueMin(),
$ruleConfig->getConditionValueMax(),
$value,
$ruleConfig->getCondition()
);
$intervalsPerDay[$day][] = [
'time' => $time,
'value' => $value,
'condition' => $ruleConfig->getCondition(),
'conditionValueMax' => $ruleConfig->getConditionValueMax(),
'conditionValueMin' => $ruleConfig->getConditionValueMin(),
'matched' => $matched,
];
}
return $intervalsPerDay;
}
/**
* Combine an array of booleans with AND/OR logic in sequence order.
*/
private function evaluateSequence(array $sequence): bool
{
if (empty($sequence)) {
return false;
}
$final = $sequence[0]['value'];
for ($i = 1; $i < count($sequence); $i++) {
$current = $sequence[$i];
switch ($current['condition']) {
case 'AND':
$final = $final && $current['value'];
break;
case 'OR':
$final = $final || $current['value'];
break;
default:
// fallback or handle unknown
$final = $final && $current['value'];
}
}
return $final;
}
/**
* Determine if ANY interval in the day's data was matched.
* Supports both single-rule arrays and grouped rules.
*/
private function hasAnyMatched(array $rulesOnDay): bool
{
foreach ($rulesOnDay as $ruleData) {
// If it's a group => check $ruleData['rules']
if (isset($ruleData['groupName']) && isset($ruleData['rules'])) {
foreach ($ruleData['rules'] as $subRule) {
foreach ($subRule['intervals'] as $interval) {
if (!empty($interval['matched'])) {
return true;
}
}
}
} else {
// Single rule => intervals are directly in $ruleData['intervals']
if (isset($ruleData['intervals'])) {
foreach ($ruleData['intervals'] as $interval) {
if (!empty($interval['matched'])) {
return true;
}
}
}
}
}
return false;
}
/**
* Generate a unique rule ID (mimicking your original approach).
*/
private function generateRuleId($ruleConfig, $key): string
{
$locName = $ruleConfig->getLocation()?->getName('en') ?? '';
$paramName = $ruleConfig->getParameter()?->getParamName('en') ?? '';
return sprintf(
"%s-%s-%s-%s-%d",
$ruleConfig->getName(),
$locName,
$paramName,
$ruleConfig->getCondition(),
$key
);
}
public function getAdvanceNotifications(
MeteomaticsWeatherService $mateoMaticsService,
$user,
$notificationIds,
$startDate,
$endDate,
$hour,
$page,
$size,
$title,
$paginator,
$translator
): array {
$timezone = new \DateTimeZone("Asia/Riyadh");
$startDateObj = new \DateTime($startDate, $timezone);
$endDateObj = new \DateTime($endDate, $timezone);
$pageSize = isset($size) ? $size : LIMIT_PER_PAGE;
$page = isset($page) ? $page : 1;
if (empty($notificationIds)) {
return ['success' => false, 'message' => $translator->trans("no_notifications_configured")];
}
$notificationListing = new DataObject\AdvanceCustomNotification\Listing();
$notificationListing->addConditionParam('o_id IN (' . $notificationIds . ')');
$notificationListing->addConditionParam('owner__id = ? OR user LIKE ? ', [$user->getId(), '%,' . $user->getId() . ',%']);
$notificationListing->setOrderKey("o_id");
$notificationListing->setOrder("desc");
if (!empty($title)) {
$notificationListing->addConditionParam("notificationName like '%$title%' ");
}
if (!empty($location)) {
$db = \Pimcore\Db::get();
$tagIds = $db->fetchFirstColumn(
"SELECT ooo_id
FROM object_localized_data_Tags
WHERE language = :language AND TagName LIKE :tagName",
[
'language' => $translator->getLocale(),
'tagName' => '%' . $location . '%'
]
);
if (!empty($tagIds)) {
$condition = 'locationTag__id IN (' . implode(",", $tagIds) . ') OR locationNames LIKE ?';
$params = [
'%' . $location . '%',
];
$notificationListing->addConditionParam($condition, $params);
} else {
$notificationListing->addConditionParam("locationNames like '%$location%' ");
}
}
$paginator = $paginator->paginate(
$notificationListing,
$page,
$pageSize
);
$notificationsCount = $paginator->count();
if (!$notificationsCount) {
return ['success' => false, 'message' => $translator->trans("no_notifications_found")];
}
$resultArr = [];
$matchedNotifications = [];
foreach ($paginator as $notification) {
// print($notification->getid());
$rules = $notification->getNotificationConfig();
$notificationResult = $this->processRules($rules, $notification, $startDateObj, $endDateObj, $hour, $timezone);
}
return $notificationResult;
}
private function processRules(
$rules,
$notification,
$startDateObj,
$endDateObj,
$hour,
$timezone
): array {
$data = [];
$finalResult = false; // Overall final result for the notification
$groupResults = [];
$ruleIndex = 1; // Incremental index for rules
foreach ($rules as $rule) {
$ruleName = $rule->getName();
$ruleType = $rule->getRuleType();
$ruleCondition = $rule->getRuleCondition();
$groupCondition = $rule->getGroupCondition();
// Fetch Meteomatics data
$result = $this->getMeteomaticData($rule, $startDateObj, $endDateObj, $timezone);
$datesData = $result['data']['data'][0]['coordinates'][0]['dates'];
$intervalsPerDay = [];
$isMatched = false; // Whether any interval matches the condition
foreach ($datesData as $date) {
if (isset($date['date'], $date['value'])) {
$interval = [
'time' => $date['date'],
'value' => $date['value'],
'condition' => $rule->getCondition(),
'conditionValueMax' => $rule->getConditionValueMax(),
'conditionValueMin' => $rule->getConditionValueMin(),
'matched' => \App\Lib\Utility::compareValues(
$rule->getCondition(),
$date['value'],
[
$rule->getConditionValueMin(),
$rule->getConditionValueMax(),
]
),
];
$day = (new DateTime($date['date']))->format('Y-m-d');
if (!isset($intervalsPerDay[$day])) {
$intervalsPerDay[$day] = [];
}
$intervalsPerDay[$day][] = $interval;
// Check if any interval matches
if ($interval['matched']) {
$isMatched = true;
}
}
}
foreach ($intervalsPerDay as $day => $intervals) {
$ruleDetails = [
'alertId' => $notification->getID(),
'ruleIndex' => $ruleIndex,
'name' => $ruleType === 'group' ? "Group" : "Rule" . $ruleIndex,
'ruleName' => $ruleName,
'advanceCustomNotificationTitle' => $notification->getNotificationName('en'),
'ruleId' => $ruleName . '-' . $rule->getLocation()?->getName('en'),
'ruleType' => $ruleType,
'location' => $rule->getLocation()?->getName('en'),
'severity_code' => (\App\Lib\Utility::getSeverityCode($notification->getSeverity(), CUSTOM_NOTIFICATION_CONFIG_COLORS) ? \App\Lib\Utility::getSeverityCode($notification->getSeverity(), CUSTOM_NOTIFICATION_CONFIG_COLORS) : ''),
'severity' => $notification->getSeverity(),
'severityAr' => (\App\Lib\Utility::getArabicTranslation($notification->getSeverity(), CUSTOM_NOTIFICATION_CONFIG_COLORS) ? \App\Lib\Utility::getArabicTranslation($notification->getSeverity(), CUSTOM_NOTIFICATION_CONFIG_COLORS) : ''),
'model' => $rule->getModelParam(),
'modelEn' => (\App\Lib\Utility::getArabicTranslationByKey('value', $rule->getModelParam(), CUSTOM_NOTIFICATION_MODEL_TYPE, 'en') ? \App\Lib\Utility::getArabicTranslationByKey('value', $rule->getModelParam(), CUSTOM_NOTIFICATION_MODEL_TYPE, 'en') : ''),
'modelAr' => (\App\Lib\Utility::getArabicTranslationByKey('value', $rule->getModelParam(), CUSTOM_NOTIFICATION_MODEL_TYPE, 'ar') ? \App\Lib\Utility::getArabicTranslationByKey('value', $rule->getModelParam(), CUSTOM_NOTIFICATION_MODEL_TYPE, 'ar') : ''),
'unit' => $rule->getParameterUnitKey(),
'unitAr' => (\App\Lib\Utility::getArabicTranslationUnits($rule->getParameterUnitKey())),
'parameterKey' => $rule->getParameter()?->getParamKey(),
'parameter' => $rule->getParameter()?->getParamName('en'),
'parameterAr' => $rule->getParameter()?->getParamName('ar'),
'condition' => $rule->getCondition(),
'conditionAr' => (\App\Lib\Utility::getArabicTranslation($rule->getCondition(), CUSTOM_NOTIFICATION_CONDITION) ? \App\Lib\Utility::getArabicTranslation($rule->getCondition(), CUSTOM_NOTIFICATION_CONDITION) : ''),
'timeInterval' => $rule->getTimeInterval(),
'conditionValueMax' => $rule->getConditionValueMax(),
'conditionValueMin' => $rule->getConditionValueMin(),
'timeInDays' => $rule->getTimeInDays(),
'ruleCondition' => $rule->getRuleCondition(),
'groupCondition' => $rule->getGroupCondition(),
'modelValue' => $rule->getModelValue(),
'heightOrDepth' => $rule->getHeightOrDepth(),
'rawDate' => $intervals[0]['time'],
'intervals' => $intervals,
];
if ($ruleType === 'group') {
// Aggregate group results
if (!isset($groupResults[$ruleName])) {
$groupResults[$ruleName] = [
'rules' => [],
'condition' => $groupCondition,
'values' => [],
];
}
$groupResults[$ruleName]['rules'][] = $ruleDetails;
$groupResults[$ruleName]['values'][] = $isMatched;
} else {
// Add standalone rule result
$data[$day][] = $ruleDetails;
$finalResult = $this->evaluateCondition($finalResult, $isMatched, $ruleCondition);
}
}
$ruleIndex++;
}
// Process group results
foreach ($groupResults as $groupName => $group) {
$groupCondition = ($group['condition']) ? $group['condition'] : "AND";
// Ensure $groupCondition is expanded to match the number of values
$operators = array_fill(0, count($group['values']) - 1, $groupCondition);
// Evaluate conditions only if there are multiple values
if (count($group['values']) > 1) {
$groupMatchResult = \App\Lib\Utility::evaluateConditionsAdvanceCustomNotification($group['values'], $operators);
} else {
// If there's only one value, use it directly
$groupMatchResult = $group['values'][0];
}
$finalResult = $this->evaluateCondition($finalResult, $groupMatchResult, $groupCondition);
$data[] = [
'groupName' => $groupName,
'result' => $groupMatchResult,
'rules' => $group['rules'],
];
if ($groupMatchResult) {
$matchedRules[] = $groupName;
}
}
return [
'finalResult' => $finalResult,
'data' => $data,
];
}
private function evaluateSingleRule($rule, $startDateObj, $endDateObj, $timezone): array
{
$duration = $rule->getTimeInterval();
$param = $rule->getParameter()->getParamKey();
$paramName = $rule->getParameter()->getParamName("en");
$unit = $rule->getParameterUnitKey();
$coordinates = json_decode($rule->getLocation()->getCoordinates(), true);
$heightDepth = $rule->getHeightOrDepth();
$resolution = 'PT1H';
$formattedCoordinates = "";
$model = $rule->getModelParam() !== "model"
? "mix&calibrated=true"
: ($rule->getModelValue() ?: 'mix');
// Construct parameter string
$parametersStr = $param;
if ($heightDepth) {
$parametersStr .= '_' . $heightDepth;
}
if ($duration) {
$parametersStr .= '_' . $duration . 'h';
}
if ($unit) {
$parametersStr .= ':' . $unit;
}
// Format coordinates
$formattedCoordinates = count($coordinates) > 1
? implode('+', array_map(fn($coordinate) => implode(',', $coordinate), $coordinates))
: implode(',', $coordinates[0]);
// Construct the URL for Meteomatics API
$startDate = $startDateObj->format('Y-m-d\T00:00:00.v\Z');
$endDate = $endDateObj->format('Y-m-d\T23:59:59.v\Z');
$url = "{$this->apiBaseUrl}/{$startDate}--{$endDate}:{$resolution}/{$parametersStr}/{$formattedCoordinates}/json?source={$model}&use_decluttered=true";
// Fetch data from Meteomatics
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
$qualifiedLocations = $data['data'][0]['coordinates'][0]['dates'];
$matched = false;
$ruleData = [];
foreach ($qualifiedLocations as $location) {
$value = $location['value'];
$date = new \DateTime($location['date'], new \DateTimeZone("UTC"));
$date->setTimezone($timezone);
$condition = $rule->getCondition();
$minValue = $rule->getConditionValueMin();
$maxValue = $rule->getConditionValueMax();
if ($condition == "range") {
$matched = \App\Lib\Utility::compareValues($condition, $value, [$minValue, $maxValue]);
} else {
$matched = \App\Lib\Utility::compareValues($condition, $value, $minValue);
}
if ($matched) {
$ruleData[] = [
'date' => $date->format('Y-m-d H:i'),
'value' => $value,
'location' => $rule->getLocation()->getName(),
];
}
}
return [
'rule_name' => $rule->getName(),
'matched' => $matched,
'data' => $ruleData,
];
}
private function evaluateCondition($currentResult, $newResult, $condition)
{
if ($condition === 'AND') {
return $currentResult && $newResult;
} elseif ($condition === 'OR') {
return $currentResult || $newResult;
}
return $currentResult;
}
}