dolibarr 25.0.0-alpha
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2003 Eric Seigne <erics@rycks.com>
4 * Copyright (C) 2004-2018 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
8 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2017 Open-DSI <support@open-dsi.fr>
10 * Copyright (C) 2021-2026 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
12 * Copyright (C) 2026 Anthony Berton <anthony.berton@bb2a.fr>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
28
35// Load Dolibarr environment
36require '../../main.inc.php';
44require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
45require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
46require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
47require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
48require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php';
49require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
50require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
51
52$MAXAGENDA = getDolGlobalString('AGENDA_EXT_NB', 6);
53$DELAYFORCACHE = 300; // 300 seconds
54
55$action = GETPOST('action', 'aZ09');
56$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
57$mode = GETPOST('mode', 'aZ09');
58if (empty($mode) && preg_match('/show_/', $action)) {
59 $mode = $action; // For backward compatibility
60}
61
62$disabledefaultvalues = GETPOSTINT('disabledefaultvalues');
63
64$check_holiday = GETPOSTINT('check_holiday');
65$check_birthday = !empty($conf->use_javascript_ajax) ? GETPOSTINT("check_birthday") : 1;
66$filter = GETPOST("search_filter", 'alpha', 3) ? GETPOST("search_filter", 'alpha', 3) : GETPOST("filter", 'alpha', 3);
67$filtert = GETPOST("search_filtert", "intcomma", 3) ? GETPOST("search_filtert", "intcomma", 3) : GETPOST("filtert", "intcomma", 3);
68$usergroup = GETPOST("search_usergroup", "intcomma", 3) ? GETPOST("search_usergroup", "intcomma", 3) : GETPOST("usergroup", "intcomma", 3);
69$usergroupids = array_map('intval', array_filter(explode(',', $usergroup)));
70$search_categ_cus = GETPOST("search_categ_cus", 'intcomma', 3) ? GETPOST("search_categ_cus", 'intcomma', 3) : 0;
71
72// If no choice done on calendar owner (like on left menu link "Agenda"), we filter on current user by default.
73if (empty($filtert) && !getDolGlobalString('AGENDA_ALL_CALENDARS')) {
74 $filtert = (string) $user->id;
75}
76if (empty($filtert)) {
77 $filtert = -1;
78}
79
80$newparam = '';
81
82// Pagination parameters
83$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
84$sortfield = GETPOST('sortfield', 'aZ09comma');
85$sortorder = GETPOST('sortorder', 'aZ09comma');
86$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
87if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
88 // If $page is not defined, or '' or -1 or if we click on clear filters
89 $page = 0;
90}
91$offset = $limit * $page;
92if (!$sortorder) {
93 $sortorder = "ASC";
94}
95if (!$sortfield) {
96 $sortfield = "a.datec";
97}
98
99// Security check
100$socid = GETPOSTINT("search_socid") ? GETPOSTINT("search_socid") : GETPOSTINT("socid");
101if ($user->socid) {
102 $socid = $user->socid;
103}
104if ($socid < 0) {
105 $socid = '';
106}
107
108$canedit = 1;
109if (!$user->hasRight('agenda', 'myactions', 'read')) {
111}
112if (!$user->hasRight('agenda', 'allactions', 'read')) {
113 $canedit = 0;
114}
115if (!$user->hasRight('agenda', 'allactions', 'read') || $filter == 'mine') { // If no permission to see all, we show only affected to me
116 $filtert = (string) $user->id;
117}
118
119$resourceid = GETPOSTINT("search_resourceid");
120$year = GETPOSTINT("year") ? GETPOSTINT("year") : date("Y");
121$month = GETPOSTINT("month") ? GETPOSTINT("month") : date("m");
122$week = GETPOSTINT("week") ? GETPOSTINT("week") : date("W");
123$day = GETPOSTINT("day") ? GETPOSTINT("day") : date("d");
124$pid = GETPOSTISSET("search_projectid") ? GETPOSTINT("search_projectid", 3) : GETPOSTINT("projectid", 3);
125$status = GETPOSTISSET("search_status") ? GETPOST("search_status", 'aZ09') : GETPOST("status", 'aZ09'); // status may be 0, 50, 100, 'todo', 'na' or -1
126$type = GETPOSTISSET("search_type") ? GETPOST("search_type", 'aZ09') : GETPOST("type", 'aZ09');
127$maxprint = GETPOSTISSET("maxprint") ? GETPOSTINT("maxprint") : getDolGlobalInt('AGENDA_MAX_EVENTS_DAY_VIEW', 3);
128
129$dateselect = dol_mktime(0, 0, 0, GETPOSTINT('dateselectmonth'), GETPOSTINT('dateselectday'), GETPOSTINT('dateselectyear'));
130if ($dateselect > 0) {
131 $day = GETPOSTINT('dateselectday');
132 $month = GETPOSTINT('dateselectmonth');
133 $year = GETPOSTINT('dateselectyear');
134}
135
136// Set actioncode (this code must be same for setting actioncode into peruser, listacton and index)
137if (GETPOST('search_actioncode', 'array:aZ09')) {
138 $actioncode = GETPOST('search_actioncode', 'array:aZ09', 3);
139 if (!count($actioncode)) {
140 $actioncode = '0';
141 }
142} else {
143 $actioncode = GETPOST("search_actioncode", "alpha", 3) ? GETPOST("search_actioncode", "alpha", 3) : (GETPOST("search_actioncode") == '0' ? '0' : ((!getDolGlobalString('AGENDA_DEFAULT_FILTER_TYPE') || $disabledefaultvalues) ? '' : getDolGlobalString('AGENDA_DEFAULT_FILTER_TYPE')));
144}
145if (is_scalar($actioncode) && $actioncode == '-1') {
146 $actioncode = '';
147}
148
149if ($status == '' && !GETPOSTISSET('search_status')) {
150 $status = ((!getDolGlobalString('AGENDA_DEFAULT_FILTER_STATUS') || $disabledefaultvalues) ? '' : getDolGlobalString('AGENDA_DEFAULT_FILTER_STATUS'));
151}
152
153$defaultview = getDolGlobalString('AGENDA_DEFAULT_VIEW', 'show_month'); // default for app
154$defaultview = getDolUserString('AGENDA_DEFAULT_VIEW', $defaultview); // default for user
155if (empty($mode) && !GETPOSTISSET('mode')) {
156 $mode = $defaultview;
157}
158if ($mode == 'default') { // When action is default, we want a calendar view and not the list
159 $mode = (($defaultview != 'show_list') ? $defaultview : 'show_month');
160}
161// View by month
162if (GETPOST('viewcal') && GETPOST('mode') != 'show_day' && GETPOST('mode') != 'show_week') {
163 $mode = 'show_month';
164 $day = '';
165}
166// View by week
167if (GETPOST('viewweek') || GETPOST('mode') == 'show_week') {
168 $mode = 'show_week';
169 $week = ($week ? $week : date("W"));
170 $day = ($day ? $day : date("d"));
171}
172// View by day
173if (GETPOST('viewday') || GETPOST('mode') == 'show_day') {
174 $mode = 'show_day';
175 $day = ($day ? $day : date("d"));
176}
177
178$object = new ActionComm($db);
179
180// Load translation files required by the page
181$langs->loadLangs(array('agenda', 'other', 'commercial'));
182
183// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
184$hookmanager->initHooks(array('agenda'));
185
186$result = restrictedArea($user, 'agenda', 0, 'actioncomm&societe', 'myactions|allactions', 'fk_soc', 'id');
187if ($user->socid && $socid) {
188 $result = restrictedArea($user, 'societe', $socid);
189}
190
191require_once DOL_DOCUMENT_ROOT.'/core/redirect_if_setup_not_complete.inc.php';
192
193
194/*
195 * Actions
196 */
197
198if (GETPOST("viewlist", 'alpha') || $mode == 'show_list') {
199 $param = '';
200 if (is_array($_POST)) {
201 foreach ($_POST as $key => $val) {
202 if ($key == 'token') {
203 continue;
204 }
205 $param .= '&'.urlencode($key).'='.urlencode($val);
206 }
207 }
208 if (!preg_match('/action=/', $param)) {
209 $param .= ($param ? '&' : '').'mode=show_list';
210 }
211 //print $param;
212 header("Location: ".DOL_URL_ROOT.'/comm/action/list.php?'.$param);
213 exit;
214}
215
216if (GETPOST("viewperuser", 'alpha') || $mode == 'show_peruser') {
217 $param = '';
218 if (is_array($_POST)) {
219 foreach ($_POST as $key => $val) {
220 if ($key == 'token') {
221 continue;
222 }
223 $param .= '&'.urlencode($key).'='.urlencode($val);
224 }
225 }
226 //print $param;
227 header("Location: ".DOL_URL_ROOT.'/comm/action/peruser.php?'.$param);
228 exit;
229}
230
231
232/*
233 * View
234 */
235
236$parameters = array(
237 'socid' => $socid,
238 'status' => $status,
239 'year' => $year,
240 'month' => $month,
241 'day' => $day,
242 'type' => $type,
243 'maxprint' => $maxprint,
244 'filter' => $filter,
245 'filtert' => $filtert,
246 'showbirthday' => $check_birthday,
247 'canedit' => $canedit,
248 'optioncss' => $optioncss,
249 'actioncode' => $actioncode,
250 'pid' => $pid,
251 'resourceid' => $resourceid,
252 'usergroup' => $usergroup,
253);
254$reshook = $hookmanager->executeHooks('beforeAgenda', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
255if ($reshook < 0) {
256 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
257}
258
259$form = new Form($db);
260$companystatic = new Societe($db);
261$contactstatic = new Contact($db);
262$userstatic = new User($db);
263
264$help_url = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:M&oacute;dulo_Agenda|DE:Modul_Terminplanung';
265llxHeader('', $langs->trans("Agenda"), $help_url);
266
267$now = dol_now();
268$nowarray = dol_getdate($now);
269$nowyear = $nowarray['year'];
270$nowmonth = $nowarray['mon'];
271$nowday = $nowarray['mday'];
272
273$listofextcals = array();
274
275// Define list of external calendars (global admin setup)
276$i = 0;
277while ($i < $MAXAGENDA) {
278 $i++;
279 $source = 'AGENDA_EXT_SRC'.$i;
280 $name = 'AGENDA_EXT_NAME'.$i;
281 $offsettz = 'AGENDA_EXT_OFFSETTZ'.$i;
282 $color = 'AGENDA_EXT_COLOR'.$i;
283 $enabled = 'AGENDA_EXT_ENABLED'.$i;
284 $default = 'AGENDA_EXT_ACTIVEBYDEFAULT'.$i;
285 $buggedfile = 'AGENDA_EXT_BUGGEDFILE'.$i;
286 if (getDolGlobalString($source) && getDolGlobalString($name) && getDolGlobalString($enabled)) {
287 // Note: $conf->global->buggedfile can be empty or 'uselocalandtznodaylight' or 'uselocalandtzdaylight'
288 $listofextcals[] = array(
289 'type' => 'globalsetup',
290 'src' => getDolGlobalString($source),
292 'offsettz' => (int) getDolGlobalInt($offsettz, 0),
293 'color' => dol_string_nohtmltag(getDolGlobalString($color)),
294 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
295 'default' => dol_string_nohtmltag(getDolGlobalString($default)),
296 'buggedfile' => dol_string_nohtmltag(getDolGlobalString('buggedfile', ''))
297 );
298 }
299}
300
301// Define list of external calendars (user setup)
302$i = 0;
303while ($i < $MAXAGENDA) {
304 $i++;
305 $source = 'AGENDA_EXT_SRC_'.$user->id.'_'.$i;
306 $name = 'AGENDA_EXT_NAME_'.$user->id.'_'.$i;
307 $offsettz = 'AGENDA_EXT_OFFSETTZ_'.$user->id.'_'.$i;
308 $color = 'AGENDA_EXT_COLOR_'.$user->id.'_'.$i;
309 $enabled = 'AGENDA_EXT_ENABLED_'.$user->id.'_'.$i;
310 $default = 'AGENDA_EXT_ACTIVEBYDEFAULT_'.$user->id.'_'.$i;
311 $buggedfile = 'AGENDA_EXT_BUGGEDFILE_'.$user->id.'_'.$i;
312
313 if (getDolUserString($source) && getDolUserString($name)) {
314 // Note: $conf->global->buggedfile can be empty or 'uselocalandtznodaylight' or 'uselocalandtzdaylight'
315 $listofextcals[] = array(
316 'type' => 'usersetup',
317 'src' => getDolUserString($source),
318 'name' => dol_string_nohtmltag(getDolUserString($name)),
319 'offsettz' => (int) (empty($user->conf->$offsettz) ? 0 : $user->conf->$offsettz),
320 'color' => dol_string_nohtmltag(getDolUserString($color)),
321 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
322 'default' => dol_string_nohtmltag(getDolUserString($default)),
323 'buggedfile' => dol_string_nohtmltag(isset($user->conf->buggedfile) ? $user->conf->buggedfile : '')
324 );
325 }
326}
327
328$firstdaytoshow = 0;
329$max_day_in_month = 0;
330$lastdaytoshow = 0;
331$tmpday = 0;
332$datestart = 0;
333$dateend = 0;
334$first_day = 0;
335$first_month = 0;
336$first_year = 0;
337$prev_day = 0;
338$prev_month = 0;
339$prev_year = 0;
340$max_day_in_prev_month = 0;
341$next_day = 0;
342$next_month = 0;
343$next_year = 0;
344if (empty($mode) || $mode == 'show_month') {
345 $prev = dol_get_prev_month($month, $year);
346 $prev_year = $prev['year'];
347 $prev_month = $prev['month'];
348 $next = dol_get_next_month($month, $year);
349 $next_year = $next['year'];
350 $next_month = $next['month'];
351
352 $max_day_in_prev_month = (int) date("t", dol_mktime(12, 0, 0, $prev_month, 1, $prev_year, 'gmt')); // Nb of days in previous month
353 $max_day_in_month = (int) date("t", dol_mktime(12, 0, 0, $month, 1, $year, 'gmt')); // Nb of days in next month
354 // 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)
355 $tmpday = - (int) date("w", dol_mktime(12, 0, 0, $month, 1, $year, 'gmt')) + 2; // date('w') is 0 for sunday
356 $tmpday += (getDolGlobalInt('MAIN_START_WEEK', 1) - 1);
357 if ($tmpday >= 1) {
358 $tmpday -= 7; // If tmpday is 0 we start with sunday, if -6, we start with monday of previous week.
359 }
360 // Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1)
361 $firstdaytoshow = dol_mktime(0, 0, 0, $prev_month, $max_day_in_prev_month + $tmpday, $prev_year, 'tzuserrel');
362 $next_day = 7 - ($max_day_in_month + 1 - $tmpday) % 7;
363 if ($next_day < 6) {
364 $next_day += 7;
365 }
366 $lastdaytoshow = dol_mktime(0, 0, 0, $next_month, $next_day, $next_year, 'tzuserrel');
367}
368if ($mode == 'show_week') {
369 $prev = dol_get_first_day_week($day, $month, $year);
370 $prev_year = $prev['prev_year'];
371 $prev_month = $prev['prev_month'];
372 $prev_day = $prev['prev_day'];
373 $first_day = $prev['first_day'];
374 $first_month = $prev['first_month'];
375 $first_year = $prev['first_year'];
376
377 $week = $prev['week'];
378
379 $day = (int) $day;
380 $next = dol_get_next_week($first_day, (int) $week, $first_month, $first_year);
381 $next_year = $next['year'];
382 $next_month = $next['month'];
383 $next_day = $next['day'];
384
385 // Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1)
386 $firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'tzuserrel');
387 $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, 7, 'd');
388
389 $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt'));
390
391 $tmpday = $first_day;
392}
393if ($mode == 'show_day') {
394 $prev = dol_get_prev_day($day, $month, $year);
395 $prev_year = $prev['year'];
396 $prev_month = $prev['month'];
397 $prev_day = $prev['day'];
398 $next = dol_get_next_day($day, $month, $year);
399 $next_year = $next['year'];
400 $next_month = $next['month'];
401 $next_day = $next['day'];
402 // Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1)
403 $firstdaytoshow = dol_mktime(0, 0, 0, $prev_month, $prev_day, $prev_year, 'tzuserrel');
404 $lastdaytoshow = dol_mktime(0, 0, 0, $next_month, $next_day, $next_year, 'tzuserrel');
405}
406//print 'xx'.$prev_year.'-'.$prev_month.'-'.$prev_day;
407//print 'xx'.$next_year.'-'.$next_month.'-'.$next_day;
408//print dol_print_date($firstdaytoshow,'dayhour').' '.dol_print_date($lastdaytoshow,'dayhour');
409
410/*$title = $langs->trans("DoneAndToDoActions");
411if ($status == 'done') {
412 $title = $langs->trans("DoneActions");
413}
414if ($status == 'todo') {
415 $title = $langs->trans("ToDoActions");
416}
417*/
418
419$param = '';
420if (($actioncode && $actioncode !== '-1') || GETPOSTISSET('search_actioncode')) {
421 if (is_array($actioncode)) {
422 foreach ($actioncode as $str_action) {
423 if ($str_action != '-1') {
424 $param .= "&search_actioncode[]=".urlencode($str_action);
425 }
426 }
427 } else {
428 $param .= "&search_actioncode=".urlencode($actioncode);
429 }
430}
431if ($resourceid > 0) {
432 $param .= "&search_resourceid=".urlencode((string) ($resourceid));
433}
434if ($status || GETPOSTISSET('status') || GETPOSTISSET('search_status')) {
435 $param .= "&search_status=".urlencode($status);
436}
437if ($filter) {
438 $param .= "&search_filter=".urlencode((string) $filter);
439}
440if ($filtert) {
441 $param .= "&search_filtert=".urlencode((string) $filtert);
442}
443if ($usergroup > 0) {
444 $param .= "&search_usergroup=".urlencode((string) ($usergroup));
445}
446if ($socid > 0) {
447 $param .= "&search_socid=".urlencode((string) ($socid));
448}
449if ($check_birthday) {
450 $param .= "&check_birthday=1";
451}
452if ($check_holiday) {
453 $param .= "&check_holiday=1";
454}
455if ($pid) {
456 $param .= "&search_projectid=".urlencode((string) ($pid));
457}
458if ($type) {
459 $param .= "&search_type=".urlencode($type);
460}
461$param .= "&maxprint=".urlencode((string) ($maxprint));
462if ($mode == 'show_day' || $mode == 'show_week' || $mode == 'show_month') {
463 $param .= '&mode='.urlencode($mode);
464}
465if ($search_categ_cus != 0) {
466 $param .= '&search_categ_cus='.urlencode((string) ($search_categ_cus));
467}
468if ($check_holiday) {
469 $param .= '&check_holiday=1';
470}
471
472// Show navigation bar
473$nav = '';
474$nav .= '<div class="navselectiondate inline-block nowraponall">';
475if (empty($mode) || $mode == 'show_month') {
476 $nav .= "<a href=\"?year=".$prev_year."&month=".$prev_month.$param."\"><i class=\"fa fa-chevron-left\"></i></a> &nbsp;\n";
477 $nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $month, 1, $year), "%b %Y");
478 $nav .= " </span>\n";
479 $nav .= " &nbsp; <a href=\"?year=".$next_year."&month=".$next_month.$param."\"><i class=\"fa fa-chevron-right\"></i></a>\n";
480 $picto = 'calendar';
481}
482if ($mode == 'show_week') {
483 $nav .= "<a href=\"?year=".$prev_year."&month=".$prev_month."&day=".$prev_day.$param."\"><i class=\"fa fa-chevron-left\" title=\"".dol_escape_htmltag($langs->trans("Previous"))."\"></i></a> &nbsp;\n";
484 $nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $first_month, $first_day, $first_year), "%Y").", ".$langs->trans("WeekShort")." ".$week;
485 $nav .= " </span>\n";
486 $nav .= " &nbsp; <a href=\"?year=".$next_year."&month=".$next_month."&day=".$next_day.$param."\"><i class=\"fa fa-chevron-right\" title=\"".dol_escape_htmltag($langs->trans("Next"))."\"></i></a>\n";
487 $picto = 'calendarweek';
488}
489if ($mode == 'show_day') {
490 $nav .= "<a href=\"?year=".$prev_year."&month=".$prev_month."&day=".$prev_day.$param."\"><i class=\"fa fa-chevron-left\"></i></a> &nbsp;\n";
491 $nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "daytextshort");
492 $nav .= " </span>\n";
493 $nav .= " &nbsp; <a href=\"?year=".$next_year."&month=".$next_month."&day=".$next_day.$param."\"><i class=\"fa fa-chevron-right\"></i></a>\n";
494 $picto = 'calendarday';
495}
496if (empty($conf->dol_optimize_smallscreen)) {
497 $nav .= ' <a href="?year='.$nowyear.'&month='.$nowmonth.'&day='.$nowday.$param.'" class="datenowlink marginleftonly marginrightonly">'.$langs->trans("Today").'</a> ';
498}
499$nav .= '</div>';
500
501$nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0);
502//$nav .= ' <input type="submit" class="button button-save" name="submitdateselect" value="'.$langs->trans("Refresh").'">';
503$nav .= '<button type="submit" class="liste_titre button_search valignmiddle" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
504
505// Must be after the nav definition
506$paramnodate = $param;
507$param .= '&year='.$year.'&month='.$month.($day ? '&day='.$day : '');
508//print 'x'.$param;
509
510
511
512
513/*$tabactive = '';
514 if ($mode == 'show_month') $tabactive = 'cardmonth';
515 if ($mode == 'show_week') $tabactive = 'cardweek';
516 if ($mode == 'show_day') $tabactive = 'cardday';
517 if ($mode == 'show_list') $tabactive = 'cardlist';
518 if ($mode == 'show_pertuser') $tabactive = 'cardperuser';
519 if ($mode == 'show_pertype') $tabactive = 'cardpertype';
520 */
521
522$paramnoaction = preg_replace('/mode=[a-z_]+/', '', preg_replace('/action=[a-z_]+/', '', $param));
523$paramnoactionodate = preg_replace('/mode=[a-z_]+/', '', preg_replace('/action=[a-z_]+/', '', $paramnodate));
524
525$head = calendars_prepare_head($paramnoaction);
526
527print '<form method="POST" id="searchFormList" class="listactionsfilter" action="'.$_SERVER["PHP_SELF"].'">'."\n";
528if ($optioncss != '') {
529 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
530}
531print '<input type="hidden" name="token" value="'.newToken().'">';
532print '<input type="hidden" name="mode" value="'.$mode.'">';
533
534
535$viewmode = '<div class="navmode inline-block">';
536
537$viewmode .= '<a class="btnTitle'.($mode == 'list' ? ' btnTitleSelected' : '').' reposition" href="'.DOL_URL_ROOT.'/comm/action/list.php?mode=show_list&restore_lastsearch_values=1'.$paramnoactionodate.'">';
538//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
539$viewmode .= img_picto($langs->trans("List"), 'object_calendarlist', 'class="imgforviewmode pictoactionview block"');
540//$viewmode .= '</span>';
541$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewList").'</span></a>';
542
543$viewmode .= '<a class="btnTitle'.($mode == 'show_month' ? ' btnTitleSelected' : '').' reposition" href="'.DOL_URL_ROOT.'/comm/action/index.php?mode=show_month&year='.(isset($object->datep) ? dol_print_date($object->datep, '%Y') : $year).'&month='.(isset($object->datep) ? dol_print_date($object->datep, '%m') : $month).'&day='.(isset($object->datep) ? dol_print_date($object->datep, '%d') : $day).$paramnoactionodate.'">';
544//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
545$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="pictoactionview block"');
546//$viewmode .= '</span>';
547$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewCal").'</span></a>';
548
549$viewmode .= '<a class="btnTitle'.($mode == 'show_week' ? ' btnTitleSelected' : '').' reposition" href="'.DOL_URL_ROOT.'/comm/action/index.php?mode=show_week&year='.(isset($object->datep) ? dol_print_date($object->datep, '%Y') : $year).'&month='.(isset($object->datep) ? dol_print_date($object->datep, '%m') : $month).'&day='.(isset($object->datep) ? dol_print_date($object->datep, '%d') : $day).$paramnoactionodate.'">';
550//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
551$viewmode .= img_picto($langs->trans("ViewWeek"), 'object_calendarweek', 'class="pictoactionview block"');
552//$viewmode .= '</span>';
553$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewWeek").'</span></a>';
554
555$viewmode .= '<a class="btnTitle'.($mode == 'show_day' ? ' btnTitleSelected' : '').' reposition" href="'.DOL_URL_ROOT.'/comm/action/index.php?mode=show_day&year='.(isset($object->datep) ? dol_print_date($object->datep, '%Y') : $year).'&month='.(isset($object->datep) ? dol_print_date($object->datep, '%m') : $month).'&day='.(isset($object->datep) ? dol_print_date($object->datep, '%d') : $day).$paramnoactionodate.'">';
556//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
557$viewmode .= img_picto($langs->trans("ViewDay"), 'object_calendarday', 'class="pictoactionview block"');
558//$viewmode .= '</span>';
559$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewDay").'</span></a>';
560
561$viewmode .= '<a class="btnTitle'.($mode == 'show_peruser' ? ' btnTitleSelected' : '').' reposition" href="'.DOL_URL_ROOT.'/comm/action/peruser.php?mode=show_peruser&year='.(isset($object->datep) ? dol_print_date($object->datep, '%Y') : $year).'&month='.(isset($object->datep) ? dol_print_date($object->datep, '%m') : $month).'&day='.(isset($object->datep) ? dol_print_date($object->datep, '%d') : $day).$paramnoactionodate.'">';
562//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
563$viewmode .= img_picto($langs->trans("ViewPerUser"), 'object_calendarperuser', 'class="pictoactionview block"');
564//$viewmode .= '</span>';
565$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow" title="'.dolPrintHTML($langs->trans("ViewPerUser")).'">'.$langs->trans("ViewPerUser").'</span></a>';
566
567// Add more views from hooks
568$parameters = array();
569$object = null;
570$reshook = $hookmanager->executeHooks('addCalendarView', $parameters, $object, $action);
571if (empty($reshook)) {
572 $viewmode .= $hookmanager->resPrint;
573} elseif ($reshook > 1) {
574 $viewmode = $hookmanager->resPrint;
575}
576
577$viewmode .= '</div>';
578
579$viewmode .= '<span class="marginrightonly"></span>'; // To add a space before the navigation tools
580
581
582$newparam = '';
583$newcardbutton = '';
584if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) {
585 $tmpforcreatebutton = dol_getdate(dol_now('tzuserrel'), true, 'gmt');
586
587 $newparam .= '&month='.((int) $month).'&year='.((int) $tmpforcreatebutton['year']).'&mode='.urlencode($mode);
588
589 //$param='month='.$monthshown.'&year='.$year;
590 //$hourminsec = dol_print_date(dol_mktime(10, 0, 0, 1, 1, 1970, 'gmt'), '%H', 'gmt').'0000'; // Set $hourminsec to '100000' to auto set hour to 10:00 at creation
591
592 $urltocreateaction = DOL_URL_ROOT.'/comm/action/card.php?action=create';
593 $urltocreateaction .= '&apyear='.$tmpforcreatebutton['year'].'&apmonth='.$tmpforcreatebutton['mon'].'&apday='.$tmpforcreatebutton['mday'].'&aphour='.$tmpforcreatebutton['hours'].'&apmin='.$tmpforcreatebutton['minutes'];
594 $urltocreateaction .= '&backtopage='.urlencode($_SERVER["PHP_SELF"].($newparam ? '?'.$newparam : ''));
595
596 $newcardbutton .= dolGetButtonTitle($langs->trans("AddAction"), '', 'fa fa-plus-circle', $urltocreateaction);
597}
598
599// Define the legend/list of calendard to show
600$s = '';
601
602
603$showextcals = $listofextcals;
604$bookcalcalendars = array();
605
606// Load Bookcal Calendars
607if (isModEnabled("bookcal")) {
608 $sql = "SELECT ba.rowid, bc.label, bc.ref, bc.rowid as id_cal";
609 $sql .= " FROM ".MAIN_DB_PREFIX."bookcal_availabilities as ba";
610 $sql .= " JOIN ".MAIN_DB_PREFIX."bookcal_calendar as bc";
611 $sql .= " ON bc.rowid = ba.fk_bookcal_calendar";
612 $sql .= " WHERE bc.status = 1";
613 $sql .= " AND ba.status = 1";
614 $sql .= " AND bc.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda
615 if (!empty($filtert) && $filtert != '-1') {
616 $sql .= " AND bc.visibility IN (".$db->sanitize($filtert, 0, 0, 0, 0).")";
617 }
618 $resql = $db->query($sql);
619 if ($resql) {
620 $num = $db->num_rows($resql);
621 $i = 0;
622 while ($i < $num) {
623 $objp = $db->fetch_object($resql);
624 $label = !empty($objp->label) ? $objp->label : $objp->ref;
625 $bookcalcalendars["calendars"][$objp->id_cal] = array("id" => $objp->id_cal, "label" => $label);
626 $bookcalcalendars["availabilitieslink"][$objp->rowid] = $objp->id_cal;
627 $i++;
628 }
629 } else {
631 }
632}
633
634if (!empty($conf->use_javascript_ajax)) { // If javascript on
635 $s .= "\n".'<!-- Div to calendars selectors -->'."\n";
636
637 $s .= '<script type="text/javascript">'."\n";
638 $s .= 'jQuery(document).ready(function () {'."\n";
639 $s .= 'jQuery(".check_birthday").click(function() { console.log("Toggle class .family_birthday"); jQuery(".family_birthday").toggle(); });'."\n";
640 $s .= 'jQuery(".check_holiday").click(function() { console.log("Toggle class .family_holiday"); jQuery(".family_holiday").toggle(); jQuery(this).closest("form").submit(); });'."\n";
641 if (isModEnabled("bookcal") && !empty($bookcalcalendars["calendars"])) {
642 foreach ($bookcalcalendars["calendars"] as $key => $value) {
643 $s .= 'jQuery(".check_bookcal_calendar_'.$value['id'].'").click(function() { console.log("Toggle Bookcal Calendar '.$value['id'].'"); jQuery(".family_bookcal_calendar_'.$value['id'].'").toggle(); });'."\n";
644 }
645 }
646 if ($mode == "show_week" || $mode == "show_month" || empty($mode)) {
647 // Code to enable drag and drop
648 $s .= 'jQuery( "div.sortable" ).sortable({connectWith: ".sortable", placeholder: "ui-state-highlight", items: "div.movable", receive: function( event, ui ) {'."\n";
649 // Code to submit form
650 $s .= 'console.log("submit form to record new event");'."\n";
651 //$s.='console.log(event.target);';
652 $s .= 'var newval = jQuery(event.target).closest("div.dayevent").attr("id");'."\n";
653 $s .= 'console.log("found parent div.dayevent with id = "+newval);'."\n";
654 $s .= 'var frm=jQuery("#searchFormList");'."\n";
655 $s .= 'var newurl = ui.item.find("a.cal_event").attr("href");'."\n";
656 $s .= 'console.log("Found url on href of a.cal_event"+newurl+", we submit form with actionmove=mupdate");'."\n";
657 $s .= 'frm.attr("action", newurl).children("#newdate").val(newval);frm.submit();}'."\n";
658 $s .= '});'."\n";
659 }
660 $s .= '});'."\n";
661 $s .= '</script>'."\n";
662
663 // Local calendar
664 $s .= '<div class="nowrap inline-block minheight30 hideonsmartphone"><input type="checkbox" id="check_mytasks" name="check_mytasks" value="1" checked disabled><label class="labelcalendar"><span class="check_local_text small"> '.$langs->trans("LocalAgenda").' &nbsp; </span></label></div>';
665
666 // Holiday calendar
667 if ($user->hasRight("holiday", "read")) {
668 $s .= '
669 <div class="nowrap inline-block minheight30"><input type="checkbox" id="check_holiday" name="check_holiday" value="1" class="marginleftonly check_holiday"' . ($check_holiday ? ' checked' : '') . '>
670 <label for="check_holiday" class="labelcalendar">
671 <span class="check_holiday_text small">' . $langs->trans("Holidays") . '</span>
672 </label> &nbsp;
673 </div>';
674 }
675
676 // External calendars
677 if (is_array($showextcals) && count($showextcals) > 0) {
678 $s .= '<script type="text/javascript">'."\n";
679 $s .= 'jQuery(document).ready(function () {
680 jQuery("div input[name^=\"check_ext\"]").each(function(index, elem) {
681 var name = jQuery(elem).attr("name");
682 if (jQuery(elem).is(":checked")) {
683 jQuery(".family_ext" + name.replace("check_ext", "")).show();
684 } else {
685 jQuery(".family_ext" + name.replace("check_ext", "")).hide();
686 }
687 });
688
689 jQuery("div input[name^=\"check_ext\"]").click(function() {
690 var name = $(this).attr("name");
691 jQuery(".family_ext" + name.replace("check_ext", "")).toggle();
692 });
693 });' . "\n";
694 $s .= '</script>'."\n";
695
696 foreach ($showextcals as $val) {
697 $htmlname = md5($val['name']); // not used for security purpose, only to get a string with no special char
698
699 if (!empty($val['default']) || GETPOSTINT('check_ext'.$htmlname)) {
700 $default = "checked";
701 } else {
702 $default = '';
703 }
704
705 $tooltip = $langs->trans("Cache").' '.round($DELAYFORCACHE / 60).'mn';
706
707 $s .= '<div class="nowrap inline-block minheight30"><input type="checkbox" id="check_ext'.$htmlname.'" class="marginleftonly check_ext_'.$htmlname.'" name="check_ext'.$htmlname.'" value="1" '.$default.'><label for="check_ext'.$htmlname.'" title="'.dol_escape_htmltag($tooltip).'" class="labelcalendar"><span class="check_ext_text small">'.dol_escape_htmltag($val['name']).'</small></label> &nbsp; </div>';
708 }
709 }
710
711 // Birthdays
712 $s .= '<div class="nowrap inline-block minheight30"><input type="checkbox" id="check_birthday" name="check_birthday" class="marginleftonly check_birthday" value="1" '. (GETPOSTINT('check_birthday') ? ' checked' : '') .'><label for="check_birthday" class="labelcalendar"><span class="check_birthday_text small">'.$langs->trans("AgendaShowBirthdayEvents").'</span></label> &nbsp; </div>';
713
714 // Bookcal Calendar
715 if (isModEnabled("bookcal")) {
716 if (!empty($bookcalcalendars["calendars"])) {
717 foreach ($bookcalcalendars["calendars"] as $key => $value) {
718 $label = $value['label'];
719 $s .= '<div class="nowrap inline-block minheight30">';
720 $s .= '<input '.(GETPOST('check_bookcal_calendar_'.$value['id']) ? "checked" : "").' type="checkbox" id="check_bookcal_calendar_'.$value['id'].'" name="check_bookcal_calendar_'.$value['id'].'" class="marginleftonly check_bookcal_calendar_'.$value['id'].'">';
721 $s .= '<label for="check_bookcal_calendar_'.$value['id'].'" class="labelcalendar">';
722 $s .= '<span class="check_bookcal_calendar_'.$value['id'].'_text">'.$langs->trans("AgendaShowBookcalCalendar", $label).'</span>';
723 $s .= '</label> &nbsp; </div>';
724 }
725 }
726 }
727
728 // Calendars from hooks
729 $parameters = array();
730 $reshook = $hookmanager->executeHooks('addCalendarChoice', $parameters, $object, $action);
731 if (empty($reshook)) {
732 $s .= $hookmanager->resPrint;
733 } elseif ($reshook > 1) {
734 $s = $hookmanager->resPrint;
735 }
736
737 $s .= "\n".'<!-- End div to calendars selectors -->'."\n";
738} else { // If javascript off
739 $newparam = $param; // newparam is for birthday links
740 $newparam = preg_replace('/check_birthday=[0-1]/i', 'check_birthday='.(empty($check_birthday) ? 1 : 0), $newparam);
741 if (!preg_match('/check_birthday=/i', $newparam)) {
742 $newparam .= '&check_birthday=1';
743 }
744 $s = '<a href="'.$_SERVER['PHP_SELF'].'?'.dol_escape_htmltag($newparam);
745 $s .= '">';
746 if (empty($check_birthday)) {
747 $s .= $langs->trans("AgendaShowBirthdayEvents");
748 } else {
749 $s .= $langs->trans("AgendaHideBirthdayEvents");
750 }
751 $s .= '</a>';
752}
753
754
755// Load events from database into $eventarray
756$filters = array(
757 'usergroup' => $usergroup,
758 'filtert' => $filtert,
759 'resourceid' => $resourceid,
760 'actioncode' => $actioncode,
761 'pid' => $pid,
762 'socid' => $socid,
763 'type' => $type,
764 'status' => $status,
765 'search_categ_cus' => $search_categ_cus,
766);
767$agendaeventresult = agenda_build_eventarray($db, $hookmanager, $user, $object, $action, $mode, $year, $month, $day, $firstdaytoshow, $lastdaytoshow, $filters);
768$eventarray = $agendaeventresult['eventarray'];
769$nbevents = $agendaeventresult['nbevents'];
770$MAXONSAMEPAGE = $agendaeventresult['maxonsamepage'];
771
772
773// BIRTHDATES CALENDAR
774// Complete $eventarray with birthdates
775if ($check_birthday) {
776 agenda_get_birthday_events($db, $langs, $user, $mode, $month, $day, $year, $eventarray, $nbevents);
777}
778
779// LEAVE-HOLIDAY CALENDAR
780if ($user->hasRight("holiday", "read")) {
781 $sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.statut, x.rowid, x.date_debut as date_start, x.date_fin as date_end, x.halfday, x.statut as status";
782 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u";
783 $sql .= " WHERE u.rowid = x.fk_user";
784 $sql .= " AND u.statut = '1'"; // Show only active users (0 = inactive user, 1 = active user)
785 $sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
786 if ($mode == 'show_day') {
787 // Request only leaves for the current selected day
788 $sql .= " AND '".$db->escape($year."-".$month."-".$day)."' BETWEEN x.date_debut AND x.date_fin"; // date_debut and date_fin are date without time
789 } elseif ($mode == 'show_week') {
790 // Restrict on current month (we get more, but we will filter later)
791 $sql .= " AND x.date_debut < '".$db->idate(dol_get_last_day($year, $month))."'";
792 $sql .= " AND x.date_fin >= '".$db->idate(dol_get_first_day($year, $month))."'";
793 } elseif ($mode == 'show_month') {
794 // Restrict on current month
795 $sql .= " AND x.date_debut <= '".$db->idate(dol_get_last_day($year, $month))."'";
796 $sql .= " AND x.date_fin >= '".$db->idate(dol_get_first_day($year, $month))."'";
797 }
798 if (!$user->hasRight('holiday', 'readall') || $filtert == '-3') {
799 // Restrict on users of current user and his children
800 $sql .= " AND x.fk_user IN(".$db->sanitize(implode(", ", $user->getAllChildIds(1))).") ";
801 }
802 if ($filtert > 0) {
803 // Restrict on user
804 $sql .= " AND x.fk_user = ".((int) $filtert);
805 }
806
807 $resql = $db->query($sql);
808 if ($resql) {
809 $num = $db->num_rows($resql);
810 $i = 0;
811 $nbevents += $num;
812
813 while ($i < $num) {
814 $obj = $db->fetch_object($resql);
815
816 $event = new ActionComm($db);
817
818 // Need the id of the leave object for link to it
819 $event->id = $obj->rowid;
820 $event->ref = (string) $event->id;
821
822 $event->type_code = 'HOLIDAY';
823 $event->type_label = '';
824 $event->type_color = '';
825 $event->type = 'holiday';
826 $event->type_picto = 'holiday';
827
828 // date_debut and date_fin are dates without time, so they must be read and rendered in GMT to
829 // stay independent from the server and user timezones (otherwise the calendar day box is shifted).
830 $event->datep = (int) $db->jdate($obj->date_start, 'gmt') + (empty($obj->halfday) || $obj->halfday == 1 ? 0 : 12) * 60 * 60;
831 $event->datef = (int) $db->jdate($obj->date_end, 'gmt') + (empty($obj->halfday) || $obj->halfday == -1 ? 24 : 12) * 60 * 60 - 1;
832 $event->date_start_in_calendar = $event->datep;
833 $event->date_end_in_calendar = $event->datef;
834
835 if ($obj->status == 3) {
836 // Show no symbol for leave with state "leave approved"
837 $event->percentage = -1;
838 } elseif ($obj->status == 2) {
839 // Show TO-DO symbol for leave with state "leave wait for approval"
840 $event->percentage = 0;
841 }
842
843 $event->label = $langs->trans("Holiday");
844
845 $daycursor = $event->date_start_in_calendar;
846 $annee = (int) dol_print_date($daycursor, '%Y', 'gmt');
847 $mois = (int) dol_print_date($daycursor, '%m', 'gmt');
848 $jour = (int) dol_print_date($daycursor, '%d', 'gmt');
849
850 $daycursorend = $event->date_end_in_calendar;
851 $anneeend = (int) dol_print_date($daycursorend, '%Y', 'gmt');
852 $moisend = (int) dol_print_date($daycursorend, '%m', 'gmt');
853 $jourend = (int) dol_print_date($daycursorend, '%d', 'gmt');
854
855 // daykey must be date that represent day box in calendar so must be a user time
856 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
857 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
858 $ifornbofdays = 0;
859 do {
860 $ifornbofdays++;
861
862 $firstdayofholiday = ($ifornbofdays == 1);
863 $lastdayofholiday = ($daykeygmt == dol_get_first_hour($event->date_end_in_calendar, 'gmt'));
864
865 /*
866 var_dump(dol_print_date($daykeygmt, 'dayhour', 'gmt'));
867 var_dump(dol_print_date(dol_get_first_hour($event->date_end_in_calendar, 'gmt'), 'dayhour', 'gmt'));
868 var_dump($lastdayofholiday);
869 var_dump($obj->halfday);
870 */
871
872 if ((in_array($obj->halfday, array(1, 2)) == 1 && $lastdayofholiday) || (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday)) {
873 // We create a copy of event because we want tochange the label
874 $newevent = dol_clone($event, 1);
875 if (in_array($obj->halfday, array(1, 2)) && $lastdayofholiday) {
876 $newevent->label .= ' ('.$langs->trans("Morning").')';
877 } elseif (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday) {
878 $newevent->label .= ' ('.$langs->trans("Afternoon").')';
879 }
880 $eventarray[$daykey][] = $newevent; // We need to use ->gtTypePicto, getXXXon object, so clone must be PHP clone.
881 } else {
882 $eventarray[$daykey][] = $event; // We can use the event unchanged
883 }
884
885 $daykey += 60 * 60 * 24;
886 $daykeygmt += 60 * 60 * 24;
887 } while ($daykey <= $event->date_end_in_calendar);
888
889 $i++;
890 }
891 }
892}
893
894// EXTERNAL CALENDAR
895// Complete $eventarray with external import Ical
896if (count($listofextcals)) {
897 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/ical.class.php';
898
899 foreach ($listofextcals as $key => $extcal) {
900 $url = $extcal['src']; // Example: https://www.google.com/calendar/ical/eldy10%40gmail.com/private-cde92aa7d7e0ef6110010a821a2aaeb/basic.ics
901 $namecal = $extcal['name'];
902 $offsettz = $extcal['offsettz'];
903 $colorcal = $extcal['color'];
904 $buggedfile = $extcal['buggedfile'];
905
906 $pathforcachefile = dol_sanitizePathName($conf->user->dir_temp).'/'.dol_sanitizeFileName('extcal_'.$namecal.'_user'.$user->id).'.cache';
907 //var_dump($pathforcachefile);exit;
908
909 $ical = new ICal();
910 $ical->parse($url, $pathforcachefile, $DELAYFORCACHE);
911 if ($ical->error) {
912 // Save error message for extcal
913 $listofextcals[$key]['error'] = $ical->error;
914 $s .= '<br><div class="warning">'.dol_escape_htmltag($listofextcals[$key]['name']).': '.$url.'<br>Error message: '.dol_escape_htmltag($ical->error).'</div>';
915 }
916
917 // After this $ical->cal['VEVENT'] contains array of events, $ical->cal['DAYLIGHT'] contains daylight info, $ical->cal['STANDARD'] contains non daylight info, ...
918 //var_dump($ical->cal); exit;
919 $icalevents = array();
920 $tmparray = $ical->get_event_list();
921 if (is_array($tmparray)) {
922 $icalevents = array_merge($icalevents, $tmparray); // Add $ical->cal['VEVENT']
923 }
924 $tmparray = $ical->get_freebusy_list();
925 if (is_array($tmparray)) {
926 $icalevents = array_merge($icalevents, $tmparray); // Add $ical->cal['VFREEBUSY']
927 }
928
929 $nbevents += count($icalevents);
930
931 if (count($icalevents) > 0) {
932 // Duplicate all repeatable events into new entries
933 $moreicalevents = array();
934 foreach ($icalevents as $icalevent) {
935 if (isset($icalevent['RRULE']) && is_array($icalevent['RRULE'])) { //repeatable event
936 //if ($event->date_start_in_calendar < $firstdaytoshow) $event->date_start_in_calendar=$firstdaytoshow;
937 //if ($event->date_end_in_calendar > $lastdaytoshow) $event->date_end_in_calendar=($lastdaytoshow-1);
938 if ($icalevent['DTSTART;VALUE=DATE']) { //fullday event
939 $datecurstart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
940 $datecurend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
941 } elseif (is_array($icalevent['DTSTART']) && !empty($icalevent['DTSTART']['unixtime'])) {
942 $datecurstart = $icalevent['DTSTART']['unixtime'];
943 $datecurend = $icalevent['DTEND']['unixtime'];
944 if (!empty($ical->cal['DAYLIGHT']['DTSTART']) && $datecurstart) {
945 //var_dump($ical->cal);
946 $tmpcurstart = $datecurstart;
947 $tmpcurend = $datecurend;
948 $tmpdaylightstart = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['DAYLIGHT']['DTSTART'];
949 $tmpdaylightend = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['STANDARD']['DTSTART'];
950 //var_dump($tmpcurstart);var_dump($tmpcurend); var_dump($ical->cal['DAYLIGHT']['DTSTART']);var_dump($ical->cal['STANDARD']['DTSTART']);
951 // Edit datecurstart and datecurend
952 if ($tmpcurstart >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
953 $datecurstart -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
954 } else {
955 $datecurstart -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
956 }
957 if ($tmpcurend >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
958 $datecurend -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
959 } else {
960 $datecurend -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
961 }
962 }
963 // datecurstart and datecurend are now GMT date
964 //var_dump($datecurstart); var_dump($datecurend); exit;
965 } else {
966 // Not a recognized record
967 dol_syslog("Found a not recognized repeatable record with unknown date start", LOG_ERR);
968 continue;
969 }
970 //print 'xx'.$datecurstart;exit;
971
972 $interval = (empty($icalevent['RRULE']['INTERVAL']) ? 1 : $icalevent['RRULE']['INTERVAL']);
973 $until = empty($icalevent['RRULE']['UNTIL']) ? 0 : dol_stringtotime($icalevent['RRULE']['UNTIL'], 1);
974 $maxrepeat = empty($icalevent['RRULE']['COUNT']) ? 0 : $icalevent['RRULE']['COUNT'];
975 if ($until && ($until + ($datecurend - $datecurstart)) < $firstdaytoshow) {
976 continue; // We discard repeatable event that end before start date to show
977 }
978 if ($datecurstart >= $lastdaytoshow) {
979 continue; // We discard repeatable event that start after end date to show
980 }
981
982 $numofevent = 0;
983 while (($datecurstart < $lastdaytoshow) && (empty($maxrepeat) || ($numofevent < $maxrepeat))) {
984 if ($datecurend >= $firstdaytoshow) { // We add event
985 $newevent = $icalevent;
986 unset($newevent['RRULE']);
987 if ($icalevent['DTSTART;VALUE=DATE']) {
988 $newevent['DTSTART;VALUE=DATE'] = dol_print_date($datecurstart, '%Y%m%d');
989 $newevent['DTEND;VALUE=DATE'] = dol_print_date($datecurend + 1, '%Y%m%d');
990 } else {
991 $newevent['DTSTART'] = $datecurstart;
992 $newevent['DTEND'] = $datecurend;
993 }
994 $moreicalevents[] = $newevent;
995 }
996 // Jump on next occurrence
997 $numofevent++;
998 $savdatecurstart = $datecurstart;
999 if ($icalevent['RRULE']['FREQ'] == 'DAILY') {
1000 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'd');
1001 $datecurend = dol_time_plus_duree($datecurend, $interval, 'd');
1002 }
1003 if ($icalevent['RRULE']['FREQ'] == 'WEEKLY') {
1004 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'w');
1005 $datecurend = dol_time_plus_duree($datecurend, $interval, 'w');
1006 } elseif ($icalevent['RRULE']['FREQ'] == 'MONTHLY') {
1007 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'm');
1008 $datecurend = dol_time_plus_duree($datecurend, $interval, 'm');
1009 } elseif ($icalevent['RRULE']['FREQ'] == 'YEARLY') {
1010 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'y');
1011 $datecurend = dol_time_plus_duree($datecurend, $interval, 'y');
1012 }
1013 // Test to avoid infinite loop ($datecurstart must increase)
1014 if ($savdatecurstart >= $datecurstart) {
1015 dol_syslog("Found a rule freq ".$icalevent['RRULE']['FREQ']." not managed by dolibarr code. Assume 1 week frequency.", LOG_ERR);
1016 $datecurstart += 3600 * 24 * 7;
1017 $datecurend += 3600 * 24 * 7;
1018 }
1019 }
1020 }
1021 }
1022 $icalevents = array_merge($icalevents, $moreicalevents);
1023
1024 // Loop on each entry into cal file to know if entry is qualified and add an ActionComm into $eventarray
1025 foreach ($icalevents as $icalevent) {
1026 //var_dump($icalevent);
1027
1028 //print $icalevent['SUMMARY'].'->';
1029 //var_dump($icalevent);exit;
1030 if (!empty($icalevent['RRULE'])) {
1031 continue; // We found a repeatable event. It was already split into unitary events, so we discard general rule.
1032 }
1033
1034 // Create a new object action
1035 $event = new ActionComm($db);
1036 $addevent = false;
1037 if (isset($icalevent['DTSTART;VALUE=DATE'])) { // fullday event
1038 // For full day events, date are also GMT but they won't but converted using tz during output
1039 $datestart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
1040 if (empty($icalevent['DTEND;VALUE=DATE'])) {
1041 $dateend = $datestart + 86400 - 1;
1042 } else {
1043 $dateend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
1044 }
1045 //print 'x'.$datestart.'-'.$dateend;exit;
1046 //print dol_print_date($dateend,'dayhour','gmt');
1047 $event->fulldayevent = 1;
1048 $addevent = true;
1049 } elseif (!is_array($icalevent['DTSTART'])) { // not fullday event (DTSTART is not array. It is a value like '19700101T000000Z' for 00:00 in greenwitch)
1050 $datestart = $icalevent['DTSTART'];
1051 $dateend = empty($icalevent['DTEND']) ? $datestart : $icalevent['DTEND'];
1052
1053 $datestart += +($offsettz * 3600);
1054 $dateend += +($offsettz * 3600);
1055
1056 $addevent = true;
1057 //var_dump($offsettz);
1058 //var_dump(dol_print_date($datestart, 'dayhour', 'gmt'));
1059 } elseif (isset($icalevent['DTSTART']['unixtime'])) { // File contains a local timezone + a TZ (for example when using bluemind)
1060 $datestart = $icalevent['DTSTART']['unixtime'];
1061 $dateend = $icalevent['DTEND']['unixtime'];
1062
1063 $datestart += +($offsettz * 3600);
1064 $dateend += +($offsettz * 3600);
1065
1066 // $buggedfile is set to uselocalandtznodaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtznodaylight'
1067 if ($buggedfile === 'uselocalandtznodaylight') { // unixtime is a local date that does not take daylight into account, TZID is +1 for example for 'Europe/Paris' in summer instead of 2
1068 // TODO
1069 }
1070 // $buggedfile is set to uselocalandtzdaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtzdaylight' (for example with bluemind)
1071 if ($buggedfile === 'uselocalandtzdaylight') { // unixtime is a local date that does take daylight into account, TZID is +2 for example for 'Europe/Paris' in summer
1072 $localtzs = new DateTimeZone((string) preg_replace('/"/', '', $icalevent['DTSTART']['TZID']));
1073 $localtze = new DateTimeZone((string) preg_replace('/"/', '', $icalevent['DTEND']['TZID']));
1074 $localdts = new DateTime(dol_print_date($datestart, 'dayrfc', 'gmt'), $localtzs);
1075 $localdte = new DateTime(dol_print_date($dateend, 'dayrfc', 'gmt'), $localtze);
1076 $tmps = -1 * $localtzs->getOffset($localdts);
1077 $tmpe = -1 * $localtze->getOffset($localdte);
1078 $datestart += $tmps;
1079 $dateend += $tmpe;
1080 //var_dump($datestart);
1081 }
1082 $addevent = true;
1083 }
1084
1085 if ($addevent) {
1086 $event->id = $icalevent['UID'];
1087 $event->ref = (string) $event->id;
1088 $userId = $userstatic->findUserIdByEmail($namecal);
1089 if (!empty($userId) && $userId > 0) {
1090 $event->userassigned[$userId] = $userId;
1091 $event->percentage = -1;
1092 }
1093
1094 $event->type_code = "ICALEVENT";
1095 $event->type_label = $namecal;
1096 $event->type_color = $colorcal;
1097 $event->type = 'icalevent';
1098 $event->type_picto = 'rss';
1099
1100 $event->icalname = $namecal;
1101 $event->icalcolor = $colorcal;
1102 $usertime = 0; // We don't modify date because we want to have date into memory datep and datef stored as GMT date. Compensation will be done during output.
1103 $event->datep = (int) ($datestart + $usertime);
1104 $event->datef = (int) ($dateend + $usertime);
1105
1106 if (isset($icalevent['SUMMARY']) && $icalevent['SUMMARY']) {
1107 $event->label = dol_string_nohtmltag($icalevent['SUMMARY']);
1108 } elseif (isset($icalevent['DESCRIPTION']) && $icalevent['DESCRIPTION']) {
1109 $event->label = dol_nl2br(dol_string_nohtmltag($icalevent['DESCRIPTION']), 1);
1110 } else {
1111 $event->label = $langs->trans("ExtSiteNoLabel");
1112 }
1113
1114 // Priority (see https://www.kanzaki.com/docs/ical/priority.html)
1115 // LOW = 0 to 4
1116 // MEDIUM = 5
1117 // HIGH = 6 to 9
1118 if (!empty($icalevent['PRIORITY'])) {
1119 $event->priority = $icalevent['PRIORITY'];
1120 }
1121
1122 // Transparency (see https://www.kanzaki.com/docs/ical/transp.html)
1123 if (!empty($icalevent['TRANSP'])) {
1124 if ($icalevent['TRANSP'] == "TRANSPARENT") {
1125 $event->transparency = 0; // 0 = available / free
1126 }
1127 if ($icalevent['TRANSP'] == "OPAQUE") {
1128 $event->transparency = 1; // 1 = busy
1129 }
1130
1131 // TODO: MS outlook states
1132 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:TRANSPARENT => Available / Free
1133 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:OPAQUE => Work another place
1134 // X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE + TRANSP:OPAQUE => With reservations
1135 // X-MICROSOFT-CDO-BUSYSTATUS:BUSY + TRANSP:OPAQUE => Busy
1136 // X-MICROSOFT-CDO-BUSYSTATUS:OOF + TRANSP:OPAQUE => Away from the office / off-site
1137 }
1138
1139 if (!empty($icalevent['LOCATION'])) {
1140 $event->location = $icalevent['LOCATION'];
1141 }
1142
1143 $event->date_start_in_calendar = $event->datep;
1144
1145 if ((int) $event->datef != 0 && $event->datef >= $event->datep) {
1146 $event->date_end_in_calendar = $event->datef;
1147 } else {
1148 $event->date_end_in_calendar = $event->datep;
1149 }
1150
1151 // Add event into $eventarray if date range are ok.
1152 if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) {
1153 //print 'x'.$datestart.'-'.$dateend;exit;
1154 //print 'x'.$datestart.'-'.$dateend;exit;
1155 //print 'x'.$datestart.'-'.$dateend;exit;
1156 // This record is out of visible range
1157 } else {
1158 if ($event->date_start_in_calendar < $firstdaytoshow) {
1159 $event->date_start_in_calendar = $firstdaytoshow;
1160 }
1161 if ($event->date_end_in_calendar >= $lastdaytoshow) {
1162 $event->date_end_in_calendar = ($lastdaytoshow - 1);
1163 }
1164
1165 // Add an entry in actionarray for each day
1166 $daycursor = $event->date_start_in_calendar;
1167 $annee = (int) dol_print_date($daycursor, '%Y', 'tzuserrel');
1168 $mois = (int) dol_print_date($daycursor, '%m', 'tzuserrel');
1169 $jour = (int) dol_print_date($daycursor, '%d', 'tzuserrel');
1170
1171 // Loop on each day covered by action to prepare an index to show on calendar
1172 $loop = true;
1173 $j = 0;
1174 // daykey must be date that represent day box in calendar so must be a user time
1175 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1176 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1177 do {
1178 //if ($event->fulldayevent) print dol_print_date($daykeygmt,'dayhour','gmt').'-'.dol_print_date($daykey,'dayhour','gmt').'-'.dol_print_date($event->date_end_in_calendar,'dayhour','gmt').' ';
1179 $eventarray[$daykey][] = $event;
1180 $daykey += 60 * 60 * 24;
1181 $daykeygmt += 60 * 60 * 24; // Add one day
1182 if (($event->fulldayevent ? $daykeygmt : $daykey) > $event->date_end_in_calendar) {
1183 $loop = false;
1184 }
1185 } while ($loop);
1186 }
1187 }
1188 }
1189 }
1190 }
1191}
1192
1193// Complete $eventarray with events coming from external module
1194$parameters = array();
1195$object = null;
1196$reshook = $hookmanager->executeHooks('getCalendarEvents', $parameters, $object, $action);
1197if (!empty($hookmanager->resArray['eventarray'])) {
1198 foreach ($hookmanager->resArray['eventarray'] as $keyDate => $events) {
1199 if (!isset($eventarray[$keyDate])) {
1200 $eventarray[$keyDate] = array();
1201 }
1202 $eventarray[$keyDate] = array_merge($eventarray[$keyDate], $events);
1203 }
1204}
1205
1206// Sort events
1207foreach ($eventarray as $keyDate => &$dateeventarray) {
1208 usort($dateeventarray, 'sort_events_by_date');
1209}
1210
1211
1212$maxnbofchar = 0;
1213$cachethirdparties = array();
1214$cachecontacts = array();
1215$cacheusers = array();
1216// default values
1218 array(137, 86, 161),
1219 array(60, 147, 183),
1220 array(250, 190, 80),
1221 array(80, 166, 90),
1222 array(190, 190, 100),
1223 array(91, 115, 247),
1224 array(140, 140, 220),
1225 array(190, 120, 120),
1226 array(115, 125, 150),
1227 array(100, 170, 20),
1228 array(150, 135, 125),
1229 array(85, 135, 150),
1230 array(150, 135, 80),
1231 array(150, 80, 150)
1232);
1233
1234// Define theme_datacolor array
1235$color_file = DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/theme_vars.inc.php";
1236if (is_readable($color_file)) {
1237 global $theme_datacolor;
1238 include $color_file;
1240}
1241
1242$massactionbutton = '';
1243
1244print_barre_liste($langs->trans("Agenda"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, 1, -1, 'object_action', 0, $nav.'<span class="marginleftonly"></span>'.$newcardbutton, '', $limit, 1, 0, 1, $viewmode);
1245
1246if ($nbevents > $MAXONSAMEPAGE) {
1247 print info_admin('Number of results has been truncated to '.$MAXONSAMEPAGE, 0, 0, 'warning').'<br>';
1248}
1249
1250// Show div with list of calendars
1251print $s;
1252
1253
1254if (empty($mode) || $mode == 'show_month') { // View by month
1255 $newparam = $param; // newparam is for birthday links
1256 $newparam = preg_replace('/check_birthday=/i', 'check_birthday_=', $newparam); // To avoid replacement when replace day= is done
1257 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1258 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1259 $newparam = preg_replace('/day=[0-9]+&?/i', '', $newparam);
1260 $newparam = preg_replace('/month=[0-9]+&?/i', '', $newparam);
1261 $newparam = preg_replace('/year=[0-9]+&?/i', '', $newparam);
1262 $newparam = preg_replace('/viewcal=[0-9]+&?/i', '', $newparam);
1263 $newparam = preg_replace('/check_birthday_=/i', 'check_birthday=', $newparam); // Restore correct parameter
1264 $newparam .= '&viewcal=1';
1265
1266 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1267 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroupids, '', $resourceid, $search_categ_cus);
1268 print '</div>';
1269
1270 print '<div class="div-table-responsive-no-min sectioncalendarbymonth maxscreenheightless300">';
1271 print '<table class="centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore">';
1272 print ' <tr class="liste_titre sticky">';
1273 // Column title of weeks numbers
1274 echo ' <td class="center">#</td>';
1275 $i = 0;
1276 while ($i < 7) {
1277 print ' <td class="center bold uppercase tdfordaytitle'.($i == 0 ? ' borderleft' : '').'">';
1278 $numdayinweek = (($i + (getDolGlobalInt('MAIN_START_WEEK', 1))) % 7);
1279 if (!empty($conf->dol_optimize_smallscreen)) {
1280 $labelshort = array(0 => 'SundayMin', 1 => 'MondayMin', 2 => 'TuesdayMin', 3 => 'WednesdayMin', 4 => 'ThursdayMin', 5 => 'FridayMin', 6 => 'SaturdayMin');
1281 print $langs->trans($labelshort[$numdayinweek]);
1282 } else {
1283 print $langs->trans("Day".$numdayinweek);
1284 }
1285 print ' </td>'."\n";
1286 $i++;
1287 }
1288 echo ' </tr>'."\n";
1289
1290 $todayarray = dol_getdate($now, true);
1291 $todaytms = dol_mktime(0, 0, 0, $todayarray['mon'], $todayarray['mday'], $todayarray['year']);
1292
1293 // In loops, tmpday contains day nb in current month (can be zero or negative for days of previous month)
1294 //var_dump($eventarray);
1295 for ($iter_week = 0; $iter_week < 6; $iter_week++) {
1296 echo " <tr>\n";
1297 // Get date of the current day, format 'yyyy-mm-dd'
1298 if ($tmpday <= 0) { // If number of the current day is in previous month
1299 $currdate0 = sprintf("%04d", $prev_year).sprintf("%02d", $prev_month).sprintf("%02d", $max_day_in_prev_month + $tmpday);
1300 } elseif ($tmpday <= $max_day_in_month) { // If number of the current day is in current month
1301 $currdate0 = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $tmpday);
1302 } else { // If number of the current day is in next month
1303 $currdate0 = sprintf("%04d", $next_year).sprintf("%02d", $next_month).sprintf("%02d", $tmpday - $max_day_in_month);
1304 }
1305 // Get week number for the targeted date '$currdate0'
1306 $numweek0 = date("W", strtotime(date($currdate0)));
1307 // Show the week number, and define column width
1308 echo ' <td class="center weeknumber opacitymedium" width="2%">'.$numweek0.'</td>';
1309
1310 for ($iter_day = 0; $iter_day < 7; $iter_day++) {
1311 if ($tmpday <= 0) {
1312 /* Show days before the beginning of the current month (previous month) */
1313 $style = 'cal_other_month cal_past';
1314 if ($iter_day == 6) {
1315 $style .= ' cal_other_month_right';
1316 }
1317 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1318 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1319 show_day_events($db, $max_day_in_prev_month + $tmpday, $prev_month, $prev_year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam);
1320 echo " </td>\n";
1321 } elseif ($tmpday <= $max_day_in_month) {
1322 /* Show days of the current month */
1323 $curtime = dol_mktime(0, 0, 0, $month, $tmpday, $year);
1324 $style = 'cal_current_month';
1325 if ($iter_day == 6) {
1326 $style .= ' cal_current_month_right';
1327 }
1328 $today = 0;
1329 if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $month && $todayarray['year'] == $year) {
1330 $today = 1;
1331 }
1332 if ($today) {
1333 $style = 'cal_today';
1334 }
1335 if ($curtime < $todaytms) {
1336 $style .= ' cal_past';
1337 }
1338 //var_dump($todayarray['mday']."==".$tmpday." && ".$todayarray['mon']."==".$month." && ".$todayarray['year']."==".$year.' -> '.$style);
1339 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1340 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1341 show_day_events($db, $tmpday, $month, $year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam, 0, 60, 0, $bookcalcalendars);
1342 echo "</td>\n";
1343 } else {
1344 /* Show days after the current month (next month) */
1345 $style = 'cal_other_month';
1346 if ($iter_day == 6) {
1347 $style .= ' cal_other_month_right';
1348 }
1349 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1350 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1351 show_day_events($db, $tmpday - $max_day_in_month, $next_month, $next_year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam);
1352 echo "</td>\n";
1353 }
1354 $tmpday++;
1355 }
1356 echo " </tr>\n";
1357 }
1358 print "</table>\n";
1359 print '</div>';
1360
1361 print '<input type="hidden" name="actionmove" value="mupdate">';
1362 print '<input type="hidden" name="backtopage" value="'.dol_escape_htmltag($_SERVER['PHP_SELF']).'?mode=show_month&'.dol_escape_htmltag($_SERVER['QUERY_STRING']).'">';
1363 print '<input type="hidden" name="newdate" id="newdate">';
1364} elseif ($mode == 'show_week') {
1365 // View by week
1366 $newparam = $param; // newparam is for birthday links
1367 $newparam = preg_replace('/check_birthday=/i', 'check_birthday_=', $newparam); // To avoid replacement when replace day= is done
1368 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1369 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1370 $newparam = preg_replace('/day=[0-9]+&?/i', '', $newparam);
1371 $newparam = preg_replace('/month=[0-9]+&?/i', '', $newparam);
1372 $newparam = preg_replace('/year=[0-9]+&?/i', '', $newparam);
1373 $newparam = preg_replace('/viewweek=[0-9]+&?/i', '', $newparam);
1374 $newparam = preg_replace('/check_birthday_=/i', 'check_birthday=', $newparam); // Restore correct parameter
1375 $newparam .= '&viewweek=1';
1376
1377 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1378 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroupids, '', $resourceid);
1379 print '</div>';
1380
1381 print '<div class="div-table-responsive-no-min sectioncalendarbyweek maxscreenheightless300">';
1382 print '<table class="centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore">';
1383 print ' <tr class="liste_titre">';
1384 $i = 0;
1385 while ($i < 7) {
1386 echo ' <td class="center bold uppercase tdfordaytitle">'.$langs->trans("Day".(($i + (getDolGlobalInt('MAIN_START_WEEK', 1))) % 7))."</td>\n";
1387 $i++;
1388 }
1389 echo " </tr>\n";
1390
1391 echo ' <tr class="trcalweek">'."\n";
1392
1393 for ($iter_day = 0; $iter_day < 7; $iter_day++) {
1394 // Show days of the current week
1395 $curtime = dol_time_plus_duree($firstdaytoshow, $iter_day, 'd'); // $firstdaytoshow is in timezone of server
1396 $tmpday = (int) dol_print_date($curtime, '%d', 'tzuserrel');
1397 $tmpmonth = (int) dol_print_date($curtime, '%m', 'tzuserrel');
1398 $tmpyear = (int) dol_print_date($curtime, '%Y', 'tzuserrel');
1399
1400 $style = 'cal_current_month';
1401 if ($iter_day == 6) {
1402 $style .= ' cal_other_month_right';
1403 }
1404
1405 $today = 0;
1406 $todayarray = dol_getdate($now, true);
1407 if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $tmpmonth && $todayarray['year'] == $tmpyear) {
1408 $today = 1;
1409 }
1410 if ($today) {
1411 $style = 'cal_today';
1412 }
1413
1414 echo ' <td class="'.$style.'" width="14%" valign="top">';
1415 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1416 show_day_events($db, $tmpday, $tmpmonth, $tmpyear, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 0, $bookcalcalendars);
1417 echo " </td>\n";
1418 }
1419 echo " </tr>\n";
1420
1421 print "</table>\n";
1422 print '</div>';
1423
1424 echo '<input type="hidden" name="actionmove" value="mupdate">';
1425 echo '<input type="hidden" name="backtopage" value="'.dol_escape_htmltag($_SERVER['PHP_SELF']).'?mode=show_week&'.dol_escape_htmltag($_SERVER['QUERY_STRING']).'">';
1426 echo '<input type="hidden" name="newdate" id="newdate">';
1427} else { // View by day
1428 $newparam = $param; // newparam is for birthday links
1429 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1430 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1431 $newparam = preg_replace('/viewday=[0-9]+&?/i', '', $newparam);
1432 $newparam .= '&viewday=1';
1433 // Code to show just one day
1434 $style = 'cal_current_month cal_current_month_oneday';
1435 $today = 0;
1436 $todayarray = dol_getdate($now, true);
1437 if ($todayarray['mday'] == $day && $todayarray['mon'] == $month && $todayarray['year'] == $year) {
1438 $today = 1;
1439 }
1440 //if ($today) $style='cal_today';
1441
1442 $timestamp = dol_mktime(12, 0, 0, $month, $day, $year);
1443 $arraytimestamp = dol_getdate($timestamp);
1444
1445 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1446 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroupids, '', $resourceid);
1447 print '</div>';
1448
1449 print '<div class="div-table-responsive-no-min sectioncalendarbyday maxscreenheightless300">';
1450 echo '<table class="tagtable centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore" style="margin-bottom: 10px !important;">';
1451
1452 echo ' <tr class="tagtr liste_titre">';
1453 echo ' <td class="tagtd center bold uppercase">'.$langs->trans("Day".$arraytimestamp['wday'])."</td>\n";
1454 echo " </tr>\n";
1455
1456 /*
1457 echo ' <div class="tagtr">';
1458 echo ' <div class="tagtd width100"></div>';
1459 echo ' <div class="tagtd center">';
1460 echo show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, -1);
1461 echo ' </div>'."\n";
1462 echo " </div>\n";
1463 */
1464
1465 print '<tr class="trcalday"><td class="tdtop">';
1466
1467 /* WIP View per hour */
1468 $useviewhour = 0;
1469 if ($useviewhour) {
1470 print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
1471
1472 $maxheightwin = (isset($_SESSION["dol_screenheight"]) && $_SESSION["dol_screenheight"] > 500) ? ($_SESSION["dol_screenheight"] - 200) : 660; // Also into index.php file
1473
1474 echo '<div style="max-height: '.$maxheightwin.'px;">';
1475 echo '<div class="tagtable centpercent calendarviewcontainer">';
1476
1477 $maxnbofchar = 80;
1478
1479 $tmp = explode('-', getDolGlobalString('MAIN_DEFAULT_WORKING_HOURS'));
1480 $minhour = round((float) $tmp[0], 0);
1481 $maxhour = round((float) $tmp[1], 0);
1482 if ($minhour > 23) {
1483 $minhour = 23;
1484 }
1485 if ($maxhour < 1) {
1486 $maxhour = 1;
1487 }
1488 if ($maxhour <= $minhour) {
1489 $maxhour = $minhour + 1;
1490 }
1491
1492 $i = 0;
1493 $j = 0;
1494 while ($i < 24) {
1495 echo ' <div class="tagtr calendarviewcontainertr">'."\n";
1496 echo ' <div class="tagtd width100 tdtop">'.dol_print_date($i * 3600, 'hour', 'gmt').'</div>';
1497 echo ' <div class="tagtd '.$style.' tdtop"></div>'."\n";
1498 echo ' </div>'."\n";
1499 $i++;
1500 $j++;
1501 }
1502
1503 echo '</div></div>';
1504
1505 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1506 show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 1, $bookcalcalendars);
1507
1508 print '</div>';
1509 } else {
1510 print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
1511
1512 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1513 show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 0, $bookcalcalendars);
1514
1515 print '</div>';
1516 }
1517
1518
1519 print '</td></tr>';
1520
1521 echo '</table>';
1522 print '</div>';
1523}
1524
1525print "\n".'</form>';
1526
1527// End of page
1528llxFooter();
1529$db->close();
1530
1531
1539function sort_events_by_date($a, $b)
1540{
1541 // Sort holidays at first
1542 if ($a->type_code === 'HOLIDAY') {
1543 return -1;
1544 }
1545 if ($b->type_code === 'HOLIDAY') {
1546 return 1;
1547 }
1548
1549 // datep => Event start time
1550 // datef => Event end time
1551
1552 // Events have different start time
1553 if ($a->datep !== $b->datep) {
1554 return (int) ($a->datep - $b->datep);
1555 }
1556
1557 // Events have same start time and no end time
1558 if ((!is_numeric($b->datef)) || (!is_numeric($a->datef))) {
1559 return sort_events_by_percentage($a, $b);
1560 }
1561
1562 // Events have the same start time and same end time
1563 if ($b->datef === $a->datef) {
1564 return sort_events_by_percentage($a, $b);
1565 }
1566
1567 // Events have the same start time, but have different end time -> longest event first
1568 return (int) ($b->datef - $a->datef);
1569}
1570
1579{
1580 // Sort events with no percentage before each other
1581 // (useful to sort holidays, sick days or similar on the top)
1582
1583 if ($a->percentage < 0) {
1584 return -1;
1585 }
1586
1587 if ($b->percentage < 0) {
1588 return 1;
1589 }
1590
1591 return (int) ($b->percentage - $a->percentage);
1592}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
agenda_get_birthday_events($db, $langs, $user, $mode, $month, $day, $year, &$eventarray, &$nbevents)
Complete an agenda calendar event array with contact birthday pseudo-events.
print_actions_filter( $form, $canedit, $status, $year, $month, $day, $showbirthday, $filtera, $filtert, $filtered, $pid, $socid, $action, $showextcals=array(), $actioncode='', $usergroupid=0, $excludetype='', $resourceid=0, $search_categ_cus=0, $search_import_key='')
Show filter form in agenda view.
calendars_prepare_head($param)
Define head array for tabs of agenda setup pages.
agenda_build_eventarray($db, $hookmanager, $user, &$object, &$action, $mode, $year, $month, $day, $firstdaytoshow, $lastdaytoshow, $filters, $sincedatec=null)
Build $eventarray (list of ActionComm objects, indexed by day) for the agenda calendar views (month/w...
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage agenda events (actions)
Class to manage contact/addresses.
Class to manage generation of HTML components Only common components must be here.
Class to read/parse ICal calendars.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
$theme_datacolor
Definition index.php:1217
sort_events_by_percentage($a, $b)
Sort events by percentage.
Definition index.php:1578
$cacheusers
Definition index.php:1215
sort_events_by_date($a, $b)
Sort events by date.
Definition index.php:1539
dol_get_prev_month($month, $year)
Return previous month.
Definition date.lib.php:524
dol_get_first_hour($date, $gm='tzserver')
Return GMT time for first hour of a given GMT date (it removes hours, min and second part)
Definition date.lib.php:665
dol_get_next_day($day, $month, $year)
Return next day.
Definition date.lib.php:509
dol_get_next_week($day, $week, $month, $year)
Return next week.
Definition date.lib.php:583
dol_get_first_day_week($day, $month, $year, $gm=false)
Return first day of week for a date.
Definition date.lib.php:680
dol_get_prev_day($day, $month, $year)
Return previous day.
Definition date.lib.php:493
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:605
dol_get_next_month($month, $year)
Return next month.
Definition date.lib.php:543
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition date.lib.php:436
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:624
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
dol_sanitizePathName($str, $newstr='_', $unaccent=0, $allowdash=0)
Clean a string to use it as a path name.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
getDolUserString($key, $default='', $tmpuser=null)
Return Dolibarr user constant string value.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='', $cssfordropdown='info_admin')
Show information in HTML for admin users or standard users.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Definition html.lib.php:172
conf($dolibarr_main_document_root, $realpathconf=null)
Load conf file (file must exists)
Definition inc.php:431
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
Definition receipt.php:487
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.