* Copyright (C) 2006-2017 Laurent Destailleur * Copyright (C) 2009-2012 Regis Houssin * Copyright (C) 2023 anthony Berton * Copyright (C) 2024 MDW * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/public/bookcal/index.php * \ingroup core * \brief File to offer a way to book a rendez-vous into a public calendar * Example of URL: https://localhost/public/bookcal/index.php?id=... */ if (!defined('NOLOGIN')) { define("NOLOGIN", 1); // This means this output page does not require to be logged. } if (!defined('NOCSRFCHECK')) { define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. } if (!defined('NOBROWSERNOTIF')) { define('NOBROWSERNOTIF', '1'); } // Load Dolibarr environment require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/class/calendar.class.php'; require_once DOL_DOCUMENT_ROOT.'/bookcal/class/availabilities.class.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/public.lib.php'; // Security check if (!isModEnabled('bookcal')) { httponly_accessforbidden('Module Bookcal isn\'t enabled'); } /** * @var Conf $conf * @var DoliDB $db * @var Translate $langs */ $langs->loadLangs(array("main", "other", "dict", "agenda", "errors", "companies")); $action = GETPOST('action', 'aZ09'); $id = GETPOSTINT('id'); $id_availability = GETPOSTINT('id_availability'); $year = GETPOSTINT("year") ? GETPOSTINT("year") : idate("Y"); $month = GETPOSTINT("month") ? GETPOSTINT("month") : idate("m"); $week = GETPOSTINT("week") ? GETPOSTINT("week") : idate("W"); $day = GETPOSTINT("day") ? GETPOSTINT("day") : idate("d"); $dateselect = dol_mktime(0, 0, 0, GETPOSTINT('dateselectmonth'), GETPOSTINT('dateselectday'), GETPOSTINT('dateselectyear'), 'tzuserrel'); if ($dateselect > 0) { $day = GETPOSTINT('dateselectday'); $month = GETPOSTINT('dateselectmonth'); $year = GETPOSTINT('dateselectyear'); } $backtopage = GETPOST("backtopage", "alpha"); $object = new Calendar($db); $result = $object->fetch($id); $availability = new Availabilities($db); if ($id_availability > 0) { $result = $availability->fetch($id_availability); } $now = dol_now(); $nowarray = dol_getdate($now); $nowyear = $nowarray['year']; $nowmonth = $nowarray['mon']; $nowday = $nowarray['mday']; $prev = dol_get_prev_month($month, $year); $prev_year = $prev['year']; $prev_month = $prev['month']; $next = dol_get_next_month($month, $year); $next_year = $next['year']; $next_month = $next['month']; $max_day_in_prev_month = idate("t", dol_mktime(0, 0, 0, $prev_month, 1, $prev_year, 'gmt')); // Nb of days in previous month $max_day_in_month = idate("t", dol_mktime(0, 0, 0, $month, 1, $year)); // Nb of days in next month // tmpday is a negative or null cursor to know how many days before the 1st to show on month view (if tmpday=0, 1st is monday) $tmpday = - idate("w", dol_mktime(12, 0, 0, $month, 1, $year, 'gmt')) + 2; // idate('w') is 0 for sunday $tmpday += (getDolGlobalInt('MAIN_START_WEEK', 1) - 1); if ($tmpday >= 1) { $tmpday -= 7; // If tmpday is 0 we start with sunday, if -6, we start with monday of previous week. } // Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) $firstdaytoshow = dol_mktime(0, 0, 0, $prev_month, $max_day_in_prev_month + $tmpday, $prev_year, 'tzuserrel'); $next_day = 7 - ($max_day_in_month + 1 - $tmpday) % 7; if ($next_day < 6) { $next_day += 7; } $lastdaytoshow = dol_mktime(0, 0, 0, $next_month, $next_day, $next_year, 'tzuserrel'); $datechosen = GETPOST('datechosen', 'alpha'); $datetimechosen = GETPOSTINT('datetimechosen'); $isdatechosen = false; $timebooking = GETPOST("timebooking"); $datetimebooking = GETPOSTINT("datetimebooking"); $durationbooking = GETPOSTINT("durationbooking"); $errmsg = ''; /** * Show header for booking * * @param string $title Title * @param string $head Head array * @param int $disablejs More content into html header * @param int $disablehead More content into html header * @param string[]|string $arrayofjs Array of complementary js files * @param string[]|string $arrayofcss Array of complementary css files * @return void */ function llxHeaderVierge($title, $head = "", $disablejs = 0, $disablehead = 0, $arrayofjs = [], $arrayofcss = []) { global $conf, $langs, $mysoc; top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); // Show html headers print ''; $urllogo = ''; // Define urllogo if (getDolGlobalInt('BOOKCAL_SHOW_COMPANY_LOGO') || getDolGlobalString('BOOPKCAL_PUBLIC_INTERFACE_TOPIC')) { // Print logo if (getDolGlobalInt('BOOKCAL_SHOW_COMPANY_LOGO')) { $urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png'; if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) { $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$mysoc->logo_small); } elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) { $urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$mysoc->logo); } elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) { $urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg'; } } } print '
'; // Output html code for logo print '
'; print '
'; if ($urllogo) { print ''; print ''; print ''; } if (getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) { print '
'.(getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') ? getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC') : $langs->trans("BookCalSystem")).''; } if (empty($urllogo) && ! getDolGlobalString('BOOKCAL_PUBLIC_INTERFACE_TOPIC')) { print $mysoc->name; } print '
'; if (!getDolGlobalInt('MAIN_HIDE_POWERED_BY')) { print ''; } print '
'; print '
'; print '
'; } /* * Actions */ if ($action == 'add' ) { // Test on permission not required here (anonymous action protected by mitigation of /public/... urls) $error = 0; $idcontact = 0; $calendar = $object; $contact = new Contact($db); $actioncomm = new ActionComm($db); $nb_post_max = getDolGlobalInt("MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS", 200); if (!is_object($user)) { $user = new User($db); } $db->begin(); if (!GETPOST("lastname")) { $error++; $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Lastname"))."
\n"; } if (!GETPOST("firstname")) { $error++; $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Firstname"))."
\n"; } if (!GETPOST("email")) { $error++; $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Email"))."
\n"; } if (!$error) { $sql = "SELECT s.rowid"; $sql .= " FROM ".MAIN_DB_PREFIX."socpeople as s"; $sql .= " WHERE s.lastname = '".$db->escape(GETPOST("lastname"))."'"; $sql .= " AND s.firstname = '".$db->escape(GETPOST("firstname"))."'"; $sql .= " AND s.email = '".$db->escape(GETPOST("email"))."'"; $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); if ($num > 0) { $obj = $db->fetch_object($resql); $idcontact = $obj->rowid; $contact->fetch($idcontact); } else { $contact->lastname = GETPOST("lastname"); $contact->firstname = GETPOST("firstname"); $contact->email = GETPOST("email"); $contact->ip = getUserRemoteIP(); if (checkNbPostsForASpeceificIp($contact, $nb_post_max) <= 0) { $error++; $errmsg .= implode('
', $contact->errors); } else { $result = $contact->create($user); if ($result < 0) { $error++; $errmsg .= $contact->error." ".implode(',', $contact->errors); } } } } else { $error++; $errmsg .= $db->lasterror(); } } if (!$error) { $dateend = dol_time_plus_duree(GETPOSTINT("datetimebooking"), GETPOSTINT("durationbooking"), 'i'); $actioncomm->label = $langs->trans("BookcalBookingTitle"); $actioncomm->type = 'AC_RDV'; $actioncomm->type_id = 5; $actioncomm->datep = GETPOSTINT("datetimebooking"); $actioncomm->datef = $dateend; $actioncomm->note_private = GETPOST("description"); $actioncomm->percentage = -1; $actioncomm->fk_bookcal_calendar = $id; $actioncomm->userownerid = $calendar->visibility; $actioncomm->contact_id = $contact->id; $actioncomm->socpeopleassigned = [ $contact->id => [ 'id' => $contact->id, 'mandatory' => 0, 'answer_status' => 0, 'transparency' =>0, ] ]; $actioncomm->ip = getUserRemoteIP(); if (checkNbPostsForASpeceificIp($actioncomm, $nb_post_max) <= 0) { $error++; $errmsg .= implode('
', $actioncomm->errors); } else { $result = $actioncomm->create($user); if ($result < 0) { $error++; $errmsg .= $actioncomm->error." ".implode(',', $actioncomm->errors); } } } if (!$error) { $db->commit(); $action = 'afteradd'; } else { $db->rollback(); $action = 'create'; } } /* * View */ $form = new Form($db); llxHeaderVierge('BookingCalendar'); print '

'.(!empty($object->label) ? $object->label : $object->ref).'

'; dol_htmloutput_errors($errmsg); if ($action == 'create') { $backtopage = $_SERVER["PHP_SELF"].'?id='.$id.'&datechosen='.$datechosen; } else { $backtopage = DOL_URL_ROOT.'/public/bookcal/index.php?id='.$id; } //print '
'; print '
'; print '
'; if ($action == 'afteradd') { print '

'; print $langs->trans("BookingSuccessfullyBooked"); print '

'; print $langs->trans("BookingReservationHourAfter", dol_print_date(GETPOSTINT("datetimebooking"), "dayhourtext")); } else { $param = ''; print ''; print ''; print ''; print ''; print ''; print ''; if ($action == "create") { print ''; print ''; } else { print ''; print ''; } print ''; print '
'; if ($action != 'create') { print '
'; print ''; $nav = '  '."\n"; $nav .= ' '.dol_print_date(dol_mktime(0, 0, 0, $month, 1, $year), "%b %Y"); $nav .= " \n"; $nav .= '   '."\n"; if (empty($conf->dol_optimize_smallscreen)) { $nav .= '   '.$langs->trans("Today").' '; } $nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0); $nav .= ''; print $nav; print '
'; } print '
'; print ''; print '
'; if (empty($datetimebooking)) { $timebookingarray = explode(" - ", $timebooking); $timestartarray = explode(":", $timebookingarray[0]); $timeendarray = explode(":", $timebookingarray[1]); $datetimebooking = dol_time_plus_duree($datetimechosen, intval($timestartarray[0]), "h"); $datetimebooking = dol_time_plus_duree($datetimebooking, intval($timestartarray[1]), "i"); } print ''.img_picto("", "calendar")." ".dol_print_date($datetimebooking, 'dayhourtext').''; print ''; print ''; print '
'; print ''."\n"; print ''; print ''; print ''; print ''; print ''; print ''; // Lastname print ''."\n"; // Firstname print ''."\n"; // EMail print ''."\n"; // Comments print ''; print ''; print ''."\n"; print '
'; print $langs->trans("Message"); print '
'."\n"; print '
'; print ''; print '
'; print '
'; print '
'; print ''; print ' '; // Column title of weeks numbers print ' '; $i = 0; while ($i < 7) { $numdayinweek = (($i + (isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : 1)) % 7); if (!empty($conf->dol_optimize_smallscreen)) { print ' '."\n"; } else { print ' '."\n"; } $i++; } print ' '."\n"; $todayarray = dol_getdate($now, true); $todaytms = dol_mktime(0, 0, 0, $todayarray['mon'], $todayarray['mday'], $todayarray['year']); // Load into an array all days with availabilities of the calendar for the current month $todayarray['mon'] and $todayarray['year'] $arrayofavailabledays = array(); $arrayofavailabilities = $availability->fetchAll('', '', 0, 0, '(status:=:1) AND (fk_bookcal_calendar:=:'.((int) $id).')'); if ($arrayofavailabilities < 0) { setEventMessages($availability->error, $availability->errors, 'errors'); } else { foreach ($arrayofavailabilities as $key => $value) { $startarray = dol_getdate($value->start); $endarray = dol_getdate($value->end); for ($i = $startarray['mday']; $i <= $endarray['mday']; $i++) { if ($todayarray['mon'] >= $startarray['mon'] && $todayarray['mon'] <= $endarray['mon']) { $arrayofavailabledays[dol_mktime(0, 0, 0, $todayarray['mon'], $i, $todayarray['year'])] = dol_mktime(0, 0, 0, $todayarray['mon'], $i, $todayarray['year']); } } } } for ($iter_week = 0; $iter_week < 6; $iter_week++) { echo " \n"; // Get date of the current day, format 'yyyy-mm-dd' if ($tmpday <= 0) { // If number of the current day is in previous month $currdate0 = sprintf("%04d", $prev_year).sprintf("%02d", $prev_month).sprintf("%02d", $max_day_in_prev_month + $tmpday); } elseif ($tmpday <= $max_day_in_month) { // If number of the current day is in current month $currdate0 = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $tmpday); } else {// If number of the current day is in next month $currdate0 = sprintf("%04d", $next_year).sprintf("%02d", $next_month).sprintf("%02d", $tmpday - $max_day_in_month); } // Get week number for the targeted date '$currdate0' $numweek0 = idate("W", strtotime(date($currdate0))); // Show the week number, and define column width echo ' '; for ($iter_day = 0; $iter_day < 7; $iter_day++) { if ($tmpday <= 0) { /* Show days before the beginning of the current month (previous month) */ $style = 'cal_other_month cal_past'; if ($iter_day == 6) { $style .= ' cal_other_month_right'; } echo ' \n"; } elseif ($tmpday <= $max_day_in_month) { /* Show days of the current month */ $curtime = dol_mktime(0, 0, 0, $month, $tmpday, $year); $style = 'cal_current_month'; if ($iter_day == 6) { $style .= ' cal_current_month_right'; } $today = 0; if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $month && $todayarray['year'] == $year) { $today = 1; } //var_dump($curtime); var_dump($todaytms); var_dump($arrayofavailabledays); if ($curtime > $todaytms && in_array($curtime, $arrayofavailabledays)) { $style .= ' cal_available cursorpointer'; } if ($curtime < $todaytms) { $style .= ' cal_past'; } $dateint = sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $tmpday); if (!empty(explode('dayevent_', $datechosen)[1]) && explode('dayevent_', $datechosen)[1] == $dateint) { $style .= ' cal_chosen'; $isdatechosen = true; } echo ' \n"; } else { /* Show days after the current month (next month) */ $style = 'cal_other_month'; if ($iter_day == 6) { $style .= ' cal_other_month_right'; } echo ' \n"; } $tmpday++; } echo " \n"; } print '
#'; $labelshort = array(0 => 'SundayMin', 1 => 'MondayMin', 2 => 'TuesdayMin', 3 => 'WednesdayMin', 4 => 'ThursdayMin', 5 => 'FridayMin', 6 => 'SaturdayMin'); print $langs->trans($labelshort[$numdayinweek]); print ' '; //$labelshort = array(0=>'SundayMin', 1=>'MondayMin', 2=>'TuesdayMin', 3=>'WednesdayMin', 4=>'ThursdayMin', 5=>'FridayMin', 6=>'SaturdayMin'); $labelshort = array(0 => 'Sunday', 1 => 'Monday', 2 => 'Tuesday', 3 => 'Wednesday', 4 => 'Thursday', 5 => 'Friday', 6 => 'Saturday'); print $langs->trans($labelshort[$numdayinweek]); print '
'.$numweek0.''; show_bookcal_day_events($max_day_in_prev_month + $tmpday, $prev_month, $prev_year); echo " '; show_bookcal_day_events($tmpday, $month, $year, $today); echo "'; show_bookcal_day_events($tmpday - $max_day_in_month, $next_month, $next_year); echo "
'; print '
'; // Column visible after selection of a day print '
'; print '
'; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print '
'; print '





'.$langs->trans("SelectADay").'
'; print '
'; print '
'; print '
'; print '
'; print '
'; print '
'; print '
'; print ''; } llxFooter('', 'public'); /** * Show event of a particular day * * @param int $day Day * @param int $month Month * @param int $year Year * @param int $today Today's day * @return void */ function show_bookcal_day_events($day, $month, $year, $today = 0) { global $conf; if ($conf->use_javascript_ajax) { // Enable the "Show more button..." $conf->global->MAIN_JS_SWITCH_AGENDA = 1; } $dateint = sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day); $eventdatetime = dol_mktime(-1, -1, -1, $month, $day, $year); //print 'show_bookcal_day_events day='.$day.' month='.$month.' year='.$year.' dateint='.$dateint; print "\n"; $curtime = dol_mktime(0, 0, 0, $month, $day, $year); // Line with title of day print '
'."\n"; print dol_print_date($curtime, '%d'); print '
'; if ($today) { print img_picto('today', 'fontawesome_circle_fas_black_7px'); } else { print '
'; } print '
'; // table print "\n"; }