get_all(); // Log the start of the script error_log('Cron job started: ' . date('Y-m-d H:i:s')); // Function to convert weeks or months to days 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 extractRanges($slotStart, $slotEnd, $serviceStart, $serviceEnd, $interval, $date) { // 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 calculateTotalPoints($daysToCheck, $slot, $service, $eventTiming, $schedule, $project, $ser_id) { // 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'; } $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']; } // error_log("counter" . json_encode($counter)); // error_log("skip" . json_encode($skip)); 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'), ]; } // error_log("daysToCheckIndices" . json_encode($daysToCheckIndices)); // error_log("daysToCheckIndices" . json_encode($daysToCheckData)); $totalPoints = 0; // Loop through the selected days and calculate total points $dayNames = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']; // foreach ($daysToCheckIndices as $dayIndex) { foreach ($daysToCheckData as $dayData) { // $dayName = $dayNames[$dayIndex]; // error_log("day" . $dayName); $dayIndex = $dayData['index']; $dayName = $dayNames[$dayIndex]; $date = $dayData['date']; error_log("day: $dayName, date: $date"); if (isset($slot->$dayName)) { if (!array_key_exists($dayName, $service)) { continue; // Day not found in the service schedule } foreach ($service[$dayName] as $ser) { $serviceStart = strtotime(sprintf("%02d:%02d", $ser["openHour"], $ser["openMinute"])); $serviceEnd = strtotime(sprintf("%02d:%02d", $ser["closeHour"], $ser["closeMinute"])); // Comparing service hours with slot hours // if ($serviceStart >= $slotStart && $serviceEnd <= $slotEnd) { // error_log("id" . $project->id); // error_log("slotStart" . date("H:i:s", $slotStart)); $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; $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); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { // error_log($response); $data = json_decode($response, true); $stepSize = $eventTiming["slotInterval"]; error_log("stepSize" . json_encode($stepSize)); $rslt = []; if (!empty($data[$dayData['date']]["slots"])) { foreach ($data[$dayData['date']]["slots"] as $time) { $dateTime = new DateTime($time); // while ($dateTime <= new DateTime($data[$dayData['date']]["slots"][1])) { $rslt[] = $dateTime->format('H:i:s'); // $dateTime->modify("+$stepSize minutes"); // } } foreach ($slot->$dayName as $timeSlot) { // Convert the day to a DateTime object for comparison // $currentDay = new DateTime($dayName); // Check if the day is after or equal to today. // if ($currentDay > $currentDate) { // error_log("currentDay" . $currentDay->format('Y-m-d H:i:s')); // foreach ($timeSlots as $timeSlot) { $slotStart = strtotime($timeSlot->from); $slotEnd = strtotime($timeSlot->to); $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']); // $intervals = generateTimeIntervals(date("H:i:s", $serviceStart), date("H:i:s", $serviceEnd), $eventTiming["slotInterval"], $dayData['date']); // $intervals2 = generateTimeIntervals(date("H:i:s", $slotStart), date("H:i:s", $slotEnd), $eventTiming["slotInterval"], $dayData['date']); error_log("slotStart " . date("H:i:s", $slotStart)); error_log("slotEnd " . date("H:i:s", $slotEnd)); error_log("serviceStart " . date("H:i:s", $serviceStart)); error_log("serviceEnd " . date("H:i:s", $serviceEnd)); // error_log("intervals " . json_encode($intervals)); // error_log("intervals2 " . json_encode($intervals2)); // error_log("slots " . json_encode($rslt)); error_log("range " . json_encode($range)); // $intersections = array_intersect($intervals, $intervals2); if (!$range) { continue; } $intersection = array_intersect($rslt, $range); if (empty($intersection)) { continue; } // error_log("intersections " . json_encode($intersections)); error_log("intersection " . json_encode($intersection)); foreach ($intersection as $intersect) { $totalPoints += (int)$timeSlot->point; } } error_log($totalPoints); } // error_log("start " . $start * 1000); // error_log("slotEnd" . date("Y-m-d H:i:s", $start)); // error_log("end " . $end * 1000); // error_log("slotStart " . $slotStart * 1000); // // error_log("slotEnd" . date("H:i:s", $slotEnd)); // error_log("slotEnd " . $slotEnd * 1000); // // error_log("serviceStart" . date("H:i:s", $serviceStart)); // error_log("serviceStart " . $serviceStart * 1000); // // error_log("serviceEnd" . date("H:i:s", $serviceEnd)); // error_log("serviceEnd " . $serviceEnd * 1000); // foreach ($intersections as $intersection) { // $totalPoints += (int)$timeSlot->point; // } // } } // } // } // $totalPoints += intval($timeSlot->point) ?: 0; } } } return $totalPoints; } function generateTimeIntervals($startTime, $endTime, $intervalMinutes, $date) { // $start = new DateTime($startTime); // $end = new DateTime($endTime); // $start = $date . ' ' . date("H:i:s", $startTime); // $end = $date . ' ' . date("H:i:s", $endTime); $start = new DateTime($date . ' ' . $startTime); $end = new DateTime($date . ' ' . $endTime); // error_log("start " . $start); // error_log("end " . $end); if ($end < $start) { $end->modify('+1 day'); } $intervalObj = new DateInterval("PT{$intervalMinutes}M"); // PT stands for 'Period Time' // Adjust end time to include it in the intervals // $end->add($intervalObj); $period = new DatePeriod($start, $intervalObj, $end); $intervals = array(); foreach ($period as $dt) { $intervals[] = $dt->format('H:i:s'); } return $intervals; } function checkServiceInSlot($service, $slot, $project, $eventTiming, $schedule, $ser_id) { $slotpoint = 0; // Get the current date $currentDate = new DateTime('now'); error_log("currentDate" . $currentDate->format('Y-m-d H:i:s')); if ($project->alert == 'On') { $slotpoint = calculateTotalPoints((int)$project->days, $slot, $service, $eventTiming, $schedule, $project, $ser_id); if ($slotpoint < (int)$project->score_threshold && $slotpoint != 0) { // Retrieve webhook URL and payload $webhookUrl = $project->webhook; // $webhookUrl = "https://hook.eu1.make.com/tcdowbyvjswiw6xnhxu8derehhyczfb4"; // $webhookUrl = "https://hook.eu1.make.com/otaauwkih0ojxa3bezs4gdg6dr8w7bpd"; if (filter_var($webhookUrl, FILTER_VALIDATE_URL)) { // echo json_validate($project->payload); $jsonData = json_decode($project->payload); // echo json_encode($project->payload); // echo gettype($project->payload); // echo gettype($jsonData); // error_log(gettype($jsonData)); // Check if decoding was successful // if (json_last_error() !== JSON_ERROR_NONE) { // echo json_last_error_msg(); // error_log('Error decoding JSON for project with ID ' . $project->id); // continue; // } // 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); // Check for cURL errors if (curl_errno($ch)) { error_log('Curl error for project with ID ' . $project->id . ': ' . curl_error($ch)); } else { // Log the webhook response $data = [ 'actual_score' => $slotpoint, ]; // Insert data into the database using LicenseModel $projectModel = new ProjectModel(); $projectModel->edit($data, $project->id); error_log('Webhook response for project with ID ' . $project->id . ': ' . $response); } // Close cURL session curl_close($ch); } else { error_log('Webhook for project with ID ' . $project->id . ' is not a URL '); } } else { $data = [ 'actual_score' => $slotpoint, ]; // Insert data into the database using LicenseModel $projectModel = new ProjectModel(); $projectModel->edit($data, $project->id); error_log("Point is higher than mininum point set"); } } else { // Log that no alert is set for the project error_log('No alert set for project with ID ' . $project->id); } } // $config = MkdConfig::get_instance()->get_config(); // $apikey = $config['gohighlevel_key']; // $cid = $_POST['calendar_id']; // $pid = (int)$_POST['project_id']; // Iterate through projects foreach ($projects as $project) { if (!empty($project->location)) { $apikey = $project->location; $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "https://rest.gohighlevel.com/v1/calendars/services", 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 " . $apikey, "Version: 2021-04-15" ], ]); $response = curl_exec($curl); $err = curl_error($curl); // error_log($response); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { // Check if the project has an alert set to 'Yes' $slots = json_decode($project->slot); // error_log($slotpoint); // error_log((int)$project->score_threshold); error_log(' '); // exit; $cid = $project->calendar; // Decode JSON string to PHP array $data = json_decode($response, true); // Search for the service with the specified ID $searchedService = null; foreach ($data['services'] as $service) { if ($service['id'] === $cid) { $searchedService = $service; break; } } // Output the result if ($searchedService !== null) { // echo json_encode($searchedService["availability"]["officeHours"]); $slots = json_decode($project->slot); // echo json_encode($slots); echo checkServiceInSlot($searchedService["availability"]["officeHours"], $slots, $project, $searchedService["availability"]["eventTiming"], $searchedService["availability"]["schedule"], $searchedService["id"]); } else { error_log("Service with ID '" . $cid . "' not found."); } } } else { error_log('Empty location api key'); } // Log the end of the script } error_log('Cron job completed: ' . date('Y-m-d H:i:s'));