545 lines
16 KiB
PHP
545 lines
16 KiB
PHP
<?php
|
|
|
|
include_once 'lib/ghl/calendar.php';
|
|
|
|
function filterTimeSlots($timeSlots, $startTime, $endTime) {
|
|
$filteredSlots = array_filter($timeSlots, function($slot) use ($startTime, $endTime) {
|
|
$slotTime = strtotime($slot);
|
|
$start = strtotime($startTime);
|
|
$end = strtotime($endTime);
|
|
|
|
return $slotTime >= $start && $slotTime <= $end;
|
|
});
|
|
|
|
return array_values($filteredSlots); // Reset array keys
|
|
}
|
|
|
|
|
|
function extractRanges($slotStart, $slotEnd, $serviceStart, $serviceEnd, $interval, $date)
|
|
{
|
|
//echo function args
|
|
echo "\n Function Args \n ";
|
|
print_r(func_get_args());
|
|
// Convert time strings to DateTime objects for easier comparison
|
|
$slotStartTime = new DateTime($date . ' ' . $slotStart);
|
|
$slotEndTime = new DateTime($date . ' ' . $slotEnd);
|
|
$serviceStartTime = new DateTime($date . ' ' . $serviceStart);
|
|
$serviceEndTime = new DateTime($date . ' ' . $serviceEnd);
|
|
|
|
if ($slotEndTime < $slotStartTime) {
|
|
$slotEndTime->modify('+1 day');
|
|
}
|
|
if ($serviceEndTime < $serviceStartTime) {
|
|
$serviceEndTime->modify('+1 day');
|
|
}
|
|
|
|
// Check if service time falls within the slot range
|
|
if ($serviceStartTime >= $slotStartTime && $serviceStartTime < $slotEndTime) {
|
|
// if ($serviceStartTime >= $slotStartTime && $serviceEndTime <= $slotEndTime) {
|
|
$ranges = array();
|
|
|
|
// Calculate ranges based on the interval
|
|
$currentRangeStart = $serviceStartTime;
|
|
if ($currentRangeStart < $slotEndTime) {
|
|
array_push($ranges, $currentRangeStart->format('H:i:s'));
|
|
}
|
|
while ($currentRangeStart < $serviceEndTime) {
|
|
$currentRangeEnd = clone $currentRangeStart;
|
|
$currentRangeEnd->add(new DateInterval("PT" . $interval . "M"));
|
|
|
|
// Check if the calculated range end is within the slot range
|
|
if ($currentRangeEnd < $slotEndTime) {
|
|
// array_push(
|
|
// $ranges,
|
|
// $currentRangeStart->format('H:i:s')
|
|
// );
|
|
array_push(
|
|
$ranges,
|
|
$currentRangeEnd->format('H:i:s')
|
|
);
|
|
} else {
|
|
// Add the end time within the slot range
|
|
// array_push($ranges, $slotEndTime->format('H:i:s'));
|
|
// Break the loop if the range end exceeds the slot end time
|
|
break;
|
|
}
|
|
|
|
$currentRangeStart = $currentRangeEnd;
|
|
}
|
|
|
|
return $ranges;
|
|
} elseif ($serviceStartTime < $slotStartTime && $serviceEndTime <= $slotEndTime) {
|
|
// if ($serviceStartTime >= $slotStartTime && $serviceEndTime <= $slotEndTime) {
|
|
$ranges = array();
|
|
|
|
// Calculate ranges based on the interval
|
|
$currentRangeStart = $slotStartTime;
|
|
if ($currentRangeStart < $serviceEndTime) {
|
|
array_push($ranges, $currentRangeStart->format('H:i:s'));
|
|
}
|
|
// array_push($ranges, $currentRangeStart->format('H:i:s'));
|
|
while ($currentRangeStart < $serviceEndTime) {
|
|
$currentRangeEnd = clone $currentRangeStart;
|
|
$currentRangeEnd->add(new DateInterval("PT" . $interval . "M"));
|
|
|
|
// Check if the calculated range end is within the slot range
|
|
if ($currentRangeEnd < $slotEndTime) {
|
|
// array_push(
|
|
// $ranges,
|
|
// $currentRangeStart->format('H:i:s')
|
|
// );
|
|
array_push(
|
|
$ranges,
|
|
$currentRangeEnd->format('H:i:s')
|
|
);
|
|
} else {
|
|
// Add the end time within the slot range
|
|
// array_push($ranges, $slotEndTime->format('H:i:s'));
|
|
// Break the loop if the range end exceeds the slot end time
|
|
break;
|
|
}
|
|
|
|
$currentRangeStart = $currentRangeEnd;
|
|
}
|
|
|
|
return $ranges;
|
|
} elseif ($serviceStartTime < $slotStartTime && $serviceEndTime > $slotEndTime) {
|
|
// if ($serviceStartTime >= $slotStartTime && $serviceEndTime <= $slotEndTime) {
|
|
$ranges = array();
|
|
|
|
// Calculate ranges based on the interval
|
|
$currentRangeStart = $slotStartTime;
|
|
if ($currentRangeStart < $serviceEndTime) {
|
|
array_push($ranges, $currentRangeStart->format('H:i:s'));
|
|
}
|
|
// array_push($ranges, $currentRangeStart->format('H:i:s'));
|
|
while ($currentRangeStart < $serviceEndTime) {
|
|
$currentRangeEnd = clone $currentRangeStart;
|
|
$currentRangeEnd->add(new DateInterval("PT" . $interval . "M"));
|
|
|
|
// Check if the calculated range end is within the slot range
|
|
if ($currentRangeEnd < $slotEndTime) {
|
|
// array_push(
|
|
// $ranges,
|
|
// $currentRangeStart->format('H:i:s')
|
|
// );
|
|
array_push(
|
|
$ranges,
|
|
$currentRangeEnd->format('H:i:s')
|
|
);
|
|
} else {
|
|
// Add the end time within the slot range
|
|
// array_push($ranges, $slotEndTime->format('H:i:s'));
|
|
// Break the loop if the range end exceeds the slot end time
|
|
break;
|
|
}
|
|
|
|
$currentRangeStart = $currentRangeEnd;
|
|
}
|
|
|
|
return $ranges;
|
|
} elseif ($serviceStartTime >= $slotStartTime && $serviceEndTime <= $slotEndTime) {
|
|
$ranges = array();
|
|
|
|
// Calculate ranges based on the interval
|
|
$currentRangeStart = $serviceStartTime;
|
|
if ($currentRangeStart < $serviceEndTime) {
|
|
array_push($ranges, $currentRangeStart->format('H:i:s'));
|
|
}
|
|
// array_push($ranges, $currentRangeStart->format('H:i:s'));
|
|
while ($currentRangeStart <= $serviceEndTime) {
|
|
$currentRangeEnd = clone $currentRangeStart;
|
|
$currentRangeEnd->add(new DateInterval("PT" . $interval . "M"));
|
|
|
|
// Check if the calculated range end is within the slot range
|
|
if ($currentRangeEnd <= $slotEndTime) {
|
|
// array_push(
|
|
// $ranges,
|
|
// $currentRangeStart->format('H:i:s')
|
|
// );
|
|
array_push(
|
|
$ranges,
|
|
$currentRangeEnd->format('H:i:s')
|
|
);
|
|
} else {
|
|
// Add the end time within the slot range
|
|
// array_push($ranges, $slotEndTime->format('H:i:s'));
|
|
// Break the loop if the range end exceeds the slot end time
|
|
break;
|
|
}
|
|
|
|
$currentRangeStart = $currentRangeEnd;
|
|
}
|
|
|
|
return $ranges;
|
|
} else {
|
|
// Service time is outside the slot range
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function convertToDays($value, $unit)
|
|
{
|
|
switch ($unit) {
|
|
case 'weeks':
|
|
return $value * 7;
|
|
case 'months':
|
|
// Assuming a month is considered as 30 days for simplicity
|
|
return $value * 30;
|
|
case 'hours':
|
|
return 0; // Set to 0 days if the unit is hours
|
|
default:
|
|
return $value;
|
|
}
|
|
}
|
|
|
|
function checkServiceInSlot($service, $slot, $mod, $eventTiming, $schedule, $ser_id)
|
|
{
|
|
|
|
$slotpoint = 0;
|
|
// Get the current date
|
|
$currentDate = new DateTime('now');
|
|
|
|
|
|
// return $slotpoint;
|
|
|
|
// if ($mod->alert == 'On') {
|
|
$slotpoint = calculateTotalPoints((int)$mod->days, $slot, $service, $eventTiming, $schedule, $mod, $ser_id);
|
|
if (is_array($slotpoint)) {
|
|
return $slotpoint['message'];
|
|
}
|
|
if ($slotpoint < (int)$mod->score_threshold && $slotpoint != 0) {
|
|
|
|
$data = [
|
|
'actual_score' => $slotpoint,
|
|
];
|
|
// Update points
|
|
$projectModel = new ProjectModel();
|
|
$projectModel->edit($data, $mod->id);
|
|
|
|
if ($mod->alert != 'On') {
|
|
return 'No alert set for project ' . $mod->project_name . ' with ID ' . $mod->id;
|
|
}
|
|
|
|
// Retrieve webhook URL and payload
|
|
$webhookUrl = $mod->webhook;
|
|
if (!filter_var($webhookUrl, FILTER_VALIDATE_URL)) {
|
|
// error_log('Webhook for project ' . $mod->project_name . ' with ID ' . $mod->id . ' is not a URL ');
|
|
return 'Invalid Webhook URL';
|
|
}
|
|
|
|
|
|
$jsonData = json_decode($mod->payload);
|
|
|
|
|
|
// Set up cURL options
|
|
$curlOptions = [
|
|
CURLOPT_URL => $webhookUrl,
|
|
CURLOPT_POST => 1,
|
|
CURLOPT_POSTFIELDS => json_encode($jsonData), // Send encoded JSON
|
|
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
];
|
|
|
|
// Initialize cURL session
|
|
$ch = curl_init();
|
|
|
|
// Set cURL options
|
|
curl_setopt_array($ch, $curlOptions);
|
|
|
|
// Execute cURL session and get the result
|
|
$response = curl_exec($ch);
|
|
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
|
if ($status_code != 200) {
|
|
// error_log('Curl error for project ' . $mod->project_name . ' with ID ' . $mod->id . ': ' . curl_error($ch));
|
|
return 'Something went wrong while sending webhook payload';
|
|
}
|
|
|
|
|
|
|
|
// Log the webhook response
|
|
curl_close($ch);
|
|
// error_log('Webhook response for project ' . $mod->project_name . ' with ID ' . $mod->id . ': ' . $response);
|
|
return 'Accepted';
|
|
|
|
|
|
// Close cURL session
|
|
|
|
} else {
|
|
|
|
$data = [
|
|
'actual_score' => $slotpoint,
|
|
];
|
|
|
|
|
|
// Insert data into the database using LicenseModel
|
|
$projectModel = new ProjectModel();
|
|
$projectModel->edit($data, $mod->id);
|
|
$result = "Point is higher than mininum point set"; // Initialize result variable
|
|
|
|
return $result; // Return the accumulated result
|
|
|
|
}
|
|
// } else {
|
|
// // Log that no alert is set for the project
|
|
// // error_log('No alert set for project ' . $mod->project_name . ' with ID ' . $mod->id);
|
|
// return 'No alert set for project ' . $mod->project_name . ' with ID ' . $mod->id;
|
|
// }
|
|
}
|
|
|
|
function generateTimeIntervals($startTime, $endTime, $intervalMinutes, $date)
|
|
{
|
|
|
|
$start = new DateTime($date . ' ' . $startTime);
|
|
$end = new DateTime($date . ' ' . $endTime);
|
|
|
|
if ($end < $start) {
|
|
$end->modify('+1 day');
|
|
}
|
|
$intervalObj = new DateInterval("PT{$intervalMinutes}M"); // PT stands for 'Period Time'
|
|
|
|
$period = new DatePeriod($start, $intervalObj, $end);
|
|
|
|
$intervals = array();
|
|
foreach ($period as $dt) {
|
|
$intervals[] = $dt->format('H:i:s');
|
|
}
|
|
|
|
return $intervals;
|
|
}
|
|
|
|
function calculateTotalPoints($daysToCheck, $slot, $service, $eventTiming, $schedule, $project, $ser_id)
|
|
{
|
|
// return json_encode($schedule);
|
|
|
|
|
|
// Convert allowBookingFor to days if the unit is months or weeks
|
|
if ($schedule['allowBookingForUnit'] === 'months' || $schedule['allowBookingForUnit'] === 'weeks') {
|
|
$schedule['allowBookingFor'] = convertToDays($schedule['allowBookingFor'], $schedule['allowBookingForUnit']);
|
|
$schedule['allowBookingForUnit'] = 'days';
|
|
}
|
|
if ($schedule['allowBookingAfterUnit'] === 'months' || $schedule['allowBookingAfterUnit'] === 'weeks' || $schedule['allowBookingAfterUnit'] === 'hours') {
|
|
$schedule['allowBookingAfter'] = convertToDays($schedule['allowBookingAfter'], $schedule['allowBookingAfterUnit']);
|
|
$schedule['allowBookingAfterUnit'] = 'days';
|
|
}
|
|
// return "well";
|
|
|
|
$currentDate = new DateTime();
|
|
$currentDayIndex = $currentDate->format('w'); // 0 for Sunday, 1 for Monday, ..., 6 for Saturday
|
|
|
|
// Get the next two days to check
|
|
// $daysToCheckIndices = [];
|
|
// for ($i = 0; $i < $daysToCheck; $i++) {
|
|
// $nextDayIndex = ($currentDayIndex + $i + 1) % 7;
|
|
// $daysToCheckIndices[] = $nextDayIndex;
|
|
// }
|
|
|
|
|
|
|
|
$daysToCheckData = [];
|
|
if (empty($schedule['allowBookingFor'])) {
|
|
$counter = $daysToCheck;
|
|
} else {
|
|
$counter = (int)$schedule['allowBookingFor'];
|
|
}
|
|
if (empty($schedule['allowBookingAfter'])) {
|
|
$skip = 0;
|
|
} else {
|
|
$skip = (int)$schedule['allowBookingAfter'];
|
|
}
|
|
// Don't check beyond 30 days
|
|
if ($counter > 30) {
|
|
$counter = 30;
|
|
}
|
|
for ($i = $skip; $i < $counter; $i++) {
|
|
$nextDayIndex = ($currentDayIndex + $i) % 7;
|
|
$nextDate = clone $currentDate;
|
|
$nextDate->modify("+$i day");
|
|
|
|
|
|
$daysToCheckData[] = [
|
|
'index' => $nextDayIndex,
|
|
'date' => $nextDate->format('Y-m-d'),
|
|
];
|
|
}
|
|
|
|
|
|
|
|
// return json_encode($daysToCheckData);
|
|
$totalPoints = 0;
|
|
|
|
// Loop through the selected days and calculate total points
|
|
$dayNames = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
|
|
|
// GHL V2 token refresh
|
|
// access token expires in a day
|
|
// refresh token last for a year if you don't use it.
|
|
// after refreshing you get a new refresh token and access token but previous refresh token expires.
|
|
$canRefresh = false;
|
|
if ($project->refresh_token != "") {
|
|
$canRefresh = true;
|
|
}
|
|
|
|
if ($canRefresh) {
|
|
$calendar = new GHLCalendar($project->id, $project->access_token, $project->refresh_token);
|
|
$result = $calendar->refreshToken();
|
|
|
|
if ($result['code'] != 200) {
|
|
return $result;
|
|
}
|
|
}
|
|
// foreach ($daysToCheckIndices as $dayIndex) {
|
|
foreach ($daysToCheckData as $dayData) {
|
|
// $dayName = $dayNames[$dayIndex];
|
|
// // error_log("day" . $dayName);
|
|
|
|
|
|
|
|
$dayIndex = $dayData['index'];
|
|
$dayName = $dayNames[$dayIndex];
|
|
$date = $dayData['date'];
|
|
|
|
|
|
|
|
// print_r($service);
|
|
if (isset($slot->$dayName)) {
|
|
if (!array_key_exists($dayName, $service)) {
|
|
continue; // Day not found in the service schedule
|
|
}
|
|
$der = [];
|
|
|
|
|
|
foreach ($service[$dayName] as $ser) {
|
|
$serviceStart = strtotime(sprintf("%02d:%02d", $ser["openHour"], $ser["openMinute"]));
|
|
$serviceEnd = strtotime(sprintf("%02d:%02d", $ser["closeHour"], $ser["closeMinute"]));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// $start = strtotime($dayData['date'] . ' ' . sprintf("%02d:%02d", $ser["openHour"], $ser["openMinute"]));
|
|
// $end = strtotime($dayData['date'] . ' ' . sprintf("%02d:%02d", $ser["closeHour"], $ser["closeMinute"]));
|
|
// $start = $start * 1000;
|
|
// $end = $end * 1000;
|
|
|
|
// Set start time to beginning of day (00:00:00)
|
|
$start = strtotime($dayData['date'] . ' 00:00:00');
|
|
// Set end time to end of day (23:59:59)
|
|
$end = strtotime($dayData['date'] . ' 23:59:59');
|
|
|
|
$start = $start * 1000;
|
|
$end = $end * 1000;
|
|
$apikey2 = $project->location;
|
|
$curl = curl_init();
|
|
|
|
|
|
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_URL => "https://rest.gohighlevel.com/v1/appointments/slots?calendarId=$ser_id&startDate=$start&endDate=$end",
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_ENCODING => "",
|
|
CURLOPT_MAXREDIRS => 10,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
|
CURLOPT_CUSTOMREQUEST => "GET",
|
|
CURLOPT_HTTPHEADER => [
|
|
"Accept: application/json",
|
|
"Authorization: Bearer " . $apikey2,
|
|
"Version: 2021-04-15"
|
|
],
|
|
]);
|
|
|
|
$response = curl_exec($curl);
|
|
$err = curl_error($curl);
|
|
$status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
|
|
|
|
|
curl_close($curl);
|
|
|
|
|
|
if ($status_code != 200 && !$canRefresh) {
|
|
return ["code" => 422, "message" => "Please authorize the app to fetch free slots"];
|
|
}
|
|
|
|
if ($status_code != 200) {
|
|
|
|
$calendar = new GHLCalendar($project->id, $project->access_token, $project->refresh_token);
|
|
$result = $calendar->getFreeSlots( $ser_id, $start, $end);
|
|
sleep(3); // consider rate limit
|
|
|
|
if ($result['code'] != 200) {
|
|
// $result['message'] = "Something went wrong while fetching free slots";
|
|
return $result;
|
|
continue;
|
|
}
|
|
$data = $result['data'];
|
|
// continue;
|
|
}
|
|
|
|
|
|
|
|
$data = empty($data) ? json_decode($response, true) : $data;
|
|
|
|
|
|
// return json_encode($data);
|
|
|
|
|
|
$stepSize = $eventTiming["slotInterval"];
|
|
|
|
$rslt = [];
|
|
|
|
if (!empty($data[$dayData['date']]["slots"])) {
|
|
|
|
foreach ($data[$dayData['date']]["slots"] as $time) {
|
|
$dateTime = new DateTime($time);
|
|
$dateTime->modify('+5 hours'); // Convert from UTC-5 to UTC/GMT
|
|
|
|
$rslt[] = $dateTime->format('H:i:s');
|
|
}
|
|
|
|
|
|
|
|
foreach ($slot->$dayName as $timeSlot) {
|
|
|
|
|
|
$slotStart = strtotime($timeSlot->from);
|
|
$slotEnd = strtotime($timeSlot->to);
|
|
|
|
$filteredSlots = filterTimeSlots($rslt, date("H:i:s", $slotStart), date("H:i:s", $slotEnd));
|
|
|
|
|
|
$totalPoints += (int)$timeSlot->point * count($filteredSlots);
|
|
|
|
/*
|
|
$range = extractRanges(date("H:i:s", $slotStart), date("H:i:s", $slotEnd), date("H:i:s", $serviceStart), date("H:i:s", $serviceEnd), $stepSize, $dayData['date']);
|
|
|
|
|
|
if (!$range) {
|
|
continue;
|
|
}
|
|
$intersection = array_intersect($rslt, $range);
|
|
if (empty($intersection)) {
|
|
continue;
|
|
}
|
|
foreach ($intersection as $intersect) {
|
|
$totalPoints += (int)$timeSlot->point;
|
|
// return $totalPoints;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// $totalPoints += intval($timeSlot->point) ?: 0;
|
|
}
|
|
}
|
|
|
|
// return json_encode(["derrr" => $der]);
|
|
}
|
|
|
|
return $totalPoints;
|
|
} |