dolibarr 23.0.4
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-2025 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2024-2025 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', 5);
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$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}
161if (GETPOST('viewcal') && GETPOST('mode') != 'show_day' && GETPOST('mode') != 'show_week') {
162 $mode = 'show_month';
163 $day = '';
164} // View by month
165if (GETPOST('viewweek') || GETPOST('mode') == 'show_week') {
166 $mode = 'show_week';
167 $week = ($week ? $week : date("W"));
168 $day = ($day ? $day : date("d"));
169} // View by week
170if (GETPOST('viewday') || GETPOST('mode') == 'show_day') {
171 $mode = 'show_day';
172 $day = ($day ? $day : date("d"));
173} // View by day
174
175$object = new ActionComm($db);
176
177// Load translation files required by the page
178$langs->loadLangs(array('agenda', 'other', 'commercial'));
179
180// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
181$hookmanager->initHooks(array('agenda'));
182
183$result = restrictedArea($user, 'agenda', 0, 'actioncomm&societe', 'myactions|allactions', 'fk_soc', 'id');
184if ($user->socid && $socid) {
185 $result = restrictedArea($user, 'societe', $socid);
186}
187
188require_once DOL_DOCUMENT_ROOT.'/core/redirect_if_setup_not_complete.inc.php';
189
190
191/*
192 * Actions
193 */
194
195if (GETPOST("viewlist", 'alpha') || $mode == 'show_list') {
196 $param = '';
197 if (is_array($_POST)) {
198 foreach ($_POST as $key => $val) {
199 if ($key == 'token') {
200 continue;
201 }
202 $param .= '&'.urlencode($key).'='.urlencode($val);
203 }
204 }
205 if (!preg_match('/action=/', $param)) {
206 $param .= ($param ? '&' : '').'mode=show_list';
207 }
208 //print $param;
209 header("Location: ".DOL_URL_ROOT.'/comm/action/list.php?'.$param);
210 exit;
211}
212
213if (GETPOST("viewperuser", 'alpha') || $mode == 'show_peruser') {
214 $param = '';
215 if (is_array($_POST)) {
216 foreach ($_POST as $key => $val) {
217 if ($key == 'token') {
218 continue;
219 }
220 $param .= '&'.urlencode($key).'='.urlencode($val);
221 }
222 }
223 //print $param;
224 header("Location: ".DOL_URL_ROOT.'/comm/action/peruser.php?'.$param);
225 exit;
226}
227
228
229/*
230 * View
231 */
232
233$parameters = array(
234 'socid' => $socid,
235 'status' => $status,
236 'year' => $year,
237 'month' => $month,
238 'day' => $day,
239 'type' => $type,
240 'maxprint' => $maxprint,
241 'filter' => $filter,
242 'filtert' => $filtert,
243 'showbirthday' => $check_birthday,
244 'canedit' => $canedit,
245 'optioncss' => $optioncss,
246 'actioncode' => $actioncode,
247 'pid' => $pid,
248 'resourceid' => $resourceid,
249 'usergroup' => $usergroup,
250);
251$reshook = $hookmanager->executeHooks('beforeAgenda', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
252if ($reshook < 0) {
253 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
254}
255
256$form = new Form($db);
257$companystatic = new Societe($db);
258$contactstatic = new Contact($db);
259$userstatic = new User($db);
260
261$help_url = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:M&oacute;dulo_Agenda|DE:Modul_Terminplanung';
262llxHeader('', $langs->trans("Agenda"), $help_url);
263
264$now = dol_now();
265$nowarray = dol_getdate($now);
266$nowyear = $nowarray['year'];
267$nowmonth = $nowarray['mon'];
268$nowday = $nowarray['mday'];
269
270$listofextcals = array();
271
272// Define list of external calendars (global admin setup)
273if (!getDolGlobalString('AGENDA_DISABLE_EXT')) {
274 $i = 0;
275 while ($i < $MAXAGENDA) {
276 $i++;
277 $source = 'AGENDA_EXT_SRC'.$i;
278 $name = 'AGENDA_EXT_NAME'.$i;
279 $offsettz = 'AGENDA_EXT_OFFSETTZ'.$i;
280 $color = 'AGENDA_EXT_COLOR'.$i;
281 $default = 'AGENDA_EXT_ACTIVEBYDEFAULT'.$i;
282 $buggedfile = 'AGENDA_EXT_BUGGEDFILE'.$i;
283 if (getDolGlobalString($source) && getDolGlobalString($name)) {
284 // Note: $conf->global->buggedfile can be empty or 'uselocalandtznodaylight' or 'uselocalandtzdaylight'
285 $listofextcals[] = array(
286 'type' => 'globalsetup',
287 'src' => getDolGlobalString($source),
289 'offsettz' => (int) getDolGlobalInt($offsettz, 0),
290 'color' => dol_string_nohtmltag(getDolGlobalString($color)),
291 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
292 'default' => dol_string_nohtmltag(getDolGlobalString($default)),
293 'buggedfile' => dol_string_nohtmltag(getDolGlobalString($buggedfile, ''))
294 );
295 }
296 }
297}
298
299// Define list of external calendars (user setup)
300if (!getDolUserString('AGENDA_DISABLE_EXT')) {
301 $i = 0;
302 while ($i < $MAXAGENDA) {
303 $i++;
304 $source = 'AGENDA_EXT_SRC_'.$user->id.'_'.$i;
305 $name = 'AGENDA_EXT_NAME_'.$user->id.'_'.$i;
306 $offsettz = 'AGENDA_EXT_OFFSETTZ_'.$user->id.'_'.$i;
307 $color = 'AGENDA_EXT_COLOR_'.$user->id.'_'.$i;
308 $enabled = 'AGENDA_EXT_ENABLED_'.$user->id.'_'.$i;
309 $default = 'AGENDA_EXT_ACTIVEBYDEFAULT_'.$user->id.'_'.$i;
310 $buggedfile = 'AGENDA_EXT_BUGGEDFILE_'.$user->id.'_'.$i;
311
312 if (getDolUserString($source) && getDolUserString($name)) {
313 // Note: $conf->global->buggedfile can be empty or 'uselocalandtznodaylight' or 'uselocalandtzdaylight'
314 $listofextcals[] = array(
315 'type' => 'usersetup',
316 'src' => getDolUserString($source),
317 'name' => dol_string_nohtmltag(getDolUserString($name)),
318 'offsettz' => (int) (empty($user->conf->$offsettz) ? 0 : $user->conf->$offsettz),
319 'color' => dol_string_nohtmltag(getDolUserString($color)),
320 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
321 'default' => dol_string_nohtmltag(getDolUserString($default)),
322 'buggedfile' => dol_string_nohtmltag(getDolUserString($buggedfile, ''))
323 );
324 }
325 }
326}
327$firstdaytoshow = 0;
328$max_day_in_month = 0;
329$lastdaytoshow = 0;
330$tmpday = 0;
331$datestart = 0;
332$dateend = 0;
333$first_day = 0;
334$first_month = 0;
335$first_year = 0;
336$prev_day = 0;
337$prev_month = 0;
338$prev_year = 0;
339$max_day_in_prev_month = 0;
340$next_day = 0;
341$next_month = 0;
342$next_year = 0;
343if (empty($mode) || $mode == 'show_month') {
344 $prev = dol_get_prev_month($month, $year);
345 $prev_year = $prev['year'];
346 $prev_month = $prev['month'];
347 $next = dol_get_next_month($month, $year);
348 $next_year = $next['year'];
349 $next_month = $next['month'];
350
351 $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
352 $max_day_in_month = (int) date("t", dol_mktime(12, 0, 0, $month, 1, $year, 'gmt')); // Nb of days in next month
353 // 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)
354 $tmpday = - (int) date("w", dol_mktime(12, 0, 0, $month, 1, $year, 'gmt')) + 2; // date('w') is 0 for sunday
355 $tmpday += (getDolGlobalInt('MAIN_START_WEEK', 1) - 1);
356 if ($tmpday >= 1) {
357 $tmpday -= 7; // If tmpday is 0 we start with sunday, if -6, we start with monday of previous week.
358 }
359 // Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1)
360 $firstdaytoshow = dol_mktime(0, 0, 0, $prev_month, $max_day_in_prev_month + $tmpday, $prev_year, 'tzuserrel');
361 $next_day = 7 - ($max_day_in_month + 1 - $tmpday) % 7;
362 if ($next_day < 6) {
363 $next_day += 7;
364 }
365 $lastdaytoshow = dol_mktime(0, 0, 0, $next_month, $next_day, $next_year, 'tzuserrel');
366}
367if ($mode == 'show_week') {
368 $prev = dol_get_first_day_week($day, $month, $year);
369 $prev_year = $prev['prev_year'];
370 $prev_month = $prev['prev_month'];
371 $prev_day = $prev['prev_day'];
372 $first_day = $prev['first_day'];
373 $first_month = $prev['first_month'];
374 $first_year = $prev['first_year'];
375
376 $week = $prev['week'];
377
378 $day = (int) $day;
379 $next = dol_get_next_week($first_day, (int) $week, $first_month, $first_year);
380 $next_year = $next['year'];
381 $next_month = $next['month'];
382 $next_day = $next['day'];
383
384 // Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1)
385 $firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'tzuserrel');
386 $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, 7, 'd');
387
388 $max_day_in_month = date("t", dol_mktime(0, 0, 0, $month, 1, $year, 'gmt'));
389
390 $tmpday = $first_day;
391}
392if ($mode == 'show_day') {
393 $prev = dol_get_prev_day($day, $month, $year);
394 $prev_year = $prev['year'];
395 $prev_month = $prev['month'];
396 $prev_day = $prev['day'];
397 $next = dol_get_next_day($day, $month, $year);
398 $next_year = $next['year'];
399 $next_month = $next['month'];
400 $next_day = $next['day'];
401 // Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1)
402 $firstdaytoshow = dol_mktime(0, 0, 0, $prev_month, $prev_day, $prev_year, 'tzuserrel');
403 $lastdaytoshow = dol_mktime(0, 0, 0, $next_month, $next_day, $next_year, 'tzuserrel');
404}
405//print 'xx'.$prev_year.'-'.$prev_month.'-'.$prev_day;
406//print 'xx'.$next_year.'-'.$next_month.'-'.$next_day;
407//print dol_print_date($firstdaytoshow,'dayhour').' '.dol_print_date($lastdaytoshow,'dayhour');
408
409/*$title = $langs->trans("DoneAndToDoActions");
410if ($status == 'done') {
411 $title = $langs->trans("DoneActions");
412}
413if ($status == 'todo') {
414 $title = $langs->trans("ToDoActions");
415}
416*/
417
418$param = '';
419if ($actioncode || GETPOSTISSET('search_actioncode')) {
420 if (is_array($actioncode)) {
421 foreach ($actioncode as $str_action) {
422 $param .= "&search_actioncode[]=".urlencode($str_action);
423 }
424 } else {
425 $param .= "&search_actioncode=".urlencode($actioncode);
426 }
427}
428if ($resourceid > 0) {
429 $param .= "&search_resourceid=".urlencode((string) ($resourceid));
430}
431if ($status || GETPOSTISSET('status') || GETPOSTISSET('search_status')) {
432 $param .= "&search_status=".urlencode($status);
433}
434if ($filter) {
435 $param .= "&search_filter=".urlencode((string) $filter);
436}
437if ($filtert) {
438 $param .= "&search_filtert=".urlencode((string) $filtert);
439}
440if ($usergroup > 0) {
441 $param .= "&search_usergroup=".urlencode((string) ($usergroup));
442}
443if ($socid > 0) {
444 $param .= "&search_socid=".urlencode((string) ($socid));
445}
446if ($check_birthday) {
447 $param .= "&check_birthday=1";
448}
449if ($check_holiday) {
450 $param .= "&check_holiday=1";
451}
452if ($pid) {
453 $param .= "&search_projectid=".urlencode((string) ($pid));
454}
455if ($type) {
456 $param .= "&search_type=".urlencode($type);
457}
458$param .= "&maxprint=".urlencode((string) ($maxprint));
459if ($mode == 'show_day' || $mode == 'show_week' || $mode == 'show_month') {
460 $param .= '&mode='.urlencode($mode);
461}
462if ($search_categ_cus != 0) {
463 $param .= '&search_categ_cus='.urlencode((string) ($search_categ_cus));
464}
465if ($check_holiday) {
466 $param .= '&check_holiday=1';
467}
468
469// Show navigation bar
470$nav = '';
471$nav .= '<div class="navselectiondate inline-block nowraponall">';
472if (empty($mode) || $mode == 'show_month') {
473 $nav .= "<a href=\"?year=".$prev_year."&month=".$prev_month.$param."\"><i class=\"fa fa-chevron-left\"></i></a> &nbsp;\n";
474 $nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $month, 1, $year), "%b %Y");
475 $nav .= " </span>\n";
476 $nav .= " &nbsp; <a href=\"?year=".$next_year."&month=".$next_month.$param."\"><i class=\"fa fa-chevron-right\"></i></a>\n";
477 $picto = 'calendar';
478}
479if ($mode == 'show_week') {
480 $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";
481 $nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $first_month, $first_day, $first_year), "%Y").", ".$langs->trans("WeekShort")." ".$week;
482 $nav .= " </span>\n";
483 $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";
484 $picto = 'calendarweek';
485}
486if ($mode == 'show_day') {
487 $nav .= "<a href=\"?year=".$prev_year."&month=".$prev_month."&day=".$prev_day.$param."\"><i class=\"fa fa-chevron-left\"></i></a> &nbsp;\n";
488 $nav .= " <span id=\"month_name\">".dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "daytextshort");
489 $nav .= " </span>\n";
490 $nav .= " &nbsp; <a href=\"?year=".$next_year."&month=".$next_month."&day=".$next_day.$param."\"><i class=\"fa fa-chevron-right\"></i></a>\n";
491 $picto = 'calendarday';
492}
493if (empty($conf->dol_optimize_smallscreen)) {
494 $nav .= ' <a href="?year='.$nowyear.'&month='.$nowmonth.'&day='.$nowday.$param.'" class="datenowlink marginleftonly marginrightonly">'.$langs->trans("Today").'</a> ';
495}
496$nav .= '</div>';
497
498$nav .= $form->selectDate($dateselect, 'dateselect', 0, 0, 1, '', 1, 0);
499//$nav .= ' <input type="submit" class="button button-save" name="submitdateselect" value="'.$langs->trans("Refresh").'">';
500$nav .= '<button type="submit" class="liste_titre button_search valignmiddle" name="button_search_x" value="x"><span class="fa fa-search"></span></button>';
501
502// Must be after the nav definition
503$paramnodate = $param;
504$param .= '&year='.$year.'&month='.$month.($day ? '&day='.$day : '');
505//print 'x'.$param;
506
507
508
509
510/*$tabactive = '';
511 if ($mode == 'show_month') $tabactive = 'cardmonth';
512 if ($mode == 'show_week') $tabactive = 'cardweek';
513 if ($mode == 'show_day') $tabactive = 'cardday';
514 if ($mode == 'show_list') $tabactive = 'cardlist';
515 if ($mode == 'show_pertuser') $tabactive = 'cardperuser';
516 if ($mode == 'show_pertype') $tabactive = 'cardpertype';
517 */
518
519$paramnoaction = preg_replace('/mode=[a-z_]+/', '', preg_replace('/action=[a-z_]+/', '', $param));
520$paramnoactionodate = preg_replace('/mode=[a-z_]+/', '', preg_replace('/action=[a-z_]+/', '', $paramnodate));
521
522$head = calendars_prepare_head($paramnoaction);
523
524print '<form method="POST" id="searchFormList" class="listactionsfilter" action="'.$_SERVER["PHP_SELF"].'">'."\n";
525if ($optioncss != '') {
526 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
527}
528print '<input type="hidden" name="token" value="'.newToken().'">';
529print '<input type="hidden" name="mode" value="'.$mode.'">';
530
531
532$viewmode = '<div class="navmode inline-block">';
533
534$viewmode .= '<a class="btnTitle'.($mode == 'list' ? ' btnTitleSelected' : '').' reposition" href="'.DOL_URL_ROOT.'/comm/action/list.php?mode=show_list&restore_lastsearch_values=1'.$paramnoactionodate.'">';
535//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
536$viewmode .= img_picto($langs->trans("List"), 'object_calendarlist', 'class="imgforviewmode pictoactionview block"');
537//$viewmode .= '</span>';
538$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewList").'</span></a>';
539
540$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.'">';
541//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
542$viewmode .= img_picto($langs->trans("ViewCal"), 'object_calendarmonth', 'class="pictoactionview block"');
543//$viewmode .= '</span>';
544$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewCal").'</span></a>';
545
546$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.'">';
547//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
548$viewmode .= img_picto($langs->trans("ViewWeek"), 'object_calendarweek', 'class="pictoactionview block"');
549//$viewmode .= '</span>';
550$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewWeek").'</span></a>';
551
552$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.'">';
553//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
554$viewmode .= img_picto($langs->trans("ViewDay"), 'object_calendarday', 'class="pictoactionview block"');
555//$viewmode .= '</span>';
556$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow">'.$langs->trans("ViewDay").'</span></a>';
557
558$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.'">';
559//$viewmode .= '<span class="fa paddingleft imgforviewmode valignmiddle btnTitle-icon">';
560$viewmode .= img_picto($langs->trans("ViewPerUser"), 'object_calendarperuser', 'class="pictoactionview block"');
561//$viewmode .= '</span>';
562$viewmode .= '<span class="valignmiddle text-plus-circle btnTitle-label hideonsmartphone inline-block width75 divoverflow" title="'.dolPrintHTML($langs->trans("ViewPerUser")).'">'.$langs->trans("ViewPerUser").'</span></a>';
563
564// Add more views from hooks
565$parameters = array();
566$object = null;
567$reshook = $hookmanager->executeHooks('addCalendarView', $parameters, $object, $action);
568if (empty($reshook)) {
569 $viewmode .= $hookmanager->resPrint;
570} elseif ($reshook > 1) {
571 $viewmode = $hookmanager->resPrint;
572}
573
574$viewmode .= '</div>';
575
576$viewmode .= '<span class="marginrightonly"></span>'; // To add a space before the navigation tools
577
578
579$newparam = '';
580$newcardbutton = '';
581if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) {
582 $tmpforcreatebutton = dol_getdate(dol_now('tzuserrel'), true, 'gmt');
583
584 $newparam .= '&month='.((int) $month).'&year='.((int) $tmpforcreatebutton['year']).'&mode='.urlencode($mode);
585
586 //$param='month='.$monthshown.'&year='.$year;
587 //$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
588
589 $urltocreateaction = DOL_URL_ROOT.'/comm/action/card.php?action=create';
590 $urltocreateaction .= '&apyear='.$tmpforcreatebutton['year'].'&apmonth='.$tmpforcreatebutton['mon'].'&apday='.$tmpforcreatebutton['mday'].'&aphour='.$tmpforcreatebutton['hours'].'&apmin='.$tmpforcreatebutton['minutes'];
591 $urltocreateaction .= '&backtopage='.urlencode($_SERVER["PHP_SELF"].($newparam ? '?'.$newparam : ''));
592
593 $newcardbutton .= dolGetButtonTitle($langs->trans("AddAction"), '', 'fa fa-plus-circle', $urltocreateaction);
594}
595
596// Define the legend/list of calendard to show
597$s = '';
598
599
600$showextcals = $listofextcals;
601$bookcalcalendars = array();
602
603// Load Bookcal Calendars
604if (isModEnabled("bookcal")) {
605 $sql = "SELECT ba.rowid, bc.label, bc.ref, bc.rowid as id_cal";
606 $sql .= " FROM ".MAIN_DB_PREFIX."bookcal_availabilities as ba";
607 $sql .= " JOIN ".MAIN_DB_PREFIX."bookcal_calendar as bc";
608 $sql .= " ON bc.rowid = ba.fk_bookcal_calendar";
609 $sql .= " WHERE bc.status = 1";
610 $sql .= " AND ba.status = 1";
611 $sql .= " AND bc.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda
612 if (!empty($filtert) && $filtert != '-1') {
613 $sql .= " AND bc.visibility IN (".$db->sanitize($filtert, 0, 0, 0, 0).")";
614 }
615 $resql = $db->query($sql);
616 if ($resql) {
617 $num = $db->num_rows($resql);
618 $i = 0;
619 while ($i < $num) {
620 $objp = $db->fetch_object($resql);
621 $label = !empty($objp->label) ? $objp->label : $objp->ref;
622 $bookcalcalendars["calendars"][$objp->id_cal] = array("id" => $objp->id_cal, "label" => $label);
623 $bookcalcalendars["availabilitieslink"][$objp->rowid] = $objp->id_cal;
624 $i++;
625 }
626 } else {
627 dol_print_error($db);
628 }
629}
630
631if (!empty($conf->use_javascript_ajax)) { // If javascript on
632 $s .= "\n".'<!-- Div to calendars selectors -->'."\n";
633
634 $s .= '<script type="text/javascript">'."\n";
635 $s .= 'jQuery(document).ready(function () {'."\n";
636 $s .= 'jQuery(".check_birthday").click(function() { console.log("Toggle class .family_birthday"); jQuery(".family_birthday").toggle(); });'."\n";
637 $s .= 'jQuery(".check_holiday").click(function() { console.log("Toggle class .family_holiday"); jQuery(".family_holiday").toggle(); jQuery(this).closest("form").submit(); });'."\n";
638 if (isModEnabled("bookcal") && !empty($bookcalcalendars["calendars"])) {
639 foreach ($bookcalcalendars["calendars"] as $key => $value) {
640 $s .= 'jQuery(".check_bookcal_calendar_'.$value['id'].'").click(function() { console.log("Toggle Bookcal Calendar '.$value['id'].'"); jQuery(".family_bookcal_calendar_'.$value['id'].'").toggle(); });'."\n";
641 }
642 }
643 if ($mode == "show_week" || $mode == "show_month" || empty($mode)) {
644 // Code to enable drag and drop
645 $s .= 'jQuery( "div.sortable" ).sortable({connectWith: ".sortable", placeholder: "ui-state-highlight", items: "div.movable", receive: function( event, ui ) {'."\n";
646 // Code to submit form
647 $s .= 'console.log("submit form to record new event");'."\n";
648 //$s.='console.log(event.target);';
649 $s .= 'var newval = jQuery(event.target).closest("div.dayevent").attr("id");'."\n";
650 $s .= 'console.log("found parent div.dayevent with id = "+newval);'."\n";
651 $s .= 'var frm=jQuery("#searchFormList");'."\n";
652 $s .= 'var newurl = ui.item.find("a.cal_event").attr("href");'."\n";
653 $s .= 'console.log("Found url on href of a.cal_event"+newurl+", we submit form with actionmove=mupdate");'."\n";
654 $s .= 'frm.attr("action", newurl).children("#newdate").val(newval);frm.submit();}'."\n";
655 $s .= '});'."\n";
656 }
657 $s .= '});'."\n";
658 $s .= '</script>'."\n";
659
660 // Local calendar
661 $s .= '<div class="nowrap inline-block minheight30"><input type="checkbox" id="check_mytasks" name="check_mytasks" value="1" checked disabled><label class="labelcalendar"><span class="check_holiday_text"> '.$langs->trans("LocalAgenda").' &nbsp; </span></label></div>';
662
663 // Holiday calendar
664 if ($user->hasRight("holiday", "read")) {
665 $s .= '
666 <div class="nowrap inline-block minheight30"><input type="checkbox" id="check_holiday" name="check_holiday" value="1" class="marginleftonly check_holiday"' . ($check_holiday
667 ? ' checked' : '') . '>
668 <label for="check_holiday" class="labelcalendar">
669 <span class="check_holiday_text">' . $langs->trans("Holidays") . '</span>
670 </label> &nbsp;
671 </div>';
672 }
673
674 // External calendars
675 if (is_array($showextcals) && count($showextcals) > 0) {
676 $s .= '<script type="text/javascript">'."\n";
677 $s .= 'jQuery(document).ready(function () {
678 jQuery("div input[name^=\"check_ext\"]").each(function(index, elem) {
679 var name = jQuery(elem).attr("name");
680 if (jQuery(elem).is(":checked")) {
681 jQuery(".family_ext" + name.replace("check_ext", "")).show();
682 } else {
683 jQuery(".family_ext" + name.replace("check_ext", "")).hide();
684 }
685 });
686
687 jQuery("div input[name^=\"check_ext\"]").click(function() {
688 var name = $(this).attr("name");
689 jQuery(".family_ext" + name.replace("check_ext", "")).toggle();
690 });
691 });' . "\n";
692 $s .= '</script>'."\n";
693
694 foreach ($showextcals as $val) {
695 $htmlname = md5($val['name']); // not used for security purpose, only to get a string with no special char
696
697 if (!empty($val['default']) || GETPOSTINT('check_ext'.$htmlname)) {
698 $default = "checked";
699 } else {
700 $default = '';
701 }
702
703 $tooltip = $langs->trans("Cache").' '.round($DELAYFORCACHE / 60).'mn';
704
705 $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">'.dol_escape_htmltag($val['name']).'</label> &nbsp; </div>';
706 }
707 }
708
709 // Birthdays
710 $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">'.$langs->trans("AgendaShowBirthdayEvents").'</span></label> &nbsp; </div>';
711
712 // Bookcal Calendar
713 if (isModEnabled("bookcal")) {
714 if (!empty($bookcalcalendars["calendars"])) {
715 foreach ($bookcalcalendars["calendars"] as $key => $value) {
716 $label = $value['label'];
717 $s .= '<div class="nowrap inline-block minheight30">';
718 $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'].'">';
719 $s .= '<label for="check_bookcal_calendar_'.$value['id'].'" class="labelcalendar">';
720 $s .= '<span class="check_bookcal_calendar_'.$value['id'].'_text">'.$langs->trans("AgendaShowBookcalCalendar", $label).'</span>';
721 $s .= '</label> &nbsp; </div>';
722 }
723 }
724 }
725
726 // Calendars from hooks
727 $parameters = array();
728 $reshook = $hookmanager->executeHooks('addCalendarChoice', $parameters, $object, $action);
729 if (empty($reshook)) {
730 $s .= $hookmanager->resPrint;
731 } elseif ($reshook > 1) {
732 $s = $hookmanager->resPrint;
733 }
734
735 $s .= "\n".'<!-- End div to calendars selectors -->'."\n";
736} else { // If javascript off
737 $newparam = $param; // newparam is for birthday links
738 $newparam = preg_replace('/check_birthday=[0-1]/i', 'check_birthday='.(empty($check_birthday) ? 1 : 0), $newparam);
739 if (!preg_match('/check_birthday=/i', $newparam)) {
740 $newparam .= '&check_birthday=1';
741 }
742 $s = '<a href="'.$_SERVER['PHP_SELF'].'?'.dol_escape_htmltag($newparam);
743 $s .= '">';
744 if (empty($check_birthday)) {
745 $s .= $langs->trans("AgendaShowBirthdayEvents");
746 } else {
747 $s .= $langs->trans("AgendaHideBirthdayEvents");
748 }
749 $s .= '</a>';
750}
751
752
753// Load events from database into $eventarray
754$eventarray = array();
755$nbevents = 0;
756
757// DEFAULT CALENDAR + AUTOEVENT CALENDAR + CONFERENCEBOOTH CALENDAR
758$sql = 'SELECT ';
759if ($usergroup > 0) {
760 $sql .= " DISTINCT";
761}
762$sql .= ' a.id, a.label,';
763$sql .= ' a.datep,';
764$sql .= ' a.datep2,';
765$sql .= ' a.percent,';
766$sql .= ' a.fk_user_author,a.fk_user_action,';
767$sql .= ' a.transparency, a.priority, a.fulldayevent, a.location,';
768$sql .= ' a.fk_soc, a.fk_contact, a.fk_project, a.fk_bookcal_calendar,';
769$sql .= ' a.fk_element, a.elementtype,';
770$sql .= ' ca.code as type_code, ca.libelle as type_label, ca.color as type_color, ca.type as type_type, ca.picto as type_picto';
771
772// Add fields from hooks
773$parameters = array();
774$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
775$sql .= $hookmanager->resPrint;
776
777$sqlfields = $sql; // $sql fields to remove for count total
778
779$sql .= " FROM ".MAIN_DB_PREFIX."c_actioncomm as ca, ".MAIN_DB_PREFIX."actioncomm as a";
780
781// We must filter on assignment table
782if (($filtert != '-1' && $filtert != '-2') || $usergroup > 0) {
783 // TODO Replace with a AND EXISTS
784 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as ar ON ar.fk_actioncomm = a.id AND ar.element_type = 'user'";
785 if ($filtert != '-1' && $filtert != '-2' && $filtert != '-3') {
786 $sql .= " AND (ar.fk_element IN (".$db->sanitize($filtert).") OR (ar.fk_element IS NULL AND a.fk_user_action = ".((int) $filtert)."))"; // The OR is for backward compatibility
787 } elseif ($filtert == '-3') {
788 $sql .= " AND ar.fk_element IN (".$db->sanitize(implode(',', $user->getAllChildIds(1))).")";
789 }
790 if ($usergroup > 0) {
791 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element AND ugu.fk_usergroup = ".((int) $usergroup);
792 }
793}
794
795// We must filter on resource table
796if ($resourceid > 0) {
797 $sql .= ", ".MAIN_DB_PREFIX."element_resources as r";
798}
799
800// Add table from hooks
801$parameters = array();
802$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
803$sql .= $hookmanager->resPrint;
804
805$sql .= " WHERE a.fk_action = ca.id";
806$sql .= " AND a.entity IN (".getEntity('agenda').")"; // bookcal is a "virtual view" of agenda
807// Condition on actioncode
808if (!empty($actioncode)) {
809 if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
810 if ((is_array($actioncode) && in_array('AC_NON_AUTO', $actioncode)) || $actioncode == 'AC_NON_AUTO') {
811 $sql .= " AND ca.type != 'systemauto'";
812 } elseif ((is_array($actioncode) && in_array('AC_ALL_AUTO', $actioncode)) || $actioncode == 'AC_ALL_AUTO') {
813 $sql .= " AND ca.type = 'systemauto'";
814 } else {
815 if ((is_array($actioncode) && in_array('AC_OTH', $actioncode)) || $actioncode == 'AC_OTH') {
816 $sql .= " AND ca.type != 'systemauto'";
817 }
818 if ((is_array($actioncode) && in_array('AC_OTH_AUTO', $actioncode)) || $actioncode == 'AC_OTH_AUTO') {
819 $sql .= " AND ca.type = 'systemauto'";
820 }
821 }
822 } else {
823 if ((is_array($actioncode) && in_array('AC_NON_AUTO', $actioncode)) || $actioncode === 'AC_NON_AUTO') {
824 $sql .= " AND ca.type != 'systemauto'";
825 } elseif ((is_array($actioncode) && in_array('AC_ALL_AUTO', $actioncode)) || $actioncode === 'AC_ALL_AUTO') {
826 $sql .= " AND ca.type = 'systemauto'";
827 } else {
828 if (is_array($actioncode)) {
829 // Remove all -1 values
830 $actioncode = array_filter(
831 $actioncode,
836 function ($value) {
837 return ((string) $value !== '-1');
838 }
839 );
840 if (count($actioncode)) {
841 $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", $actioncode)."'", 1).")";
842 }
843 } elseif ($actioncode !== '-1') {
844 $sql .= " AND ca.code IN (".$db->sanitize("'".implode("','", explode(',', $actioncode))."'", 1).")";
845 }
846 }
847 }
848}
849if ($resourceid > 0) {
850 $sql .= " AND r.element_type = 'action' AND r.element_id = a.id AND r.resource_id = ".((int) $resourceid);
851}
852if ($pid) {
853 $sql .= " AND a.fk_project=".((int) $pid);
854}
855// If the internal user must only see his customers, force searching by him
856$search_sale = 0;
857if (isModEnabled("societe") && !$user->hasRight('societe', 'client', 'voir')) {
858 $search_sale = $user->id;
859}
860// Search on sale representative
861if ($search_sale && $search_sale != '-1') {
862 if ($search_sale == -2) {
863 $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = a.fk_soc)";
864 } elseif ($search_sale > 0) {
865 $sql .= " AND (a.fk_soc IS NULL OR EXISTS (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = a.fk_soc AND sc.fk_user = ".((int) $search_sale)."))";
866 }
867}
868// Search on socid
869if ($socid > 0) {
870 $sql .= " AND a.fk_soc = ".((int) $socid);
871}
872//var_dump($day.' '.$month.' '.$year);
873if ($mode == 'show_day') {
874 $sql .= " AND (";
875 $sql .= " (a.datep BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'";
876 $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')";
877 $sql .= " OR ";
878 $sql .= " (a.datep2 BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'";
879 $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')";
880 $sql .= " OR ";
881 $sql .= " (a.datep < '".$db->idate(dol_mktime(0, 0, 0, $month, $day, $year, 'tzuserrel'))."'";
882 $sql .= " AND a.datep2 > '".$db->idate(dol_mktime(23, 59, 59, $month, $day, $year, 'tzuserrel'))."')";
883 $sql .= ')';
884} else {
885 // To limit array
886 $sql .= " AND (";
887 $sql .= " (a.datep BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, 1, $year) - (60 * 60 * 24 * 7))."'"; // Start 7 days before
888 $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, 28, $year) + (60 * 60 * 24 * 10))."')"; // End 7 days after + 3 to go from 28 to 31
889 $sql .= " OR ";
890 $sql .= " (a.datep2 BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month, 1, $year) - (60 * 60 * 24 * 7))."'";
891 $sql .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month, 28, $year) + (60 * 60 * 24 * 10))."')";
892 $sql .= " OR ";
893 $sql .= " (a.datep < '".$db->idate(dol_mktime(0, 0, 0, $month, 1, $year) - (60 * 60 * 24 * 7))."'";
894 $sql .= " AND a.datep2 > '".$db->idate(dol_mktime(23, 59, 59, $month, 28, $year) + (60 * 60 * 24 * 10))."')";
895 $sql .= ')';
896}
897if ($type) {
898 $sql .= " AND ca.id = ".((int) $type);
899}
900if ($status == '0') {
901 // To do (not started)
902 $sql .= " AND a.percent = 0";
903}
904if ($status === 'na') {
905 // Not applicable
906 $sql .= " AND a.percent = -1";
907}
908if ($status == '50') {
909 // Running already started
910 $sql .= " AND (a.percent > 0 AND a.percent < 100)";
911}
912if ($status == 'done' || $status == '100') {
913 $sql .= " AND (a.percent = 100)";
914}
915if ($status == 'todo') {
916 $sql .= " AND (a.percent >= 0 AND a.percent < 100)";
917}
918
919// Search in categories, -1 is all and -2 is no categories
920if ($search_categ_cus != -1) {
921 if ($search_categ_cus == -2) {
922 $sql .= " AND NOT EXISTS (SELECT ca.fk_actioncomm FROM ".MAIN_DB_PREFIX."categorie_actioncomm as ca WHERE ca.fk_actioncomm = a.id)";
923 } elseif ($search_categ_cus > 0) {
924 $sql .= " AND EXISTS (SELECT ca.fk_actioncomm FROM ".MAIN_DB_PREFIX."categorie_actioncomm as ca WHERE ca.fk_actioncomm = a.id AND ca.fk_categorie IN (".$db->sanitize($search_categ_cus)."))";
925 }
926}
927
928// Sort on date
929$sql .= $db->order("datep");
930
931$MAXONSAMEPAGE = 5000; // Useless to have more. Protection to avoid memory overload when high number of event (for example after a mass import)
932
933$sql .= $db->plimit($MAXONSAMEPAGE + 1);
934
935dol_syslog("comm/action/index.php", LOG_DEBUG);
936
937$resql = $db->query($sql);
938if ($resql) {
939 $num = $db->num_rows($resql);
940 $nbevents += $num;
941
942 $i = 0;
943 while ($i < $num && $i < $MAXONSAMEPAGE) {
944 $obj = $db->fetch_object($resql);
945
946 // Discard auto action if option is on
947 if (getDolGlobalString('AGENDA_ALWAYS_HIDE_AUTO') && $obj->type_code == 'AC_OTH_AUTO') {
948 $i++;
949 continue;
950 }
951
952 // Create a new object action
953 $event = new ActionComm($db);
954
955 $event->id = $obj->id;
956 $event->ref = (string) $event->id;
957
958 $event->fulldayevent = $obj->fulldayevent;
959
960 // event->datep and event->datef must be GMT date.
961 if ($event->fulldayevent) {
962 $tzforfullday = getDolGlobalString('MAIN_STORE_FULL_EVENT_IN_GMT');
963 $event->datep = $db->jdate($obj->datep, $tzforfullday ? 'tzuser' : 'tzserver'); // If saved in $tzforfullday = gmt, we must invert date to be in user tz
964 $event->datef = $db->jdate($obj->datep2, $tzforfullday ? 'tzuser' : 'tzserver');
965 } else {
966 // Example: $obj->datep = '1970-01-01 01:00:00', jdate will return 0 if TZ of PHP server is Europe/Berlin (+1)
967 $event->datep = $db->jdate($obj->datep, 'tzserver');
968 $event->datef = $db->jdate($obj->datep2, 'tzserver');
969 }
970 //$event->datep_formated_gmt = dol_print_date($event->datep, 'dayhour', 'gmt');
971 //var_dump($obj->id.' '.$obj->datep.' '.dol_print_date($obj->datep, 'dayhour', 'gmt'));
972 //var_dump($obj->id.' '.$event->datep.' '.dol_print_date($event->datep, 'dayhour', 'gmt'));
973
974 $event->type_code = $obj->type_code;
975 $event->type_label = $obj->type_label;
976 $event->type_color = $obj->type_color;
977 $event->type = $obj->type_type;
978 $event->type_picto = $obj->type_picto;
979
980 $event->label = $obj->label;
981 $event->percentage = $obj->percent;
982
983 $event->authorid = $obj->fk_user_author; // user id of creator
984 $event->userownerid = $obj->fk_user_action; // user id of owner
985 $event->fetch_userassigned(); // This load $event->userassigned
986
987 $event->priority = $obj->priority;
988 $event->location = $obj->location;
989 $event->transparency = $obj->transparency;
990 $event->fk_element = $obj->fk_element;
991 $event->elementid = $obj->fk_element;
992 $event->elementtype = $obj->elementtype;
993
994 $event->fk_project = $obj->fk_project;
995
996 $event->socid = $obj->fk_soc;
997 $event->contact_id = $obj->fk_contact;
998 $event->fk_bookcal_calendar = $obj->fk_bookcal_calendar;
999 if (!empty($event->fk_bookcal_calendar)) {
1000 $event->type = "bookcal_calendar";
1001 }
1002
1003 // Defined date_start_in_calendar and date_end_in_calendar property
1004 // They are date start and end of action but modified to not be outside calendar view.
1005 $event->date_start_in_calendar = $event->datep;
1006 if ($event->datef != '' && $event->datef >= $event->datep) {
1007 $event->date_end_in_calendar = $event->datef;
1008 } else {
1009 $event->date_end_in_calendar = $event->datep;
1010 }
1011
1012 // Check values
1013 if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) {
1014 // This record is out of visible range
1015 } else {
1016 if ($event->date_start_in_calendar < $firstdaytoshow) {
1017 $event->date_start_in_calendar = $firstdaytoshow;
1018 }
1019 if ($event->date_end_in_calendar >= $lastdaytoshow) {
1020 $event->date_end_in_calendar = ($lastdaytoshow - 1);
1021 }
1022
1023 // Add an entry in actionarray for each day
1024 $daycursor = $event->date_start_in_calendar;
1025 $annee = (int) dol_print_date($daycursor, '%Y', 'tzuserrel');
1026 $mois = (int) dol_print_date($daycursor, '%m', 'tzuserrel');
1027 $jour = (int) dol_print_date($daycursor, '%d', 'tzuserrel');
1028
1029 $daycursorend = $event->date_end_in_calendar;
1030 $anneeend = (int) dol_print_date($daycursorend, '%Y', 'tzuserrel');
1031 $moisend = (int) dol_print_date($daycursorend, '%m', 'tzuserrel');
1032 $jourend = (int) dol_print_date($daycursorend, '%d', 'tzuserrel');
1033
1034 //var_dump(dol_print_date($event->date_start_in_calendar, 'dayhour', 'gmt')); // Hour at greenwich
1035 //var_dump($annee.'-'.$mois.'-'.$jour);
1036 //print 'annee='.$annee.' mois='.$mois.' jour='.$jour.'<br>';
1037
1038 // Loop on each day covered by action to prepare an index to show on calendar
1039 $loop = true;
1040 $j = 0;
1041 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt'); // $mois, $jour, $annee has been set for user tz
1042 $daykeyend = dol_mktime(0, 0, 0, $moisend, $jourend, $anneeend, 'gmt'); // $moisend, $jourend, $anneeend has been set for user tz
1043 /*
1044 print 'GMT '.$event->date_start_in_calendar.' '.dol_print_date($event->date_start_in_calendar, 'dayhour', 'gmt').'<br>';
1045 print 'TZSERVER '.$event->date_start_in_calendar.' '.dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzserver').'<br>';
1046 print 'TZUSERREL '.$event->date_start_in_calendar.' '.dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzuserrel').'<br>';
1047 print 'GMT '.$event->date_end_in_calendar.' '.dol_print_date($event->date_end_in_calendar, 'dayhour', 'gmt').'<br>';
1048 print 'TZSERVER '.$event->date_end_in_calendar.' '.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzserver').'<br>';
1049 print 'TZUSER '.$event->date_end_in_calendar.' '.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzuserrel').'<br>';
1050 */
1051 do {
1052 //if ($event->id==408)
1053 //print 'daykey='.$daykey.' daykeyend='.$daykeyend.' '.dol_print_date($daykey, 'dayhour', 'gmt').' - '.dol_print_date($event->datep, 'dayhour', 'gmt').' '.dol_print_date($event->datef, 'dayhour', 'gmt').'<br>';
1054 //print 'daykey='.$daykey.' daykeyend='.$daykeyend.' '.dol_print_date($daykey, 'dayhour', 'tzuserrel').' - '.dol_print_date($event->datep, 'dayhour', 'tzuserrel').' '.dol_print_date($event->datef, 'dayhour', 'tzuserrel').'<br>';
1055
1056 $eventarray[$daykey][] = $event;
1057 $j++;
1058
1059 $daykey += 60 * 60 * 24;
1060 //if ($daykey > $event->date_end_in_calendar) {
1061 if ($daykey > $daykeyend) {
1062 $loop = false;
1063 }
1064 } while ($loop);
1065 //var_dump($eventarray);
1066 //print 'Event '.$i.' id='.$event->id.' (start='.dol_print_date($event->datep).'-end='.dol_print_date($event->datef);
1067 //print ' startincalendar='.dol_print_date($event->date_start_in_calendar).'-endincalendar='.dol_print_date($event->date_end_in_calendar).') was added in '.$j.' different index key of array<br>';
1068 }
1069
1070 $parameters['obj'] = $obj;
1071 $reshook = $hookmanager->executeHooks('hookEventElements', $parameters, $event, $action); // Note that $action and $object may have been modified by some hooks
1072 $event = $hookmanager->resPrint;
1073 if ($reshook < 0) {
1074 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1075 }
1076
1077 $i++;
1078 }
1079} else {
1080 dol_print_error($db);
1081}
1082//var_dump($eventarray);
1083
1084
1085// BIRTHDATES CALENDAR
1086// Complete $eventarray with birthdates
1087if ($check_birthday) {
1088 // Add events in array
1089 $sql = 'SELECT sp.rowid, sp.lastname, sp.firstname, sp.birthday';
1090 $sql .= ' FROM '.MAIN_DB_PREFIX.'socpeople as sp';
1091 $sql .= ' WHERE (priv=0 OR (priv=1 AND fk_user_creat='.((int) $user->id).'))';
1092 $sql .= " AND sp.entity IN (".getEntity('contact').")";
1093 if ($mode == 'show_day') {
1094 $sql .= ' AND MONTH(birthday) = '.((int) $month);
1095 $sql .= ' AND DAY(birthday) = '.((int) $day);
1096 } else {
1097 $sql .= ' AND MONTH(birthday) = '.((int) $month);
1098 }
1099 $sql .= ' ORDER BY birthday';
1100
1101 dol_syslog("comm/action/index.php", LOG_DEBUG);
1102 $resql = $db->query($sql);
1103 if ($resql) {
1104 $num = $db->num_rows($resql);
1105 $nbevents += $num;
1106
1107 $i = 0;
1108 while ($i < $num) {
1109 $obj = $db->fetch_object($resql);
1110
1111 $event = new ActionComm($db);
1112
1113 $event->id = $obj->rowid; // We put contact id in action id for birthdays events
1114 $event->ref = (string) $event->id;
1115
1116 $datebirth = dol_stringtotime($obj->birthday, 1);
1117 //print 'ee'.$obj->birthday.'-'.$datebirth;
1118 $datearray = dol_getdate($datebirth, true);
1119 $event->datep = dol_mktime(0, 0, 0, $datearray['mon'], $datearray['mday'], $year, true); // For full day events, date are also GMT but they won't but converted during output
1120 $event->datef = $event->datep;
1121
1122 $event->type_code = 'BIRTHDAY';
1123 $event->type_label = '';
1124 $event->type_color = '';
1125 $event->type = 'birthdate';
1126 $event->type_picto = 'birthdate';
1127
1128 $event->label = $langs->trans("Birthday").' '.dolGetFirstLastname($obj->firstname, $obj->lastname);
1129 $event->percentage = 100;
1130 $event->fulldayevent = 1;
1131
1132 $event->contact_id = $obj->rowid;
1133
1134 $event->date_start_in_calendar = $db->jdate($event->datep);
1135 $event->date_end_in_calendar = $db->jdate($event->datef);
1136
1137 // Add an entry in eventarray for each day
1138 $daycursor = $event->datep;
1139 $annee = (int) dol_print_date($daycursor, '%Y', 'tzuserrel');
1140 $mois = (int) dol_print_date($daycursor, '%m', 'tzuserrel');
1141 $jour = (int) dol_print_date($daycursor, '%d', 'tzuserrel');
1142
1143 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1144
1145 $eventarray[$daykey][] = $event;
1146
1147 /*$loop = true;
1148 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee);
1149 do {
1150 $eventarray[$daykey][] = $event;
1151 $daykey += 60 * 60 * 24;
1152 if ($daykey > $event->date_end_in_calendar) $loop = false;
1153 } while ($loop);
1154 */
1155 $i++;
1156 }
1157 } else {
1158 dol_print_error($db);
1159 }
1160}
1161
1162// LEAVE-HOLIDAY CALENDAR
1163if ($user->hasRight("holiday", "read")) {
1164 $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";
1165 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u";
1166 $sql .= " WHERE u.rowid = x.fk_user";
1167 $sql .= " AND u.statut = '1'"; // Show only active users (0 = inactive user, 1 = active user)
1168 $sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
1169 if ($mode == 'show_day') {
1170 // Request only leaves for the current selected day
1171 $sql .= " AND '".$db->escape($year)."-".$db->escape($month)."-".$db->escape($day)."' BETWEEN x.date_debut AND x.date_fin"; // date_debut and date_fin are date without time
1172 } elseif ($mode == 'show_week') {
1173 // Restrict on current month (we get more, but we will filter later)
1174 $sql .= " AND x.date_debut < '".$db->idate(dol_get_last_day($year, $month))."'";
1175 $sql .= " AND x.date_fin >= '".$db->idate(dol_get_first_day($year, $month))."'";
1176 } elseif ($mode == 'show_month') {
1177 // Restrict on current month
1178 $sql .= " AND x.date_debut <= '".$db->idate(dol_get_last_day($year, $month))."'";
1179 $sql .= " AND x.date_fin >= '".$db->idate(dol_get_first_day($year, $month))."'";
1180 }
1181 if (!$user->hasRight('holiday', 'readall') || $filtert == '-3') {
1182 // Restrict on users of current user and his children
1183 $sql .= " AND x.fk_user IN(".$db->sanitize(implode(", ", $user->getAllChildIds(1))).") ";
1184 }
1185 if ($filtert > 0) {
1186 // Restrict on user
1187 $sql .= " AND x.fk_user = ".((int) $filtert);
1188 }
1189
1190 $resql = $db->query($sql);
1191 if ($resql) {
1192 $num = $db->num_rows($resql);
1193 $i = 0;
1194 $nbevents += $num;
1195
1196 while ($i < $num) {
1197 $obj = $db->fetch_object($resql);
1198
1199 $event = new ActionComm($db);
1200
1201 // Need the id of the leave object for link to it
1202 $event->id = $obj->rowid;
1203 $event->ref = (string) $event->id;
1204
1205 $event->type_code = 'HOLIDAY';
1206 $event->type_label = '';
1207 $event->type_color = '';
1208 $event->type = 'holiday';
1209 $event->type_picto = 'holiday';
1210
1211 // date_debut and date_fin are dates without time, so they must be read and rendered in GMT to
1212 // stay independent from the server and user timezones (otherwise the calendar day box is shifted).
1213 $event->datep = $db->jdate($obj->date_start, 'gmt') + (empty($obj->halfday) || $obj->halfday == 1 ? 0 : 12) * 60 * 60;
1214 $event->datef = $db->jdate($obj->date_end, 'gmt') + (empty($obj->halfday) || $obj->halfday == -1 ? 24 : 12) * 60 * 60 - 1;
1215 $event->date_start_in_calendar = $event->datep;
1216 $event->date_end_in_calendar = $event->datef;
1217
1218 if ($obj->status == 3) {
1219 // Show no symbol for leave with state "leave approved"
1220 $event->percentage = -1;
1221 } elseif ($obj->status == 2) {
1222 // Show TO-DO symbol for leave with state "leave wait for approval"
1223 $event->percentage = 0;
1224 }
1225
1226 $event->label = $langs->trans("Holiday");
1227
1228 $daycursor = $event->date_start_in_calendar;
1229 $annee = (int) dol_print_date($daycursor, '%Y', 'gmt');
1230 $mois = (int) dol_print_date($daycursor, '%m', 'gmt');
1231 $jour = (int) dol_print_date($daycursor, '%d', 'gmt');
1232
1233 $daycursorend = $event->date_end_in_calendar;
1234 $anneeend = (int) dol_print_date($daycursorend, '%Y', 'gmt');
1235 $moisend = (int) dol_print_date($daycursorend, '%m', 'gmt');
1236 $jourend = (int) dol_print_date($daycursorend, '%d', 'gmt');
1237
1238 // daykey must be date that represent day box in calendar so must be a user time
1239 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1240 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1241 $ifornbofdays = 0;
1242 do {
1243 $ifornbofdays++;
1244
1245 $firstdayofholiday = ($ifornbofdays == 1);
1246 $lastdayofholiday = ($daykeygmt == dol_get_first_hour($event->date_end_in_calendar, 'gmt'));
1247
1248 /*
1249 var_dump(dol_print_date($daykeygmt, 'dayhour', 'gmt'));
1250 var_dump(dol_print_date(dol_get_first_hour($event->date_end_in_calendar, 'gmt'), 'dayhour', 'gmt'));
1251 var_dump($lastdayofholiday);
1252 var_dump($obj->halfday);
1253 */
1254
1255 if ((in_array($obj->halfday, array(1, 2)) == 1 && $lastdayofholiday) || (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday)) {
1256 // We create a copy of event because we want tochange the label
1257 $newevent = dol_clone($event, 1);
1258 if (in_array($obj->halfday, array(1, 2)) && $lastdayofholiday) {
1259 $newevent->label .= ' ('.$langs->trans("Morning").')';
1260 } elseif (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday) {
1261 $newevent->label .= ' ('.$langs->trans("Afternoon").')';
1262 }
1263 $eventarray[$daykey][] = $newevent; // We need to use ->gtTypePicto, getXXXon object, so clone must be PHP clone.
1264 } else {
1265 $eventarray[$daykey][] = $event; // We can use the event unchanged
1266 }
1267
1268 $daykey += 60 * 60 * 24;
1269 $daykeygmt += 60 * 60 * 24;
1270 } while ($daykey <= $event->date_end_in_calendar);
1271
1272 $i++;
1273 }
1274 }
1275}
1276
1277// EXTERNAL CALENDAR
1278// Complete $eventarray with external import Ical
1279if (count($listofextcals)) {
1280 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/ical.class.php';
1281
1282 foreach ($listofextcals as $key => $extcal) {
1283 $url = $extcal['src']; // Example: https://www.google.com/calendar/ical/eldy10%40gmail.com/private-cde92aa7d7e0ef6110010a821a2aaeb/basic.ics
1284 $namecal = $extcal['name'];
1285 $offsettz = $extcal['offsettz'];
1286 $colorcal = $extcal['color'];
1287 $buggedfile = $extcal['buggedfile'];
1288
1289 $pathforcachefile = dol_sanitizePathName($conf->user->dir_temp).'/'.dol_sanitizeFileName('extcal_'.$namecal.'_user'.$user->id).'.cache';
1290 //var_dump($pathforcachefile);exit;
1291
1292 $ical = new ICal();
1293 $ical->parse($url, $pathforcachefile, $DELAYFORCACHE);
1294 if ($ical->error) {
1295 // Save error message for extcal
1296 $listofextcals[$key]['error'] = $ical->error;
1297 $s .= '<br><div class="warning">'.dol_escape_htmltag($listofextcals[$key]['name']).': '.$url.'<br>Error message: '.dol_escape_htmltag($ical->error).'</div>';
1298 }
1299
1300 // After this $ical->cal['VEVENT'] contains array of events, $ical->cal['DAYLIGHT'] contains daylight info, $ical->cal['STANDARD'] contains non daylight info, ...
1301 //var_dump($ical->cal); exit;
1302 $icalevents = array();
1303 $tmparray = $ical->get_event_list();
1304 if (is_array($tmparray)) {
1305 $icalevents = array_merge($icalevents, $tmparray); // Add $ical->cal['VEVENT']
1306 }
1307 $tmparray = $ical->get_freebusy_list();
1308 if (is_array($tmparray)) {
1309 $icalevents = array_merge($icalevents, $tmparray); // Add $ical->cal['VFREEBUSY']
1310 }
1311
1312 $nbevents += count($icalevents);
1313
1314 if (count($icalevents) > 0) {
1315 // Duplicate all repeatable events into new entries
1316 $moreicalevents = array();
1317 foreach ($icalevents as $icalevent) {
1318 if (isset($icalevent['RRULE']) && is_array($icalevent['RRULE'])) { //repeatable event
1319 //if ($event->date_start_in_calendar < $firstdaytoshow) $event->date_start_in_calendar=$firstdaytoshow;
1320 //if ($event->date_end_in_calendar > $lastdaytoshow) $event->date_end_in_calendar=($lastdaytoshow-1);
1321 if ($icalevent['DTSTART;VALUE=DATE']) { //fullday event
1322 $datecurstart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
1323 $datecurend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
1324 } elseif (is_array($icalevent['DTSTART']) && !empty($icalevent['DTSTART']['unixtime'])) {
1325 $datecurstart = $icalevent['DTSTART']['unixtime'];
1326 $datecurend = $icalevent['DTEND']['unixtime'];
1327 if (!empty($ical->cal['DAYLIGHT']['DTSTART']) && $datecurstart) {
1328 //var_dump($ical->cal);
1329 $tmpcurstart = $datecurstart;
1330 $tmpcurend = $datecurend;
1331 $tmpdaylightstart = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['DAYLIGHT']['DTSTART'];
1332 $tmpdaylightend = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['STANDARD']['DTSTART'];
1333 //var_dump($tmpcurstart);var_dump($tmpcurend); var_dump($ical->cal['DAYLIGHT']['DTSTART']);var_dump($ical->cal['STANDARD']['DTSTART']);
1334 // Edit datecurstart and datecurend
1335 if ($tmpcurstart >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
1336 $datecurstart -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
1337 } else {
1338 $datecurstart -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
1339 }
1340 if ($tmpcurend >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
1341 $datecurend -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
1342 } else {
1343 $datecurend -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
1344 }
1345 }
1346 // datecurstart and datecurend are now GMT date
1347 //var_dump($datecurstart); var_dump($datecurend); exit;
1348 } else {
1349 // Not a recognized record
1350 dol_syslog("Found a not recognized repeatable record with unknown date start", LOG_ERR);
1351 continue;
1352 }
1353 //print 'xx'.$datecurstart;exit;
1354
1355 $interval = (empty($icalevent['RRULE']['INTERVAL']) ? 1 : $icalevent['RRULE']['INTERVAL']);
1356 $until = empty($icalevent['RRULE']['UNTIL']) ? 0 : dol_stringtotime($icalevent['RRULE']['UNTIL'], 1);
1357 $maxrepeat = empty($icalevent['RRULE']['COUNT']) ? 0 : $icalevent['RRULE']['COUNT'];
1358 if ($until && ($until + ($datecurend - $datecurstart)) < $firstdaytoshow) {
1359 continue; // We discard repeatable event that end before start date to show
1360 }
1361 if ($datecurstart >= $lastdaytoshow) {
1362 continue; // We discard repeatable event that start after end date to show
1363 }
1364
1365 $numofevent = 0;
1366 while (($datecurstart < $lastdaytoshow) && (empty($maxrepeat) || ($numofevent < $maxrepeat))) {
1367 if ($datecurend >= $firstdaytoshow) { // We add event
1368 $newevent = $icalevent;
1369 unset($newevent['RRULE']);
1370 if ($icalevent['DTSTART;VALUE=DATE']) {
1371 $newevent['DTSTART;VALUE=DATE'] = dol_print_date($datecurstart, '%Y%m%d');
1372 $newevent['DTEND;VALUE=DATE'] = dol_print_date($datecurend + 1, '%Y%m%d');
1373 } else {
1374 $newevent['DTSTART'] = $datecurstart;
1375 $newevent['DTEND'] = $datecurend;
1376 }
1377 $moreicalevents[] = $newevent;
1378 }
1379 // Jump on next occurrence
1380 $numofevent++;
1381 $savdatecurstart = $datecurstart;
1382 if ($icalevent['RRULE']['FREQ'] == 'DAILY') {
1383 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'd');
1384 $datecurend = dol_time_plus_duree($datecurend, $interval, 'd');
1385 }
1386 if ($icalevent['RRULE']['FREQ'] == 'WEEKLY') {
1387 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'w');
1388 $datecurend = dol_time_plus_duree($datecurend, $interval, 'w');
1389 } elseif ($icalevent['RRULE']['FREQ'] == 'MONTHLY') {
1390 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'm');
1391 $datecurend = dol_time_plus_duree($datecurend, $interval, 'm');
1392 } elseif ($icalevent['RRULE']['FREQ'] == 'YEARLY') {
1393 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'y');
1394 $datecurend = dol_time_plus_duree($datecurend, $interval, 'y');
1395 }
1396 // Test to avoid infinite loop ($datecurstart must increase)
1397 if ($savdatecurstart >= $datecurstart) {
1398 dol_syslog("Found a rule freq ".$icalevent['RRULE']['FREQ']." not managed by dolibarr code. Assume 1 week frequency.", LOG_ERR);
1399 $datecurstart += 3600 * 24 * 7;
1400 $datecurend += 3600 * 24 * 7;
1401 }
1402 }
1403 }
1404 }
1405 $icalevents = array_merge($icalevents, $moreicalevents);
1406
1407 // Loop on each entry into cal file to know if entry is qualified and add an ActionComm into $eventarray
1408 foreach ($icalevents as $icalevent) {
1409 //var_dump($icalevent);
1410
1411 //print $icalevent['SUMMARY'].'->';
1412 //var_dump($icalevent);exit;
1413 if (!empty($icalevent['RRULE'])) {
1414 continue; // We found a repeatable event. It was already split into unitary events, so we discard general rule.
1415 }
1416
1417 // Create a new object action
1418 $event = new ActionComm($db);
1419 $addevent = false;
1420 if (isset($icalevent['DTSTART;VALUE=DATE'])) { // fullday event
1421 // For full day events, date are also GMT but they won't but converted using tz during output
1422 $datestart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
1423 if (empty($icalevent['DTEND;VALUE=DATE'])) {
1424 $dateend = $datestart + 86400 - 1;
1425 } else {
1426 $dateend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
1427 }
1428 //print 'x'.$datestart.'-'.$dateend;exit;
1429 //print dol_print_date($dateend,'dayhour','gmt');
1430 $event->fulldayevent = 1;
1431 $addevent = true;
1432 } elseif (!is_array($icalevent['DTSTART'])) { // not fullday event (DTSTART is not array. It is a value like '19700101T000000Z' for 00:00 in greenwitch)
1433 $datestart = $icalevent['DTSTART'];
1434 $dateend = empty($icalevent['DTEND']) ? $datestart : $icalevent['DTEND'];
1435
1436 $datestart += +($offsettz * 3600);
1437 $dateend += +($offsettz * 3600);
1438
1439 $addevent = true;
1440 //var_dump($offsettz);
1441 //var_dump(dol_print_date($datestart, 'dayhour', 'gmt'));
1442 } elseif (isset($icalevent['DTSTART']['unixtime'])) { // File contains a local timezone + a TZ (for example when using bluemind)
1443 $datestart = $icalevent['DTSTART']['unixtime'];
1444 $dateend = $icalevent['DTEND']['unixtime'];
1445
1446 $datestart += +($offsettz * 3600);
1447 $dateend += +($offsettz * 3600);
1448
1449 // $buggedfile is set to uselocalandtznodaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtznodaylight'
1450 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
1451 // TODO
1452 }
1453 // $buggedfile is set to uselocalandtzdaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtzdaylight' (for example with bluemind)
1454 if ($buggedfile === 'uselocalandtzdaylight') { // unixtime is a local date that does take daylight into account, TZID is +2 for example for 'Europe/Paris' in summer
1455 $localtzs = new DateTimeZone(preg_replace('/"/', '', $icalevent['DTSTART']['TZID']));
1456 $localtze = new DateTimeZone(preg_replace('/"/', '', $icalevent['DTEND']['TZID']));
1457 $localdts = new DateTime(dol_print_date($datestart, 'dayrfc', 'gmt'), $localtzs);
1458 $localdte = new DateTime(dol_print_date($dateend, 'dayrfc', 'gmt'), $localtze);
1459 $tmps = -1 * $localtzs->getOffset($localdts);
1460 $tmpe = -1 * $localtze->getOffset($localdte);
1461 $datestart += $tmps;
1462 $dateend += $tmpe;
1463 //var_dump($datestart);
1464 }
1465 $addevent = true;
1466 }
1467
1468 if ($addevent) {
1469 $event->id = $icalevent['UID'];
1470 $event->ref = (string) $event->id;
1471 $userId = $userstatic->findUserIdByEmail($namecal);
1472 if (!empty($userId) && $userId > 0) {
1473 $event->userassigned[$userId] = $userId;
1474 $event->percentage = -1;
1475 }
1476
1477 $event->type_code = "ICALEVENT";
1478 $event->type_label = $namecal;
1479 $event->type_color = $colorcal;
1480 $event->type = 'icalevent';
1481 $event->type_picto = 'rss';
1482
1483 $event->icalname = $namecal;
1484 $event->icalcolor = $colorcal;
1485 $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.
1486 $event->datep = $datestart + $usertime;
1487 $event->datef = $dateend + $usertime;
1488
1489 if (isset($icalevent['SUMMARY']) && $icalevent['SUMMARY']) {
1490 $event->label = dol_string_nohtmltag($icalevent['SUMMARY']);
1491 } elseif (isset($icalevent['DESCRIPTION']) && $icalevent['DESCRIPTION']) {
1492 $event->label = dol_nl2br(dol_string_nohtmltag($icalevent['DESCRIPTION']), 1);
1493 } else {
1494 $event->label = $langs->trans("ExtSiteNoLabel");
1495 }
1496
1497 // Priority (see https://www.kanzaki.com/docs/ical/priority.html)
1498 // LOW = 0 to 4
1499 // MEDIUM = 5
1500 // HIGH = 6 to 9
1501 if (!empty($icalevent['PRIORITY'])) {
1502 $event->priority = $icalevent['PRIORITY'];
1503 }
1504
1505 // Transparency (see https://www.kanzaki.com/docs/ical/transp.html)
1506 if (!empty($icalevent['TRANSP'])) {
1507 if ($icalevent['TRANSP'] == "TRANSPARENT") {
1508 $event->transparency = 0; // 0 = available / free
1509 }
1510 if ($icalevent['TRANSP'] == "OPAQUE") {
1511 $event->transparency = 1; // 1 = busy
1512 }
1513
1514 // TODO: MS outlook states
1515 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:TRANSPARENT => Available / Free
1516 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:OPAQUE => Work another place
1517 // X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE + TRANSP:OPAQUE => With reservations
1518 // X-MICROSOFT-CDO-BUSYSTATUS:BUSY + TRANSP:OPAQUE => Busy
1519 // X-MICROSOFT-CDO-BUSYSTATUS:OOF + TRANSP:OPAQUE => Away from the office / off-site
1520 }
1521
1522 if (!empty($icalevent['LOCATION'])) {
1523 $event->location = $icalevent['LOCATION'];
1524 }
1525
1526 $event->date_start_in_calendar = $event->datep;
1527
1528 if ($event->datef != '' && $event->datef >= $event->datep) {
1529 $event->date_end_in_calendar = $event->datef;
1530 } else {
1531 $event->date_end_in_calendar = $event->datep;
1532 }
1533
1534 // Add event into $eventarray if date range are ok.
1535 if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) {
1536 //print 'x'.$datestart.'-'.$dateend;exit;
1537 //print 'x'.$datestart.'-'.$dateend;exit;
1538 //print 'x'.$datestart.'-'.$dateend;exit;
1539 // This record is out of visible range
1540 } else {
1541 if ($event->date_start_in_calendar < $firstdaytoshow) {
1542 $event->date_start_in_calendar = $firstdaytoshow;
1543 }
1544 if ($event->date_end_in_calendar >= $lastdaytoshow) {
1545 $event->date_end_in_calendar = ($lastdaytoshow - 1);
1546 }
1547
1548 // Add an entry in actionarray for each day
1549 $daycursor = $event->date_start_in_calendar;
1550 $annee = (int) dol_print_date($daycursor, '%Y', 'tzuserrel');
1551 $mois = (int) dol_print_date($daycursor, '%m', 'tzuserrel');
1552 $jour = (int) dol_print_date($daycursor, '%d', 'tzuserrel');
1553
1554 // Loop on each day covered by action to prepare an index to show on calendar
1555 $loop = true;
1556 $j = 0;
1557 // daykey must be date that represent day box in calendar so must be a user time
1558 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1559 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1560 do {
1561 //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').' ';
1562 $eventarray[$daykey][] = $event;
1563 $daykey += 60 * 60 * 24;
1564 $daykeygmt += 60 * 60 * 24; // Add one day
1565 if (($event->fulldayevent ? $daykeygmt : $daykey) > $event->date_end_in_calendar) {
1566 $loop = false;
1567 }
1568 } while ($loop);
1569 }
1570 }
1571 }
1572 }
1573 }
1574}
1575
1576// Complete $eventarray with events coming from external module
1577$parameters = array();
1578$object = null;
1579$reshook = $hookmanager->executeHooks('getCalendarEvents', $parameters, $object, $action);
1580if (!empty($hookmanager->resArray['eventarray'])) {
1581 foreach ($hookmanager->resArray['eventarray'] as $keyDate => $events) {
1582 if (!isset($eventarray[$keyDate])) {
1583 $eventarray[$keyDate] = array();
1584 }
1585 $eventarray[$keyDate] = array_merge($eventarray[$keyDate], $events);
1586 }
1587}
1588
1589// Sort events
1590foreach ($eventarray as $keyDate => &$dateeventarray) {
1591 usort($dateeventarray, 'sort_events_by_date');
1592}
1593
1594
1595$maxnbofchar = 0;
1596$cachethirdparties = array();
1597$cachecontacts = array();
1598$cacheusers = array();
1599// default values
1601 array(137, 86, 161),
1602 array(60, 147, 183),
1603 array(250, 190, 80),
1604 array(80, 166, 90),
1605 array(190, 190, 100),
1606 array(91, 115, 247),
1607 array(140, 140, 220),
1608 array(190, 120, 120),
1609 array(115, 125, 150),
1610 array(100, 170, 20),
1611 array(150, 135, 125),
1612 array(85, 135, 150),
1613 array(150, 135, 80),
1614 array(150, 80, 150)
1615);
1616
1617// Define theme_datacolor array
1618$color_file = DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/theme_vars.inc.php";
1619if (is_readable($color_file)) {
1620 global $theme_datacolor;
1621 include $color_file;
1623}
1624
1625$massactionbutton = '';
1626
1627print_barre_liste($langs->trans("Agenda"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, -1, 'object_action', 0, $nav.'<span class="marginleftonly"></span>'.$newcardbutton, '', $limit, 1, 0, 1, $viewmode);
1628
1629if ($nbevents > $MAXONSAMEPAGE) {
1630 print info_admin('Number of results has been truncated to '.$MAXONSAMEPAGE, 0, 0, 'warning').'<br>';
1631}
1632
1633// Show div with list of calendars
1634print $s;
1635
1636
1637if (empty($mode) || $mode == 'show_month') { // View by month
1638 $newparam = $param; // newparam is for birthday links
1639 $newparam = preg_replace('/check_birthday=/i', 'check_birthday_=', $newparam); // To avoid replacement when replace day= is done
1640 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1641 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1642 $newparam = preg_replace('/day=[0-9]+&?/i', '', $newparam);
1643 $newparam = preg_replace('/month=[0-9]+&?/i', '', $newparam);
1644 $newparam = preg_replace('/year=[0-9]+&?/i', '', $newparam);
1645 $newparam = preg_replace('/viewcal=[0-9]+&?/i', '', $newparam);
1646 $newparam = preg_replace('/check_birthday_=/i', 'check_birthday=', $newparam); // Restore correct parameter
1647 $newparam .= '&viewcal=1';
1648
1649 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1650 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid, $search_categ_cus);
1651 print '</div>';
1652
1653 print '<div class="div-table-responsive-no-min sectioncalendarbymonth maxscreenheightless300">';
1654 print '<table class="centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore">';
1655 print ' <tr class="liste_titre sticky">';
1656 // Column title of weeks numbers
1657 echo ' <td class="center">#</td>';
1658 $i = 0;
1659 while ($i < 7) {
1660 print ' <td class="center bold uppercase tdfordaytitle'.($i == 0 ? ' borderleft' : '').'">';
1661 $numdayinweek = (($i + (getDolGlobalInt('MAIN_START_WEEK', 1))) % 7);
1662 if (!empty($conf->dol_optimize_smallscreen)) {
1663 $labelshort = array(0 => 'SundayMin', 1 => 'MondayMin', 2 => 'TuesdayMin', 3 => 'WednesdayMin', 4 => 'ThursdayMin', 5 => 'FridayMin', 6 => 'SaturdayMin');
1664 print $langs->trans($labelshort[$numdayinweek]);
1665 } else {
1666 print $langs->trans("Day".$numdayinweek);
1667 }
1668 print ' </td>'."\n";
1669 $i++;
1670 }
1671 echo ' </tr>'."\n";
1672
1673 $todayarray = dol_getdate($now, true);
1674 $todaytms = dol_mktime(0, 0, 0, $todayarray['mon'], $todayarray['mday'], $todayarray['year']);
1675
1676 // In loops, tmpday contains day nb in current month (can be zero or negative for days of previous month)
1677 //var_dump($eventarray);
1678 for ($iter_week = 0; $iter_week < 6; $iter_week++) {
1679 echo " <tr>\n";
1680 // Get date of the current day, format 'yyyy-mm-dd'
1681 if ($tmpday <= 0) { // If number of the current day is in previous month
1682 $currdate0 = sprintf("%04d", $prev_year).sprintf("%02d", $prev_month).sprintf("%02d", $max_day_in_prev_month + $tmpday);
1683 } elseif ($tmpday <= $max_day_in_month) { // If number of the current day is in current month
1684 $currdate0 = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $tmpday);
1685 } else { // If number of the current day is in next month
1686 $currdate0 = sprintf("%04d", $next_year).sprintf("%02d", $next_month).sprintf("%02d", $tmpday - $max_day_in_month);
1687 }
1688 // Get week number for the targeted date '$currdate0'
1689 $numweek0 = date("W", strtotime(date($currdate0)));
1690 // Show the week number, and define column width
1691 echo ' <td class="center weeknumber opacitymedium" width="2%">'.$numweek0.'</td>';
1692
1693 for ($iter_day = 0; $iter_day < 7; $iter_day++) {
1694 if ($tmpday <= 0) {
1695 /* Show days before the beginning of the current month (previous month) */
1696 $style = 'cal_other_month cal_past';
1697 if ($iter_day == 6) {
1698 $style .= ' cal_other_month_right';
1699 }
1700 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1701 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1702 show_day_events($db, $max_day_in_prev_month + $tmpday, $prev_month, $prev_year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam);
1703 echo " </td>\n";
1704 } elseif ($tmpday <= $max_day_in_month) {
1705 /* Show days of the current month */
1706 $curtime = dol_mktime(0, 0, 0, $month, $tmpday, $year);
1707 $style = 'cal_current_month';
1708 if ($iter_day == 6) {
1709 $style .= ' cal_current_month_right';
1710 }
1711 $today = 0;
1712 if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $month && $todayarray['year'] == $year) {
1713 $today = 1;
1714 }
1715 if ($today) {
1716 $style = 'cal_today';
1717 }
1718 if ($curtime < $todaytms) {
1719 $style .= ' cal_past';
1720 }
1721 //var_dump($todayarray['mday']."==".$tmpday." && ".$todayarray['mon']."==".$month." && ".$todayarray['year']."==".$year.' -> '.$style);
1722 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1723 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1724 show_day_events($db, $tmpday, $month, $year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam, 0, 60, 0, $bookcalcalendars);
1725 echo "</td>\n";
1726 } else {
1727 /* Show days after the current month (next month) */
1728 $style = 'cal_other_month';
1729 if ($iter_day == 6) {
1730 $style .= ' cal_other_month_right';
1731 }
1732 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1733 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1734 show_day_events($db, $tmpday - $max_day_in_month, $next_month, $next_year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam);
1735 echo "</td>\n";
1736 }
1737 $tmpday++;
1738 }
1739 echo " </tr>\n";
1740 }
1741 print "</table>\n";
1742 print '</div>';
1743
1744 print '<input type="hidden" name="actionmove" value="mupdate">';
1745 print '<input type="hidden" name="backtopage" value="'.dol_escape_htmltag($_SERVER['PHP_SELF']).'?mode=show_month&'.dol_escape_htmltag($_SERVER['QUERY_STRING']).'">';
1746 print '<input type="hidden" name="newdate" id="newdate">';
1747} elseif ($mode == 'show_week') {
1748 // View by week
1749 $newparam = $param; // newparam is for birthday links
1750 $newparam = preg_replace('/check_birthday=/i', 'check_birthday_=', $newparam); // To avoid replacement when replace day= is done
1751 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1752 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1753 $newparam = preg_replace('/day=[0-9]+&?/i', '', $newparam);
1754 $newparam = preg_replace('/month=[0-9]+&?/i', '', $newparam);
1755 $newparam = preg_replace('/year=[0-9]+&?/i', '', $newparam);
1756 $newparam = preg_replace('/viewweek=[0-9]+&?/i', '', $newparam);
1757 $newparam = preg_replace('/check_birthday_=/i', 'check_birthday=', $newparam); // Restore correct parameter
1758 $newparam .= '&viewweek=1';
1759
1760 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1761 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid);
1762 print '</div>';
1763
1764 print '<div class="div-table-responsive-no-min sectioncalendarbyweek maxscreenheightless300">';
1765 print '<table class="centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore">';
1766 print ' <tr class="liste_titre">';
1767 $i = 0;
1768 while ($i < 7) {
1769 echo ' <td class="center bold uppercase tdfordaytitle">'.$langs->trans("Day".(($i + (getDolGlobalInt('MAIN_START_WEEK', 1))) % 7))."</td>\n";
1770 $i++;
1771 }
1772 echo " </tr>\n";
1773
1774 echo " <tr>\n";
1775
1776 for ($iter_day = 0; $iter_day < 7; $iter_day++) {
1777 // Show days of the current week
1778 $curtime = dol_time_plus_duree($firstdaytoshow, $iter_day, 'd'); // $firstdaytoshow is in timezone of server
1779 $tmpday = (int) dol_print_date($curtime, '%d', 'tzuserrel');
1780 $tmpmonth = (int) dol_print_date($curtime, '%m', 'tzuserrel');
1781 $tmpyear = (int) dol_print_date($curtime, '%Y', 'tzuserrel');
1782
1783 $style = 'cal_current_month';
1784 if ($iter_day == 6) {
1785 $style .= ' cal_other_month_right';
1786 }
1787
1788 $today = 0;
1789 $todayarray = dol_getdate($now, true);
1790 if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $tmpmonth && $todayarray['year'] == $tmpyear) {
1791 $today = 1;
1792 }
1793 if ($today) {
1794 $style = 'cal_today';
1795 }
1796
1797 echo ' <td class="'.$style.'" width="14%" valign="top">';
1798 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1799 show_day_events($db, $tmpday, $tmpmonth, $tmpyear, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 0, $bookcalcalendars);
1800 echo " </td>\n";
1801 }
1802 echo " </tr>\n";
1803
1804 print "</table>\n";
1805 print '</div>';
1806
1807 echo '<input type="hidden" name="actionmove" value="mupdate">';
1808 echo '<input type="hidden" name="backtopage" value="'.dol_escape_htmltag($_SERVER['PHP_SELF']).'?mode=show_week&'.dol_escape_htmltag($_SERVER['QUERY_STRING']).'">';
1809 echo '<input type="hidden" name="newdate" id="newdate">';
1810} else { // View by day
1811 $newparam = $param; // newparam is for birthday links
1812 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1813 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1814 $newparam = preg_replace('/viewday=[0-9]+&?/i', '', $newparam);
1815 $newparam .= '&viewday=1';
1816 // Code to show just one day
1817 $style = 'cal_current_month cal_current_month_oneday';
1818 $today = 0;
1819 $todayarray = dol_getdate($now, true);
1820 if ($todayarray['mday'] == $day && $todayarray['mon'] == $month && $todayarray['year'] == $year) {
1821 $today = 1;
1822 }
1823 //if ($today) $style='cal_today';
1824
1825 $timestamp = dol_mktime(12, 0, 0, $month, $day, $year);
1826 $arraytimestamp = dol_getdate($timestamp);
1827
1828 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1829 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid);
1830 print '</div>';
1831
1832 print '<div class="div-table-responsive-no-min sectioncalendarbyday maxscreenheightless300">';
1833 echo '<table class="tagtable centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore" style="margin-bottom: 10px !important;">';
1834
1835 echo ' <tr class="tagtr liste_titre">';
1836 echo ' <td class="tagtd center bold uppercase">'.$langs->trans("Day".$arraytimestamp['wday'])."</td>\n";
1837 echo " </tr>\n";
1838
1839 /*
1840 echo ' <div class="tagtr">';
1841 echo ' <div class="tagtd width100"></div>';
1842 echo ' <div class="tagtd center">';
1843 echo show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, -1);
1844 echo ' </div>'."\n";
1845 echo " </div>\n";
1846 */
1847
1848 print '<tr><td>';
1849
1850 /* WIP View per hour */
1851 $useviewhour = 0;
1852 if ($useviewhour) {
1853 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
1854
1855 $maxheightwin = (isset($_SESSION["dol_screenheight"]) && $_SESSION["dol_screenheight"] > 500) ? ($_SESSION["dol_screenheight"] - 200) : 660; // Also into index.php file
1856
1857 echo '<div style="max-height: '.$maxheightwin.'px;">';
1858 echo '<div class="tagtable centpercent calendarviewcontainer">';
1859
1860 $maxnbofchar = 80;
1861
1862 $tmp = explode('-', getDolGlobalString('MAIN_DEFAULT_WORKING_HOURS'));
1863 $minhour = round((float) $tmp[0], 0);
1864 $maxhour = round((float) $tmp[1], 0);
1865 if ($minhour > 23) {
1866 $minhour = 23;
1867 }
1868 if ($maxhour < 1) {
1869 $maxhour = 1;
1870 }
1871 if ($maxhour <= $minhour) {
1872 $maxhour = $minhour + 1;
1873 }
1874
1875 $i = 0;
1876 $j = 0;
1877 while ($i < 24) {
1878 echo ' <div class="tagtr calendarviewcontainertr">'."\n";
1879 echo ' <div class="tagtd width100 tdtop">'.dol_print_date($i * 3600, 'hour', 'gmt').'</div>';
1880 echo ' <div class="tagtd '.$style.' tdtop"></div>'."\n";
1881 echo ' </div>'."\n";
1882 $i++;
1883 $j++;
1884 }
1885
1886 echo '</div></div>';
1887
1888 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1889 show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 1, $bookcalcalendars);
1890
1891 print '</div>';
1892 } else {
1893 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
1894
1895 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1896 show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 0, $bookcalcalendars);
1897
1898 print '</div>';
1899 }
1900
1901
1902 print '</td></tr>';
1903
1904 echo '</table>';
1905 print '</div>';
1906}
1907
1908print "\n".'</form>';
1909
1910// End of page
1911llxFooter();
1912$db->close();
1913
1914
1934function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventarray, $maxprint = 0, $maxnbofchar = 16, $newparam = '', $showinfo = 0, $minheight = 60, $nonew = 0, $bookcalcalendarsarray = array())
1935{
1936 global $user, $conf, $langs;
1937 global $action, $mode, $filter, $filtert, $status, $actioncode, $usergroup; // Filters used into search form
1938 global $theme_datacolor;
1939 global $cachethirdparties, $cachecontacts, $cacheusers, $colorindexused;
1940 global $hookmanager;
1941
1942 '@phan-var-force array{0:array{0:int,1:int,2:int},1:array{0:int,1:int,2:int},2:array{0:int,1:int,2:int},3:array{0:int,1:int,2:int}} $theme_datacolor
1943 @phan-var-force User[] $cacheusers
1944 @phan-var-force array<int<0,3>> $colorindexused';
1951 if ($conf->use_javascript_ajax) { // Enable the "Show more button..."
1952 $conf->global->MAIN_JS_SWITCH_AGENDA = 1;
1953 }
1954
1955 $dateint = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $day);
1956 $datenowint = dol_print_date(dol_now(), "%Y%m%d");
1957 //print 'show_day_events day='.$day.' month='.$month.' year='.$year.' dateint='.$dateint.' datenowint='.$datenowint;
1958
1959 print "\n";
1960
1961 $curtime = dol_mktime(0, 0, 0, $month, $day, $year);
1962 $urltoshow = DOL_URL_ROOT.'/comm/action/index.php?mode=show_day&day='.str_pad((string) $day, 2, "0", STR_PAD_LEFT).'&month='.str_pad((string) $month, 2, "0", STR_PAD_LEFT).'&year='.$year.$newparam;
1963 $urltocreate = '';
1964 if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) {
1965 $newparam .= '&month='.str_pad((string) $month, 2, "0", STR_PAD_LEFT).'&year='.$year;
1966 $hourminsec = '100000';
1967 $urltocreate = DOL_URL_ROOT.'/comm/action/card.php?action=create&datep='.sprintf("%04d%02d%02d", $year, $month, $day).$hourminsec.'&backtopage='.urlencode($_SERVER["PHP_SELF"].($newparam ? '?'.$newparam : ''));
1968 }
1969
1970 // Line with title of day
1971 print '<div id="dayevent_'.$dateint.'" class="dayevent tagtable centpercent nobordernopadding">'."\n";
1972
1973 if ($nonew <= 0) {
1974 print '<div class="tagtr cursorpointer" onclick="window.location=\''.$urltocreate.'\';"><div class="nowrap tagtd"><div class="left inline-block">';
1975 print '<a class="dayevent-aday" style="color: #666" href="'.$urltoshow.'">';
1976 print ($datenowint == $dateint ? '<span class="badgeneutral">' : '');
1977 if ($showinfo) {
1978 print dol_print_date($curtime, 'daytextshort');
1979 } else {
1980 print dol_print_date($curtime, '%d');
1981 }
1982 print ($datenowint == $dateint ? '</span>' : '');
1983 print '</a>';
1984 print '</div><div class="nowrap floatright inline-block marginrightonly">';
1985 if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) {
1986 print '<a class="cursoradd" href="'.$urltocreate.'">'; // Explicit link, useful for nojs interfaces
1987 print img_picto($langs->trans("NewAction"), 'edit_add.png');
1988 print '</a>';
1989 }
1990 print '</div></div></div>'."\n";
1991 }
1992
1993 if ($nonew < 0) {
1994 print '</div>';
1995 return;
1996 }
1997
1998 // Line with td contains all div of each events
1999 print '<div class="tagtr">';
2000 print '<div class="tagtd centpercent agendacell sortable">';
2001
2002 //$curtime = dol_mktime (0, 0, 0, $month, $day, $year);
2003 $i = 0;
2004 $ireallyshown = 0;
2005 $itoshow = 0;
2006 $numother = 0;
2007 $numbirthday = 0;
2008 $numical = 0;
2009 $numicals = array();
2010 $ymd = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $day);
2011
2012 $colorindexused[$user->id] = 0; // Color index for current user (user->id) is always 0
2013 $nextindextouse = is_array($colorindexused) ? count($colorindexused) : 0; // At first run this is 0, so fist user has 0, next 1, ...
2014 //var_dump($colorindexused);
2015
2016 include_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
2017 $tmpholiday = new Holiday($db);
2018
2019 foreach ($eventarray as $daykey => $notused) { // daykey is the 'YYYYMMDD' to show according to user
2020 $annee = (int) dol_print_date($daykey, '%Y', 'gmt'); // We use gmt because we want the value represented by string 'YYYYMMDD'
2021 $mois = (int) dol_print_date($daykey, '%m', 'gmt'); // We use gmt because we want the value represented by string 'YYYYMMDD'
2022 $jour = (int) dol_print_date($daykey, '%d', 'gmt'); // We use gmt because we want the value represented by string 'YYYYMMDD'
2023
2024 //print 'event daykey='.$daykey.' dol_print_date(daykey)='.dol_print_date($daykey, 'dayhour', 'gmt').' jour='.$jour.' mois='.$mois.' annee='.$annee."<br>\n";
2025 //print 'event daykey='.$daykey.' dol_print_date(daykey)='.dol_print_date($daykey, 'dayhour', 'gmt').' day='.$day.' month='.$month.' year='.$year."<br>\n";
2026
2027 if ($day == $jour && $month == $mois && $year == $annee) {
2028 foreach ($eventarray[$daykey] as $index => $event) {
2029 if ($i < $maxprint || $maxprint == 0 || getDolGlobalString('MAIN_JS_SWITCH_AGENDA')) {
2030 $keysofuserassigned = array_keys($event->userassigned);
2031
2032 // Define $color (Hex string like '0088FF') and $cssclass of event
2033 $color = -1;
2034 $cssclass = '';
2035 $colorindex = -1;
2036 if (in_array($user->id, $keysofuserassigned)) {
2037 $cssclass = 'family_mytasks';
2038
2039 if (empty($cacheusers[$event->userownerid])) {
2040 $newuser = new User($db);
2041 $newuser->fetch($event->userownerid);
2042 $cacheusers[$event->userownerid] = $newuser;
2043 }
2044 //var_dump($cacheusers[$event->userownerid]->color);
2045
2046 // We decide to choose color of owner of event (event->userownerid is user id of owner, event->userassigned contains all users assigned to event)
2047 if (!empty($cacheusers[$event->userownerid]->color)) {
2048 $color = $cacheusers[$event->userownerid]->color;
2049 }
2050
2051 /* May be we need this: if (getDolGlobalString('AGENDA_USE_COLOR_PER_EVENT_TYPE')) {
2052 $color = $event->type_color;
2053 }*/
2054 } elseif ($event->type_code == 'ICALEVENT') { // Event come from external ical file
2055 $numical++;
2056 if (!empty($event->icalname)) {
2057 if (!isset($numicals[dol_string_nospecial($event->icalname)])) {
2058 $numicals[dol_string_nospecial($event->icalname)] = 0;
2059 }
2060 $numicals[dol_string_nospecial($event->icalname)]++;
2061 }
2062
2063 $color = ($event->icalcolor ? $event->icalcolor : -1);
2064 $cssclass = (!empty($event->icalname) ? 'family_ext'.md5($event->icalname) : 'family_other');
2065 } elseif ($event->type_code == 'BIRTHDAY') {
2066 $numbirthday++;
2067 $colorindex = 2;
2068 $cssclass = 'family_birthday ';
2069 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
2070 } elseif ($event->type == 'bookcal_calendar') {
2071 $numbirthday++;
2072 $colorindex = 3;
2073 $cssclass = 'family_bookcal_calendar_'.(!empty($bookcalcalendarsarray["availabilitieslink"]) ? $bookcalcalendarsarray["availabilitieslink"][$event->fk_bookcal_calendar] : "");
2074 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
2075 } else {
2076 $numother++;
2077 $color = ($event->icalcolor ? $event->icalcolor : -1);
2078 $cssclass = (!empty($event->icalname) ? 'family_ext'.md5($event->icalname) : 'family_other');
2079
2080 if (empty($cacheusers[$event->userownerid])) {
2081 $newuser = new User($db);
2082 $newuser->fetch($event->userownerid);
2083 $cacheusers[$event->userownerid] = $newuser;
2084 }
2085 //var_dump($cacheusers[$event->userownerid]->color);
2086
2087 // We decide to choose color of owner of event (event->userownerid is user id of owner, event->userassigned contains all users assigned to event)
2088 if (!empty($cacheusers[$event->userownerid]->color)) {
2089 $color = $cacheusers[$event->userownerid]->color;
2090 }
2091 }
2092
2093 if ($color < 0) { // Color was not set on user card. Set color according to color index.
2094 // Define color index if not yet defined
2095 $idusertouse = ($event->userownerid ? $event->userownerid : 0);
2096 if (isset($colorindexused[$idusertouse])) {
2097 $colorindex = $colorindexused[$idusertouse]; // Color already assigned to this user
2098 } else {
2099 $colorindex = $nextindextouse;
2100 $colorindexused[$idusertouse] = $colorindex;
2101 if (!empty($theme_datacolor[$nextindextouse + 1])) {
2102 $nextindextouse++; // Prepare to use next color
2103 }
2104 }
2105 if (isset($theme_datacolor[$colorindex])) {
2106 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
2107 } elseif (getDolGlobalString('THEME_ELDY_BACKBODY')) {
2108 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2109 $color = colorArrayToHex(colorStringToArray(getDolGlobalString('THEME_ELDY_BACKBODY'), array()), '');
2110 } else {
2111 $color = "ffffff";
2112 }
2113 }
2114 $cssclass = $cssclass.' eventday_'.$ymd;
2115
2116 // Defined style to disable drag and drop feature
2117 if ($event->type_code == 'AC_OTH_AUTO') {
2118 $cssclass .= " unmovable";
2119 } elseif ($event->type_code == 'HOLIDAY') {
2120 $cssclass .= " unmovable";
2121 } elseif ($event->type_code == 'BIRTHDAY') {
2122 $cssclass .= " unmovable";
2123 } elseif ($event->type_code == 'ICALEVENT') {
2124 $cssclass .= " unmovable";
2125 } elseif ($event->date_start_in_calendar && $event->date_end_in_calendar && date('Ymd', $event->date_start_in_calendar) != date('Ymd', $event->date_end_in_calendar)) {
2126 // If the event is on several days
2127 $tmpyearend = dol_print_date($event->date_start_in_calendar, '%Y', 'tzuserrel');
2128 $tmpmonthend = dol_print_date($event->date_start_in_calendar, '%m', 'tzuserrel');
2129 $tmpdayend = dol_print_date($event->date_start_in_calendar, '%d', 'tzuserrel');
2130 //var_dump($tmpyearend.' '.$tmpmonthend.' '.$tmpdayend);
2131 if ($tmpyearend != $annee || $tmpmonthend != $mois || $tmpdayend != $jour) {
2132 $cssclass .= " unmovable unmovable-mustusefirstdaytodrag";
2133 } else {
2134 $cssclass .= ' movable cursormove';
2135 }
2136 } else {
2137 if ($user->hasRight('agenda', 'allactions', 'create') ||
2138 (($event->authorid == $user->id || $event->userownerid == $user->id) && $user->hasRight('agenda', 'myactions', 'create'))) {
2139 $cssclass .= " movable cursormove";
2140 } else {
2141 $cssclass .= " unmovable";
2142 }
2143 }
2144
2145 $h = '';
2146 $nowrapontd = 1;
2147 if ($mode == 'show_day') {
2148 $h = 'height: 100%; ';
2149 $nowrapontd = 0;
2150 }
2151 if ($mode == 'show_week') {
2152 $h = 'height: 100%; ';
2153 $nowrapontd = 0;
2154 }
2155
2156 // Show event box
2157 print "\n";
2158 print '<!-- start event '.$i.' -->'."\n";
2159
2160 $morecss = '';
2161 if ($maxprint && $ireallyshown >= $maxprint) {
2162 $morecss = 'showifmore';
2163 }
2164 if ($event->type == 'birthdate' && !GETPOST('check_birthday')) {
2165 $morecss = 'hidden';
2166 }
2167 if ($event->type == 'holiday' && !GETPOST('check_holiday')) {
2168 $morecss = 'hidden';
2169 }
2170 /* I comment this because it hides event recorded from bookcal online page
2171 if ($event->type == 'bookcal_calendar' && !GETPOST('check_bookcal_calendar_'.$bookcalcalendarsarray["availabilitieslink"][$event->fk_bookcal_calendar])) {
2172 $morecss = 'hidden';
2173 } */
2174 if ($morecss != 'hidden') {
2175 $itoshow++;
2176 }
2177 if ($morecss != 'showifmore' && $morecss != 'hidden') {
2178 $ireallyshown++;
2179 }
2180
2181 //var_dump($event->type.' - '.$morecss.' - '.$cssclass.' - '.$i.' - '.$ireallyshown.' - '.$itoshow);
2182 if (isModEnabled("bookcal") && $event->type == 'bookcal_calendar') {
2183 print '<div id="event_'.$ymd.'_'.$i.'" class="event family_'.$event->type.'_'.$bookcalcalendarsarray["availabilitieslink"][$event->fk_bookcal_calendar].' '.$cssclass.($morecss ? ' '.$morecss : '').'"';
2184 } else {
2185 print '<div id="event_'.$ymd.'_'.$i.'" class="event family_'.$event->type.' '.$cssclass.($morecss ? ' '.$morecss : '').'"';
2186 }
2187 //print ' style="height: 100px;';
2188 //print ' position: absolute; top: 40px; width: 50%;';
2189 //print '"';
2190 print '>';
2191
2192 //var_dump($event->userassigned);
2193 //var_dump($event->transparency);
2194 print '<table class="centpercent cal_event';
2195 print(empty($event->transparency) ? ' cal_event_notbusy' : ' cal_event_busy');
2196 //if (empty($event->transparency) && empty($conf->global->AGENDA_NO_TRANSPARENT_ON_NOT_BUSY)) print ' opacitymedium'; // Not busy
2197 print '" style="'.$h;
2198 $colortouse = $color;
2199 // If colortouse is similar than background, we force to change it.
2200 if (empty($event->transparency) && !getDolGlobalString('AGENDA_NO_TRANSPARENT_ON_NOT_BUSY')) {
2201 print 'background: #f0f0f0;';
2202 print 'border-left: 5px solid #'.$colortouse.';';
2203 } else {
2204 print 'background: #f0f0f0;';
2205 print 'border-left: 5px solid #'.dol_color_minus($colortouse, -3).';';
2206 //print 'background: -webkit-gradient(linear, left top, left bottom, from(#'.dol_color_minus($colortouse, -3).'), to(#'.dol_color_minus($colortouse, -1).'));';
2207 }
2208 //print 'background: #'.$colortouse.';';
2209 //print 'background: -webkit-gradient(linear, left top, left bottom, from(#'.dol_color_minus($color, -3).'), to(#'.dol_color_minus($color, -1).'));';
2210 //if (!empty($event->transparency)) print 'background: #'.$color.'; background: -webkit-gradient(linear, left top, left bottom, from(#'.$color.'), to(#'.dol_color_minus($color,1).'));';
2211 //else print 'background-color: transparent !important; background: none; border: 1px solid #bbb;';
2212 //print ' -moz-border-radius:4px;"';
2213 //print 'border: 1px solid #ccc" width="100%"';
2214 print '">';
2215
2216 // First the tr of the event (only one tr for event is used, but several td)
2217 print '<tr>';
2218 print '<td class="tdoverflow nobottom small centpercent '.($nowrapontd ? 'nowrap ' : '').'cal_event'.($event->type_code == 'BIRTHDAY' ? ' cal_event_birthday' : '').'">';
2219 print '<!-- left section of event -->';
2220
2221 $daterange = '';
2222
2223 $parameters = array();
2224 $reshook = $hookmanager->executeHooks('eventOptions', $parameters, $event, $action); // Note that $action and $object may have been modified by some hooks
2225 if ($reshook < 0) {
2226 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2227 } else {
2228 '@phan-var-force ActionComm $event';
2229 if (empty($reshook)) {
2230 // Other calendar
2231 /*
2232 if (empty($event->fulldayevent)) {
2233 //print $event->getNomUrl(2).' ';
2234 }
2235 */
2236
2237 if ($event->type_code == 'BIRTHDAY') {
2238 // It's birthday calendar
2239 $picb = img_picto('', 'birthday-cake', 'class="pictofixedwidth"');
2240 print $picb.$langs->trans("Birthday").'<br>';
2241 }
2242
2243 // Date
2244 if ($event->type_code != 'HOLIDAY' && $event->type_code != 'BIRTHDAY') {
2245 if (empty($event->fulldayevent)) {
2246 // Show hours (start ... end)
2247 $tmpyearstart = dol_print_date($event->date_start_in_calendar, '%Y', 'tzuserrel');
2248 $tmpmonthstart = dol_print_date($event->date_start_in_calendar, '%m', 'tzuserrel');
2249 $tmpdaystart = dol_print_date($event->date_start_in_calendar, '%d', 'tzuserrel');
2250 $tmpyearend = dol_print_date($event->date_end_in_calendar, '%Y', 'tzuserrel');
2251 $tmpmonthend = dol_print_date($event->date_end_in_calendar, '%m', 'tzuserrel');
2252 $tmpdayend = dol_print_date($event->date_end_in_calendar, '%d', 'tzuserrel');
2253
2254 // Hour start
2255 if ($tmpyearstart == $annee && $tmpmonthstart == $mois && $tmpdaystart == $jour) {
2256 $daterange .= dol_print_date($event->date_start_in_calendar, 'hour', 'tzuserrel');
2257 if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) {
2258 if ($tmpyearstart == $tmpyearend && $tmpmonthstart == $tmpmonthend && $tmpdaystart == $tmpdayend) {
2259 $daterange .= '-';
2260 }
2261 //else
2262 //print '...';
2263 }
2264 }
2265 if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) {
2266 if ($tmpyearstart != $tmpyearend || $tmpmonthstart != $tmpmonthend || $tmpdaystart != $tmpdayend) {
2267 $daterange .= '...';
2268 }
2269 }
2270 // Hour end
2271 if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) {
2272 if ($tmpyearend == $annee && $tmpmonthend == $mois && $tmpdayend == $jour) {
2273 $daterange .= dol_print_date($event->date_end_in_calendar, 'hour', 'tzuserrel');
2274 }
2275 }
2276 } else {
2277 if ($showinfo) {
2278 print $langs->trans("EventOnFullDay")."<br>\n";
2279 }
2280 }
2281 }
2282
2283 // Show title
2284 $titletoshow = $daterange;
2285 $titletoshow .= ($titletoshow ? ' ' : '').dol_escape_htmltag($event->label);
2286
2287 if ($event->type_code != 'ICALEVENT' && $event->type_code != 'BIRTHDAY') {
2288 $savlabel = $event->label;
2289 $event->label = $titletoshow;
2290 // Note: List of users are inside $event->userassigned. Link may be clickable depending on permissions of user.
2291 $titletoshow = (($event->type_picto || $event->type_code) ? $event->getTypePicto() : '');
2292 $titletoshow .= $event->getNomUrl(0, $maxnbofchar, 'cal_event cal_event_title valignmiddle', '', 0, 0); // do not add 'inline-block' in css here: it makes the title transformed completely into '...'
2293 $event->label = $savlabel;
2294 }
2295
2296 // Loop on each assigned user
2297 $listofusertoshow = '';
2298 $posuserassigned = 0;
2299 foreach ($event->userassigned as $tmpid => $tmpdata) {
2300 if (!$posuserassigned && $titletoshow) {
2301 $listofusertoshow .= '<br>';
2302 }
2303 $posuserassigned++;
2304 if (empty($cacheusers[$tmpid])) {
2305 $newuser = new User($db);
2306 $newuser->fetch($tmpid);
2307 $cacheusers[$tmpid] = $newuser;
2308 }
2309
2310 $listofusertoshow .= $cacheusers[$tmpid]->getNomUrl(-3, '', 0, 0, 0, 0, '', 'valignmiddle inline-block');
2311 }
2312
2313 if ($event->type_code != 'BIRTHDAY' && $event->type_code != 'HOLIDAY') {
2314 print $titletoshow;
2315 print $listofusertoshow.' &nbsp;';
2316 }
2317
2318 if ($event->type_code == 'ICALEVENT') {
2319 print '<br>('.dol_trunc($event->icalname, $maxnbofchar).')';
2320 }
2321
2322 $thirdparty_id = ($event->socid > 0 ? $event->socid : ((is_object($event->societe) && $event->societe->id > 0) ? $event->societe->id : 0));
2323 $contact_id = ($event->contact_id > 0 ? $event->contact_id : ((is_object($event->contact) && $event->contact->id > 0) ? $event->contact->id : 0));
2324
2325 // If action related to company / contact
2326 $linerelatedto = '';
2327 if ($thirdparty_id > 0) {
2328 if (!isset($cachethirdparties[$thirdparty_id]) || !is_object($cachethirdparties[$thirdparty_id])) {
2329 $thirdparty = new Societe($db);
2330 $thirdparty->fetch($thirdparty_id);
2331 $cachethirdparties[$thirdparty_id] = $thirdparty;
2332 } else {
2333 $thirdparty = $cachethirdparties[$thirdparty_id];
2334 }
2335 if (!empty($thirdparty->id)) {
2336 $linerelatedto .= $thirdparty->getNomUrl(1, '', 0, 0, -1, 0, '', 'valignmiddle inline'); // using inline-block make the content completely replace with ... when too large
2337 }
2338 }
2339 if (!empty($contact_id) && $contact_id > 0) {
2340 if (empty($cachecontacts[$contact_id]) || !is_object($cachecontacts[$contact_id])) {
2341 $contact = new Contact($db);
2342 $contact->fetch($contact_id);
2343 $cachecontacts[$contact_id] = $contact;
2344 } else {
2345 $contact = $cachecontacts[$contact_id];
2346 }
2347 if ($linerelatedto) {
2348 $linerelatedto .= '&nbsp;';
2349 }
2350 if (!empty($contact->id)) {
2351 $linerelatedto .= $contact->getNomUrl(1, '', 0, '', -1, 0, 'valignmiddle inline'); // using inline-block make the content completely replace with ... when too large
2352 }
2353 }
2354 if (!empty($event->fk_element) && $event->fk_element > 0 && !empty($event->elementtype) && getDolGlobalString('AGENDA_SHOW_LINKED_OBJECT')) {
2355 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2356 if ($linerelatedto) {
2357 $linerelatedto .= '<br>';
2358 }
2359 $linerelatedto .= dolGetElementUrl($event->fk_element, $event->elementtype, 1);
2360 }
2361 if ($linerelatedto) {
2362 print ' '.$linerelatedto;
2363 }
2364 } elseif (!empty($reshook)) {
2365 print $hookmanager->resPrint;
2366 }
2367 }
2368
2369 if ($event->type_code == 'HOLIDAY') {
2370 // It's holiday calendar
2371 $tmpholiday->fetch($event->id);
2372
2373 print $tmpholiday->getNomUrl(1, -1, 0, 'valignmiddle inline-block');
2374
2375 $tmpid = $tmpholiday->fk_user;
2376 if (empty($cacheusers[$tmpid])) {
2377 $newuser = new User($db);
2378 $newuser->fetch($tmpid);
2379 $cacheusers[$tmpid] = $newuser;
2380 }
2381
2382 $listofusertoshow = '';
2383 $listofusertoshow .= "\n".'<br>'.$cacheusers[$tmpid]->getNomUrl(-1, '', 0, 0, 0, 0, '', 'paddingright valignmiddle inline-block')."\n";
2384 print $listofusertoshow;
2385 }
2386
2387 // Show location
2388 if ($showinfo) {
2389 if ($event->location) {
2390 print '<br>';
2391 print $langs->trans("Location").': '.$event->location;
2392 }
2393 }
2394
2395 print '</td>';
2396
2397 // Status - Percent
2398 $withstatus = 0;
2399 if ($event->type_code != 'HOLIDAY' && $event->type_code != 'BIRTHDAY' && $event->type_code != 'ICALEVENT') {
2400 $withstatus = 1;
2401 if ($event->percentage >= 0) {
2402 $withstatus = 2;
2403 }
2404 }
2405 print '<td class="nobottom right nowrap cal_event_right'.($withstatus >= 2 ? ' cal_event_right_status' : '').'">';
2406 if ($withstatus) {
2407 print $event->getLibStatut(3, 1);
2408 } else {
2409 print '&nbsp;';
2410 }
2411 print '</td></tr></table>';
2412 print '</div><!-- end event '.$i.' -->'."\n";
2413
2414 $i++;
2415 } else {
2416 print '<a href="'.DOL_URL_ROOT.'/comm/action/index.php?mode='.$mode.'&maxprint=0&month='.((int) $monthshown).'&year='.((int) $year);
2417 print($status ? '&status='.$status : '').($filter ? '&filter='.urlencode($filter) : '');
2418 print($filtert ? '&search_filtert='.urlencode((string) $filtert) : '');
2419 print($usergroup ? '&search_usergroup='.urlencode((string) $usergroup) : '');
2420 print($actioncode != '' ? '&search_actioncode='.urlencode($actioncode) : '');
2421 print '">'.img_picto("all", "1downarrow_selected.png").' ...';
2422 print ' +'.(count($eventarray[$daykey]) - $maxprint);
2423 print '</a>';
2424 break;
2425 //$ok=false; // To avoid to show twice the link
2426 }
2427 }
2428
2429 break;
2430 }
2431 }
2432 if (!$i) { // No events
2433 print '&nbsp;';
2434 }
2435
2436 if (getDolGlobalString('MAIN_JS_SWITCH_AGENDA') && $itoshow > $ireallyshown && $maxprint) {
2437 print '<div class="center cursorpointer" id="more_'.$ymd.'">'.img_picto("All", "angle-double-down", 'class="warning"').' +'.($itoshow - $ireallyshown).'</div>';
2438 //print ' +'.(count($eventarray[$daykey])-$maxprint);
2439
2440 print '<script type="text/javascript">'."\n";
2441 print 'jQuery(document).ready(function () {'."\n";
2442 print ' var open=0;'."\n";
2443 print ' jQuery("#more_'.$ymd.'").click(function() { console.log("Click on showmore for '.$ymd.'"); reinit_day_'.$ymd.'(); event.stopImmediatePropagation(); });'."\n";
2444 print ' function reinit_day_'.$ymd.'() {'."\n";
2445 print ' jQuery(".eventday_'.$ymd.'.showifmore").toggle();'."\n";
2446 print ' open = open + 1; if (open > 1) { open = 0; }'."\n";
2447 print ' if (open) { ';
2448 print ' jQuery("#more_'.$ymd.'").html(\''.img_picto("All", "angle-double-up", 'class="warning"').'\');'."\n";
2449 print ' } else { ';
2450 print ' jQuery("#more_'.$ymd.'").html(\''.img_picto("All", "angle-double-down", 'class="warning"').' +'.($itoshow - $ireallyshown).'\');'."\n";
2451 print ' }'."\n";
2452 print ' }'."\n";
2453 print '});'."\n";
2454 print '</script>'."\n";
2455 }
2456
2457 print '</div></div>'; // td tr
2458
2459 print '</div>'; // table
2460 print "\n";
2461}
2462
2463
2472function dol_color_minus($color, $minus, $minusunit = 16)
2473{
2474 $newcolor = $color;
2475 if ($minusunit == 16 && is_array($newcolor)) {
2476 $newcolor[0] = dechex(max(min(hexdec($newcolor[0]) - $minus, 15), 0));
2477 $newcolor[2] = dechex(max(min(hexdec($newcolor[2]) - $minus, 15), 0));
2478 $newcolor[4] = dechex(max(min(hexdec($newcolor[4]) - $minus, 15), 0));
2479 } else {
2480 // Not yet implemented
2481 }
2482 return $newcolor;
2483}
2484
2492function sort_events_by_date($a, $b)
2493{
2494 // Sort holidays at first
2495 if ($a->type_code === 'HOLIDAY') {
2496 return -1;
2497 }
2498 if ($b->type_code === 'HOLIDAY') {
2499 return 1;
2500 }
2501
2502 // datep => Event start time
2503 // datef => Event end time
2504
2505 // Events have different start time
2506 if ($a->datep !== $b->datep) {
2507 return $a->datep - $b->datep;
2508 }
2509
2510 // Events have same start time and no end time
2511 if ((!is_numeric($b->datef)) || (!is_numeric($a->datef))) {
2512 return sort_events_by_percentage($a, $b);
2513 }
2514
2515 // Events have the same start time and same end time
2516 if ($b->datef === $a->datef) {
2517 return sort_events_by_percentage($a, $b);
2518 }
2519
2520 // Events have the same start time, but have different end time -> longest event first
2521 return $b->datef - $a->datef;
2522}
2523
2531function sort_events_by_percentage($a, $b)
2532{
2533 // Sort events with no percentage before each other
2534 // (useful to sort holidays, sick days or similar on the top)
2535
2536 if ($a->percentage < 0) {
2537 return -1;
2538 }
2539
2540 if ($b->percentage < 0) {
2541 return 1;
2542 }
2543
2544 return $b->percentage - $a->percentage;
2545}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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.
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
print $object position
Definition edit.php:207
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:1600
$cacheusers
Definition index.php:1598
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
dol_get_prev_month($month, $year)
Return previous month.
Definition date.lib.php:537
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:678
dol_get_next_day($day, $month, $year)
Return next day.
Definition date.lib.php:522
dol_get_next_week($day, $week, $month, $year)
Return next week.
Definition date.lib.php:596
dol_get_first_day_week($day, $month, $year, $gm=false)
Return first day of week for a date.
Definition date.lib.php:693
dol_get_prev_day($day, $month, $year)
Return previous day.
Definition date.lib.php:506
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:618
dol_get_next_month($month, $year)
Return next month.
Definition date.lib.php:556
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:449
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:637
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0, $tz='')
Add a delay to a date.
Definition date.lib.php:128
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...
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)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
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_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.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
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).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
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.
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...
conf($dolibarr_main_document_root)
Load conf file (file must exists)
Definition inc.php:426
if(getDolGlobalString( 'TAKEPOS_SHOW_CUSTOMER')) print $langs trans('Date')." left 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 PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
Definition receipt.php:469
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.