= $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; }