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