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