dolibarr 23.0.3
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 $event->datep = $db->jdate($obj->date_start) + (empty($obj->halfday) || $obj->halfday == 1 ? 0 : 12) * 60 * 60;
1211 $event->datef = $db->jdate($obj->date_end) + (empty($obj->halfday) || $obj->halfday == -1 ? 24 : 12) * 60 * 60 - 1;
1212 $event->date_start_in_calendar = $event->datep;
1213 $event->date_end_in_calendar = $event->datef;
1214
1215 if ($obj->status == 3) {
1216 // Show no symbol for leave with state "leave approved"
1217 $event->percentage = -1;
1218 } elseif ($obj->status == 2) {
1219 // Show TO-DO symbol for leave with state "leave wait for approval"
1220 $event->percentage = 0;
1221 }
1222
1223 $event->label = $langs->trans("Holiday");
1224
1225 $daycursor = $event->date_start_in_calendar;
1226 $annee = (int) dol_print_date($daycursor, '%Y', 'tzuserrel');
1227 $mois = (int) dol_print_date($daycursor, '%m', 'tzuserrel');
1228 $jour = (int) dol_print_date($daycursor, '%d', 'tzuserrel');
1229
1230 $daycursorend = $event->date_end_in_calendar;
1231 $anneeend = (int) dol_print_date($daycursorend, '%Y', 'tzuserrel');
1232 $moisend = (int) dol_print_date($daycursorend, '%m', 'tzuserrel');
1233 $jourend = (int) dol_print_date($daycursorend, '%d', 'tzuserrel');
1234
1235 // daykey must be date that represent day box in calendar so must be a user time
1236 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1237 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1238 $ifornbofdays = 0;
1239 do {
1240 $ifornbofdays++;
1241
1242 $firstdayofholiday = ($ifornbofdays == 1);
1243 $lastdayofholiday = ($daykeygmt == dol_get_first_hour($event->date_end_in_calendar, 'gmt'));
1244
1245 /*
1246 var_dump(dol_print_date($daykeygmt, 'dayhour', 'gmt'));
1247 var_dump(dol_print_date(dol_get_first_hour($event->date_end_in_calendar, 'gmt'), 'dayhour', 'gmt'));
1248 var_dump($lastdayofholiday);
1249 var_dump($obj->halfday);
1250 */
1251
1252 if ((in_array($obj->halfday, array(1, 2)) == 1 && $lastdayofholiday) || (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday)) {
1253 // We create a copy of event because we want tochange the label
1254 $newevent = dol_clone($event, 1);
1255 if (in_array($obj->halfday, array(1, 2)) && $lastdayofholiday) {
1256 $newevent->label .= ' ('.$langs->trans("Morning").')';
1257 } elseif (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday) {
1258 $newevent->label .= ' ('.$langs->trans("Afternoon").')';
1259 }
1260 $eventarray[$daykey][] = $newevent; // We need to use ->gtTypePicto, getXXXon object, so clone must be PHP clone.
1261 } else {
1262 $eventarray[$daykey][] = $event; // We can use the event unchanged
1263 }
1264
1265 $daykey += 60 * 60 * 24;
1266 $daykeygmt += 60 * 60 * 24;
1267 } while ($daykey <= $event->date_end_in_calendar);
1268
1269 $i++;
1270 }
1271 }
1272}
1273
1274// EXTERNAL CALENDAR
1275// Complete $eventarray with external import Ical
1276if (count($listofextcals)) {
1277 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/ical.class.php';
1278
1279 foreach ($listofextcals as $key => $extcal) {
1280 $url = $extcal['src']; // Example: https://www.google.com/calendar/ical/eldy10%40gmail.com/private-cde92aa7d7e0ef6110010a821a2aaeb/basic.ics
1281 $namecal = $extcal['name'];
1282 $offsettz = $extcal['offsettz'];
1283 $colorcal = $extcal['color'];
1284 $buggedfile = $extcal['buggedfile'];
1285
1286 $pathforcachefile = dol_sanitizePathName($conf->user->dir_temp).'/'.dol_sanitizeFileName('extcal_'.$namecal.'_user'.$user->id).'.cache';
1287 //var_dump($pathforcachefile);exit;
1288
1289 $ical = new ICal();
1290 $ical->parse($url, $pathforcachefile, $DELAYFORCACHE);
1291 if ($ical->error) {
1292 // Save error message for extcal
1293 $listofextcals[$key]['error'] = $ical->error;
1294 $s .= '<br><div class="warning">'.dol_escape_htmltag($listofextcals[$key]['name']).': '.$url.'<br>Error message: '.dol_escape_htmltag($ical->error).'</div>';
1295 }
1296
1297 // After this $ical->cal['VEVENT'] contains array of events, $ical->cal['DAYLIGHT'] contains daylight info, $ical->cal['STANDARD'] contains non daylight info, ...
1298 //var_dump($ical->cal); exit;
1299 $icalevents = array();
1300 $tmparray = $ical->get_event_list();
1301 if (is_array($tmparray)) {
1302 $icalevents = array_merge($icalevents, $tmparray); // Add $ical->cal['VEVENT']
1303 }
1304 $tmparray = $ical->get_freebusy_list();
1305 if (is_array($tmparray)) {
1306 $icalevents = array_merge($icalevents, $tmparray); // Add $ical->cal['VFREEBUSY']
1307 }
1308
1309 $nbevents += count($icalevents);
1310
1311 if (count($icalevents) > 0) {
1312 // Duplicate all repeatable events into new entries
1313 $moreicalevents = array();
1314 foreach ($icalevents as $icalevent) {
1315 if (isset($icalevent['RRULE']) && is_array($icalevent['RRULE'])) { //repeatable event
1316 //if ($event->date_start_in_calendar < $firstdaytoshow) $event->date_start_in_calendar=$firstdaytoshow;
1317 //if ($event->date_end_in_calendar > $lastdaytoshow) $event->date_end_in_calendar=($lastdaytoshow-1);
1318 if ($icalevent['DTSTART;VALUE=DATE']) { //fullday event
1319 $datecurstart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
1320 $datecurend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
1321 } elseif (is_array($icalevent['DTSTART']) && !empty($icalevent['DTSTART']['unixtime'])) {
1322 $datecurstart = $icalevent['DTSTART']['unixtime'];
1323 $datecurend = $icalevent['DTEND']['unixtime'];
1324 if (!empty($ical->cal['DAYLIGHT']['DTSTART']) && $datecurstart) {
1325 //var_dump($ical->cal);
1326 $tmpcurstart = $datecurstart;
1327 $tmpcurend = $datecurend;
1328 $tmpdaylightstart = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['DAYLIGHT']['DTSTART'];
1329 $tmpdaylightend = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['STANDARD']['DTSTART'];
1330 //var_dump($tmpcurstart);var_dump($tmpcurend); var_dump($ical->cal['DAYLIGHT']['DTSTART']);var_dump($ical->cal['STANDARD']['DTSTART']);
1331 // Edit datecurstart and datecurend
1332 if ($tmpcurstart >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
1333 $datecurstart -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
1334 } else {
1335 $datecurstart -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
1336 }
1337 if ($tmpcurend >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
1338 $datecurend -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
1339 } else {
1340 $datecurend -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
1341 }
1342 }
1343 // datecurstart and datecurend are now GMT date
1344 //var_dump($datecurstart); var_dump($datecurend); exit;
1345 } else {
1346 // Not a recognized record
1347 dol_syslog("Found a not recognized repeatable record with unknown date start", LOG_ERR);
1348 continue;
1349 }
1350 //print 'xx'.$datecurstart;exit;
1351
1352 $interval = (empty($icalevent['RRULE']['INTERVAL']) ? 1 : $icalevent['RRULE']['INTERVAL']);
1353 $until = empty($icalevent['RRULE']['UNTIL']) ? 0 : dol_stringtotime($icalevent['RRULE']['UNTIL'], 1);
1354 $maxrepeat = empty($icalevent['RRULE']['COUNT']) ? 0 : $icalevent['RRULE']['COUNT'];
1355 if ($until && ($until + ($datecurend - $datecurstart)) < $firstdaytoshow) {
1356 continue; // We discard repeatable event that end before start date to show
1357 }
1358 if ($datecurstart >= $lastdaytoshow) {
1359 continue; // We discard repeatable event that start after end date to show
1360 }
1361
1362 $numofevent = 0;
1363 while (($datecurstart < $lastdaytoshow) && (empty($maxrepeat) || ($numofevent < $maxrepeat))) {
1364 if ($datecurend >= $firstdaytoshow) { // We add event
1365 $newevent = $icalevent;
1366 unset($newevent['RRULE']);
1367 if ($icalevent['DTSTART;VALUE=DATE']) {
1368 $newevent['DTSTART;VALUE=DATE'] = dol_print_date($datecurstart, '%Y%m%d');
1369 $newevent['DTEND;VALUE=DATE'] = dol_print_date($datecurend + 1, '%Y%m%d');
1370 } else {
1371 $newevent['DTSTART'] = $datecurstart;
1372 $newevent['DTEND'] = $datecurend;
1373 }
1374 $moreicalevents[] = $newevent;
1375 }
1376 // Jump on next occurrence
1377 $numofevent++;
1378 $savdatecurstart = $datecurstart;
1379 if ($icalevent['RRULE']['FREQ'] == 'DAILY') {
1380 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'd');
1381 $datecurend = dol_time_plus_duree($datecurend, $interval, 'd');
1382 }
1383 if ($icalevent['RRULE']['FREQ'] == 'WEEKLY') {
1384 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'w');
1385 $datecurend = dol_time_plus_duree($datecurend, $interval, 'w');
1386 } elseif ($icalevent['RRULE']['FREQ'] == 'MONTHLY') {
1387 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'm');
1388 $datecurend = dol_time_plus_duree($datecurend, $interval, 'm');
1389 } elseif ($icalevent['RRULE']['FREQ'] == 'YEARLY') {
1390 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'y');
1391 $datecurend = dol_time_plus_duree($datecurend, $interval, 'y');
1392 }
1393 // Test to avoid infinite loop ($datecurstart must increase)
1394 if ($savdatecurstart >= $datecurstart) {
1395 dol_syslog("Found a rule freq ".$icalevent['RRULE']['FREQ']." not managed by dolibarr code. Assume 1 week frequency.", LOG_ERR);
1396 $datecurstart += 3600 * 24 * 7;
1397 $datecurend += 3600 * 24 * 7;
1398 }
1399 }
1400 }
1401 }
1402 $icalevents = array_merge($icalevents, $moreicalevents);
1403
1404 // Loop on each entry into cal file to know if entry is qualified and add an ActionComm into $eventarray
1405 foreach ($icalevents as $icalevent) {
1406 //var_dump($icalevent);
1407
1408 //print $icalevent['SUMMARY'].'->';
1409 //var_dump($icalevent);exit;
1410 if (!empty($icalevent['RRULE'])) {
1411 continue; // We found a repeatable event. It was already split into unitary events, so we discard general rule.
1412 }
1413
1414 // Create a new object action
1415 $event = new ActionComm($db);
1416 $addevent = false;
1417 if (isset($icalevent['DTSTART;VALUE=DATE'])) { // fullday event
1418 // For full day events, date are also GMT but they won't but converted using tz during output
1419 $datestart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
1420 if (empty($icalevent['DTEND;VALUE=DATE'])) {
1421 $dateend = $datestart + 86400 - 1;
1422 } else {
1423 $dateend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
1424 }
1425 //print 'x'.$datestart.'-'.$dateend;exit;
1426 //print dol_print_date($dateend,'dayhour','gmt');
1427 $event->fulldayevent = 1;
1428 $addevent = true;
1429 } elseif (!is_array($icalevent['DTSTART'])) { // not fullday event (DTSTART is not array. It is a value like '19700101T000000Z' for 00:00 in greenwitch)
1430 $datestart = $icalevent['DTSTART'];
1431 $dateend = empty($icalevent['DTEND']) ? $datestart : $icalevent['DTEND'];
1432
1433 $datestart += +($offsettz * 3600);
1434 $dateend += +($offsettz * 3600);
1435
1436 $addevent = true;
1437 //var_dump($offsettz);
1438 //var_dump(dol_print_date($datestart, 'dayhour', 'gmt'));
1439 } elseif (isset($icalevent['DTSTART']['unixtime'])) { // File contains a local timezone + a TZ (for example when using bluemind)
1440 $datestart = $icalevent['DTSTART']['unixtime'];
1441 $dateend = $icalevent['DTEND']['unixtime'];
1442
1443 $datestart += +($offsettz * 3600);
1444 $dateend += +($offsettz * 3600);
1445
1446 // $buggedfile is set to uselocalandtznodaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtznodaylight'
1447 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
1448 // TODO
1449 }
1450 // $buggedfile is set to uselocalandtzdaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtzdaylight' (for example with bluemind)
1451 if ($buggedfile === 'uselocalandtzdaylight') { // unixtime is a local date that does take daylight into account, TZID is +2 for example for 'Europe/Paris' in summer
1452 $localtzs = new DateTimeZone(preg_replace('/"/', '', $icalevent['DTSTART']['TZID']));
1453 $localtze = new DateTimeZone(preg_replace('/"/', '', $icalevent['DTEND']['TZID']));
1454 $localdts = new DateTime(dol_print_date($datestart, 'dayrfc', 'gmt'), $localtzs);
1455 $localdte = new DateTime(dol_print_date($dateend, 'dayrfc', 'gmt'), $localtze);
1456 $tmps = -1 * $localtzs->getOffset($localdts);
1457 $tmpe = -1 * $localtze->getOffset($localdte);
1458 $datestart += $tmps;
1459 $dateend += $tmpe;
1460 //var_dump($datestart);
1461 }
1462 $addevent = true;
1463 }
1464
1465 if ($addevent) {
1466 $event->id = $icalevent['UID'];
1467 $event->ref = (string) $event->id;
1468 $userId = $userstatic->findUserIdByEmail($namecal);
1469 if (!empty($userId) && $userId > 0) {
1470 $event->userassigned[$userId] = $userId;
1471 $event->percentage = -1;
1472 }
1473
1474 $event->type_code = "ICALEVENT";
1475 $event->type_label = $namecal;
1476 $event->type_color = $colorcal;
1477 $event->type = 'icalevent';
1478 $event->type_picto = 'rss';
1479
1480 $event->icalname = $namecal;
1481 $event->icalcolor = $colorcal;
1482 $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.
1483 $event->datep = $datestart + $usertime;
1484 $event->datef = $dateend + $usertime;
1485
1486 if (isset($icalevent['SUMMARY']) && $icalevent['SUMMARY']) {
1487 $event->label = dol_string_nohtmltag($icalevent['SUMMARY']);
1488 } elseif (isset($icalevent['DESCRIPTION']) && $icalevent['DESCRIPTION']) {
1489 $event->label = dol_nl2br(dol_string_nohtmltag($icalevent['DESCRIPTION']), 1);
1490 } else {
1491 $event->label = $langs->trans("ExtSiteNoLabel");
1492 }
1493
1494 // Priority (see https://www.kanzaki.com/docs/ical/priority.html)
1495 // LOW = 0 to 4
1496 // MEDIUM = 5
1497 // HIGH = 6 to 9
1498 if (!empty($icalevent['PRIORITY'])) {
1499 $event->priority = $icalevent['PRIORITY'];
1500 }
1501
1502 // Transparency (see https://www.kanzaki.com/docs/ical/transp.html)
1503 if (!empty($icalevent['TRANSP'])) {
1504 if ($icalevent['TRANSP'] == "TRANSPARENT") {
1505 $event->transparency = 0; // 0 = available / free
1506 }
1507 if ($icalevent['TRANSP'] == "OPAQUE") {
1508 $event->transparency = 1; // 1 = busy
1509 }
1510
1511 // TODO: MS outlook states
1512 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:TRANSPARENT => Available / Free
1513 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:OPAQUE => Work another place
1514 // X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE + TRANSP:OPAQUE => With reservations
1515 // X-MICROSOFT-CDO-BUSYSTATUS:BUSY + TRANSP:OPAQUE => Busy
1516 // X-MICROSOFT-CDO-BUSYSTATUS:OOF + TRANSP:OPAQUE => Away from the office / off-site
1517 }
1518
1519 if (!empty($icalevent['LOCATION'])) {
1520 $event->location = $icalevent['LOCATION'];
1521 }
1522
1523 $event->date_start_in_calendar = $event->datep;
1524
1525 if ($event->datef != '' && $event->datef >= $event->datep) {
1526 $event->date_end_in_calendar = $event->datef;
1527 } else {
1528 $event->date_end_in_calendar = $event->datep;
1529 }
1530
1531 // Add event into $eventarray if date range are ok.
1532 if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) {
1533 //print 'x'.$datestart.'-'.$dateend;exit;
1534 //print 'x'.$datestart.'-'.$dateend;exit;
1535 //print 'x'.$datestart.'-'.$dateend;exit;
1536 // This record is out of visible range
1537 } else {
1538 if ($event->date_start_in_calendar < $firstdaytoshow) {
1539 $event->date_start_in_calendar = $firstdaytoshow;
1540 }
1541 if ($event->date_end_in_calendar >= $lastdaytoshow) {
1542 $event->date_end_in_calendar = ($lastdaytoshow - 1);
1543 }
1544
1545 // Add an entry in actionarray for each day
1546 $daycursor = $event->date_start_in_calendar;
1547 $annee = (int) dol_print_date($daycursor, '%Y', 'tzuserrel');
1548 $mois = (int) dol_print_date($daycursor, '%m', 'tzuserrel');
1549 $jour = (int) dol_print_date($daycursor, '%d', 'tzuserrel');
1550
1551 // Loop on each day covered by action to prepare an index to show on calendar
1552 $loop = true;
1553 $j = 0;
1554 // daykey must be date that represent day box in calendar so must be a user time
1555 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1556 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1557 do {
1558 //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').' ';
1559 $eventarray[$daykey][] = $event;
1560 $daykey += 60 * 60 * 24;
1561 $daykeygmt += 60 * 60 * 24; // Add one day
1562 if (($event->fulldayevent ? $daykeygmt : $daykey) > $event->date_end_in_calendar) {
1563 $loop = false;
1564 }
1565 } while ($loop);
1566 }
1567 }
1568 }
1569 }
1570 }
1571}
1572
1573// Complete $eventarray with events coming from external module
1574$parameters = array();
1575$object = null;
1576$reshook = $hookmanager->executeHooks('getCalendarEvents', $parameters, $object, $action);
1577if (!empty($hookmanager->resArray['eventarray'])) {
1578 foreach ($hookmanager->resArray['eventarray'] as $keyDate => $events) {
1579 if (!isset($eventarray[$keyDate])) {
1580 $eventarray[$keyDate] = array();
1581 }
1582 $eventarray[$keyDate] = array_merge($eventarray[$keyDate], $events);
1583 }
1584}
1585
1586// Sort events
1587foreach ($eventarray as $keyDate => &$dateeventarray) {
1588 usort($dateeventarray, 'sort_events_by_date');
1589}
1590
1591
1592$maxnbofchar = 0;
1593$cachethirdparties = array();
1594$cachecontacts = array();
1595$cacheusers = array();
1596// default values
1598 array(137, 86, 161),
1599 array(60, 147, 183),
1600 array(250, 190, 80),
1601 array(80, 166, 90),
1602 array(190, 190, 100),
1603 array(91, 115, 247),
1604 array(140, 140, 220),
1605 array(190, 120, 120),
1606 array(115, 125, 150),
1607 array(100, 170, 20),
1608 array(150, 135, 125),
1609 array(85, 135, 150),
1610 array(150, 135, 80),
1611 array(150, 80, 150)
1612);
1613
1614// Define theme_datacolor array
1615$color_file = DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/theme_vars.inc.php";
1616if (is_readable($color_file)) {
1617 global $theme_datacolor;
1618 include $color_file;
1620}
1621
1622$massactionbutton = '';
1623
1624print_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);
1625
1626if ($nbevents > $MAXONSAMEPAGE) {
1627 print info_admin('Number of results has been truncated to '.$MAXONSAMEPAGE, 0, 0, 'warning').'<br>';
1628}
1629
1630// Show div with list of calendars
1631print $s;
1632
1633
1634if (empty($mode) || $mode == 'show_month') { // View by month
1635 $newparam = $param; // newparam is for birthday links
1636 $newparam = preg_replace('/check_birthday=/i', 'check_birthday_=', $newparam); // To avoid replacement when replace day= is done
1637 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1638 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1639 $newparam = preg_replace('/day=[0-9]+&?/i', '', $newparam);
1640 $newparam = preg_replace('/month=[0-9]+&?/i', '', $newparam);
1641 $newparam = preg_replace('/year=[0-9]+&?/i', '', $newparam);
1642 $newparam = preg_replace('/viewcal=[0-9]+&?/i', '', $newparam);
1643 $newparam = preg_replace('/check_birthday_=/i', 'check_birthday=', $newparam); // Restore correct parameter
1644 $newparam .= '&viewcal=1';
1645
1646 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1647 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid, $search_categ_cus);
1648 print '</div>';
1649
1650 print '<div class="div-table-responsive-no-min sectioncalendarbymonth maxscreenheightless300">';
1651 print '<table class="centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore">';
1652 print ' <tr class="liste_titre sticky">';
1653 // Column title of weeks numbers
1654 echo ' <td class="center">#</td>';
1655 $i = 0;
1656 while ($i < 7) {
1657 print ' <td class="center bold uppercase tdfordaytitle'.($i == 0 ? ' borderleft' : '').'">';
1658 $numdayinweek = (($i + (getDolGlobalInt('MAIN_START_WEEK', 1))) % 7);
1659 if (!empty($conf->dol_optimize_smallscreen)) {
1660 $labelshort = array(0 => 'SundayMin', 1 => 'MondayMin', 2 => 'TuesdayMin', 3 => 'WednesdayMin', 4 => 'ThursdayMin', 5 => 'FridayMin', 6 => 'SaturdayMin');
1661 print $langs->trans($labelshort[$numdayinweek]);
1662 } else {
1663 print $langs->trans("Day".$numdayinweek);
1664 }
1665 print ' </td>'."\n";
1666 $i++;
1667 }
1668 echo ' </tr>'."\n";
1669
1670 $todayarray = dol_getdate($now, true);
1671 $todaytms = dol_mktime(0, 0, 0, $todayarray['mon'], $todayarray['mday'], $todayarray['year']);
1672
1673 // In loops, tmpday contains day nb in current month (can be zero or negative for days of previous month)
1674 //var_dump($eventarray);
1675 for ($iter_week = 0; $iter_week < 6; $iter_week++) {
1676 echo " <tr>\n";
1677 // Get date of the current day, format 'yyyy-mm-dd'
1678 if ($tmpday <= 0) { // If number of the current day is in previous month
1679 $currdate0 = sprintf("%04d", $prev_year).sprintf("%02d", $prev_month).sprintf("%02d", $max_day_in_prev_month + $tmpday);
1680 } elseif ($tmpday <= $max_day_in_month) { // If number of the current day is in current month
1681 $currdate0 = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $tmpday);
1682 } else { // If number of the current day is in next month
1683 $currdate0 = sprintf("%04d", $next_year).sprintf("%02d", $next_month).sprintf("%02d", $tmpday - $max_day_in_month);
1684 }
1685 // Get week number for the targeted date '$currdate0'
1686 $numweek0 = date("W", strtotime(date($currdate0)));
1687 // Show the week number, and define column width
1688 echo ' <td class="center weeknumber opacitymedium" width="2%">'.$numweek0.'</td>';
1689
1690 for ($iter_day = 0; $iter_day < 7; $iter_day++) {
1691 if ($tmpday <= 0) {
1692 /* Show days before the beginning of the current month (previous month) */
1693 $style = 'cal_other_month cal_past';
1694 if ($iter_day == 6) {
1695 $style .= ' cal_other_month_right';
1696 }
1697 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1698 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1699 show_day_events($db, $max_day_in_prev_month + $tmpday, $prev_month, $prev_year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam);
1700 echo " </td>\n";
1701 } elseif ($tmpday <= $max_day_in_month) {
1702 /* Show days of the current month */
1703 $curtime = dol_mktime(0, 0, 0, $month, $tmpday, $year);
1704 $style = 'cal_current_month';
1705 if ($iter_day == 6) {
1706 $style .= ' cal_current_month_right';
1707 }
1708 $today = 0;
1709 if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $month && $todayarray['year'] == $year) {
1710 $today = 1;
1711 }
1712 if ($today) {
1713 $style = 'cal_today';
1714 }
1715 if ($curtime < $todaytms) {
1716 $style .= ' cal_past';
1717 }
1718 //var_dump($todayarray['mday']."==".$tmpday." && ".$todayarray['mon']."==".$month." && ".$todayarray['year']."==".$year.' -> '.$style);
1719 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1720 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1721 show_day_events($db, $tmpday, $month, $year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam, 0, 60, 0, $bookcalcalendars);
1722 echo "</td>\n";
1723 } else {
1724 /* Show days after the current month (next month) */
1725 $style = 'cal_other_month';
1726 if ($iter_day == 6) {
1727 $style .= ' cal_other_month_right';
1728 }
1729 echo ' <td class="'.$style.' nowrap tdtop" width="14%">';
1730 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1731 show_day_events($db, $tmpday - $max_day_in_month, $next_month, $next_year, $month, $style, $eventarray, $maxprint, $maxnbofchar, $newparam);
1732 echo "</td>\n";
1733 }
1734 $tmpday++;
1735 }
1736 echo " </tr>\n";
1737 }
1738 print "</table>\n";
1739 print '</div>';
1740
1741 print '<input type="hidden" name="actionmove" value="mupdate">';
1742 print '<input type="hidden" name="backtopage" value="'.dol_escape_htmltag($_SERVER['PHP_SELF']).'?mode=show_month&'.dol_escape_htmltag($_SERVER['QUERY_STRING']).'">';
1743 print '<input type="hidden" name="newdate" id="newdate">';
1744} elseif ($mode == 'show_week') {
1745 // View by week
1746 $newparam = $param; // newparam is for birthday links
1747 $newparam = preg_replace('/check_birthday=/i', 'check_birthday_=', $newparam); // To avoid replacement when replace day= is done
1748 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1749 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1750 $newparam = preg_replace('/day=[0-9]+&?/i', '', $newparam);
1751 $newparam = preg_replace('/month=[0-9]+&?/i', '', $newparam);
1752 $newparam = preg_replace('/year=[0-9]+&?/i', '', $newparam);
1753 $newparam = preg_replace('/viewweek=[0-9]+&?/i', '', $newparam);
1754 $newparam = preg_replace('/check_birthday_=/i', 'check_birthday=', $newparam); // Restore correct parameter
1755 $newparam .= '&viewweek=1';
1756
1757 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1758 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid);
1759 print '</div>';
1760
1761 print '<div class="div-table-responsive-no-min sectioncalendarbyweek maxscreenheightless300">';
1762 print '<table class="centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore">';
1763 print ' <tr class="liste_titre">';
1764 $i = 0;
1765 while ($i < 7) {
1766 echo ' <td class="center bold uppercase tdfordaytitle">'.$langs->trans("Day".(($i + (getDolGlobalInt('MAIN_START_WEEK', 1))) % 7))."</td>\n";
1767 $i++;
1768 }
1769 echo " </tr>\n";
1770
1771 echo " <tr>\n";
1772
1773 for ($iter_day = 0; $iter_day < 7; $iter_day++) {
1774 // Show days of the current week
1775 $curtime = dol_time_plus_duree($firstdaytoshow, $iter_day, 'd'); // $firstdaytoshow is in timezone of server
1776 $tmpday = (int) dol_print_date($curtime, '%d', 'tzuserrel');
1777 $tmpmonth = (int) dol_print_date($curtime, '%m', 'tzuserrel');
1778 $tmpyear = (int) dol_print_date($curtime, '%Y', 'tzuserrel');
1779
1780 $style = 'cal_current_month';
1781 if ($iter_day == 6) {
1782 $style .= ' cal_other_month_right';
1783 }
1784
1785 $today = 0;
1786 $todayarray = dol_getdate($now, true);
1787 if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $tmpmonth && $todayarray['year'] == $tmpyear) {
1788 $today = 1;
1789 }
1790 if ($today) {
1791 $style = 'cal_today';
1792 }
1793
1794 echo ' <td class="'.$style.'" width="14%" valign="top">';
1795 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1796 show_day_events($db, $tmpday, $tmpmonth, $tmpyear, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 0, $bookcalcalendars);
1797 echo " </td>\n";
1798 }
1799 echo " </tr>\n";
1800
1801 print "</table>\n";
1802 print '</div>';
1803
1804 echo '<input type="hidden" name="actionmove" value="mupdate">';
1805 echo '<input type="hidden" name="backtopage" value="'.dol_escape_htmltag($_SERVER['PHP_SELF']).'?mode=show_week&'.dol_escape_htmltag($_SERVER['QUERY_STRING']).'">';
1806 echo '<input type="hidden" name="newdate" id="newdate">';
1807} else { // View by day
1808 $newparam = $param; // newparam is for birthday links
1809 $newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1810 $newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1811 $newparam = preg_replace('/viewday=[0-9]+&?/i', '', $newparam);
1812 $newparam .= '&viewday=1';
1813 // Code to show just one day
1814 $style = 'cal_current_month cal_current_month_oneday';
1815 $today = 0;
1816 $todayarray = dol_getdate($now, true);
1817 if ($todayarray['mday'] == $day && $todayarray['mon'] == $month && $todayarray['year'] == $year) {
1818 $today = 1;
1819 }
1820 //if ($today) $style='cal_today';
1821
1822 $timestamp = dol_mktime(12, 0, 0, $month, $day, $year);
1823 $arraytimestamp = dol_getdate($timestamp);
1824
1825 print '<div class="liste_titre liste_titre_bydiv centpercent">';
1826 print_actions_filter($form, $canedit, $status, $year, $month, $day, $check_birthday, '', $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid);
1827 print '</div>';
1828
1829 print '<div class="div-table-responsive-no-min sectioncalendarbyday maxscreenheightless300">';
1830 echo '<table class="tagtable centpercent noborder nocellnopadd cal_pannel cal_month listwithfilterbefore" style="margin-bottom: 10px !important;">';
1831
1832 echo ' <tr class="tagtr liste_titre">';
1833 echo ' <td class="tagtd center bold uppercase">'.$langs->trans("Day".$arraytimestamp['wday'])."</td>\n";
1834 echo " </tr>\n";
1835
1836 /*
1837 echo ' <div class="tagtr">';
1838 echo ' <div class="tagtd width100"></div>';
1839 echo ' <div class="tagtd center">';
1840 echo show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, -1);
1841 echo ' </div>'."\n";
1842 echo " </div>\n";
1843 */
1844
1845 print '<tr><td>';
1846
1847 /* WIP View per hour */
1848 $useviewhour = 0;
1849 if ($useviewhour) {
1850 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
1851
1852 $maxheightwin = (isset($_SESSION["dol_screenheight"]) && $_SESSION["dol_screenheight"] > 500) ? ($_SESSION["dol_screenheight"] - 200) : 660; // Also into index.php file
1853
1854 echo '<div style="max-height: '.$maxheightwin.'px;">';
1855 echo '<div class="tagtable centpercent calendarviewcontainer">';
1856
1857 $maxnbofchar = 80;
1858
1859 $tmp = explode('-', getDolGlobalString('MAIN_DEFAULT_WORKING_HOURS'));
1860 $minhour = round((float) $tmp[0], 0);
1861 $maxhour = round((float) $tmp[1], 0);
1862 if ($minhour > 23) {
1863 $minhour = 23;
1864 }
1865 if ($maxhour < 1) {
1866 $maxhour = 1;
1867 }
1868 if ($maxhour <= $minhour) {
1869 $maxhour = $minhour + 1;
1870 }
1871
1872 $i = 0;
1873 $j = 0;
1874 while ($i < 24) {
1875 echo ' <div class="tagtr calendarviewcontainertr">'."\n";
1876 echo ' <div class="tagtd width100 tdtop">'.dol_print_date($i * 3600, 'hour', 'gmt').'</div>';
1877 echo ' <div class="tagtd '.$style.' tdtop"></div>'."\n";
1878 echo ' </div>'."\n";
1879 $i++;
1880 $j++;
1881 }
1882
1883 echo '</div></div>';
1884
1885 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1886 show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 1, $bookcalcalendars);
1887
1888 print '</div>';
1889 } else {
1890 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
1891
1892 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1893 show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 0, $bookcalcalendars);
1894
1895 print '</div>';
1896 }
1897
1898
1899 print '</td></tr>';
1900
1901 echo '</table>';
1902 print '</div>';
1903}
1904
1905print "\n".'</form>';
1906
1907// End of page
1908llxFooter();
1909$db->close();
1910
1911
1931function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventarray, $maxprint = 0, $maxnbofchar = 16, $newparam = '', $showinfo = 0, $minheight = 60, $nonew = 0, $bookcalcalendarsarray = array())
1932{
1933 global $user, $conf, $langs;
1934 global $action, $mode, $filter, $filtert, $status, $actioncode, $usergroup; // Filters used into search form
1935 global $theme_datacolor;
1936 global $cachethirdparties, $cachecontacts, $cacheusers, $colorindexused;
1937 global $hookmanager;
1938
1939 '@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
1940 @phan-var-force User[] $cacheusers
1941 @phan-var-force array<int<0,3>> $colorindexused';
1948 if ($conf->use_javascript_ajax) { // Enable the "Show more button..."
1949 $conf->global->MAIN_JS_SWITCH_AGENDA = 1;
1950 }
1951
1952 $dateint = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $day);
1953 $datenowint = dol_print_date(dol_now(), "%Y%m%d");
1954 //print 'show_day_events day='.$day.' month='.$month.' year='.$year.' dateint='.$dateint.' datenowint='.$datenowint;
1955
1956 print "\n";
1957
1958 $curtime = dol_mktime(0, 0, 0, $month, $day, $year);
1959 $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;
1960 $urltocreate = '';
1961 if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) {
1962 $newparam .= '&month='.str_pad((string) $month, 2, "0", STR_PAD_LEFT).'&year='.$year;
1963 $hourminsec = '100000';
1964 $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 : ''));
1965 }
1966
1967 // Line with title of day
1968 print '<div id="dayevent_'.$dateint.'" class="dayevent tagtable centpercent nobordernopadding">'."\n";
1969
1970 if ($nonew <= 0) {
1971 print '<div class="tagtr cursorpointer" onclick="window.location=\''.$urltocreate.'\';"><div class="nowrap tagtd"><div class="left inline-block">';
1972 print '<a class="dayevent-aday" style="color: #666" href="'.$urltoshow.'">';
1973 print ($datenowint == $dateint ? '<span class="badgeneutral">' : '');
1974 if ($showinfo) {
1975 print dol_print_date($curtime, 'daytextshort');
1976 } else {
1977 print dol_print_date($curtime, '%d');
1978 }
1979 print ($datenowint == $dateint ? '</span>' : '');
1980 print '</a>';
1981 print '</div><div class="nowrap floatright inline-block marginrightonly">';
1982 if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) {
1983 print '<a class="cursoradd" href="'.$urltocreate.'">'; // Explicit link, useful for nojs interfaces
1984 print img_picto($langs->trans("NewAction"), 'edit_add.png');
1985 print '</a>';
1986 }
1987 print '</div></div></div>'."\n";
1988 }
1989
1990 if ($nonew < 0) {
1991 print '</div>';
1992 return;
1993 }
1994
1995 // Line with td contains all div of each events
1996 print '<div class="tagtr">';
1997 print '<div class="tagtd centpercent agendacell sortable">';
1998
1999 //$curtime = dol_mktime (0, 0, 0, $month, $day, $year);
2000 $i = 0;
2001 $ireallyshown = 0;
2002 $itoshow = 0;
2003 $numother = 0;
2004 $numbirthday = 0;
2005 $numical = 0;
2006 $numicals = array();
2007 $ymd = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $day);
2008
2009 $colorindexused[$user->id] = 0; // Color index for current user (user->id) is always 0
2010 $nextindextouse = is_array($colorindexused) ? count($colorindexused) : 0; // At first run this is 0, so fist user has 0, next 1, ...
2011 //var_dump($colorindexused);
2012
2013 include_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
2014 $tmpholiday = new Holiday($db);
2015
2016 foreach ($eventarray as $daykey => $notused) { // daykey is the 'YYYYMMDD' to show according to user
2017 $annee = (int) dol_print_date($daykey, '%Y', 'gmt'); // We use gmt because we want the value represented by string 'YYYYMMDD'
2018 $mois = (int) dol_print_date($daykey, '%m', 'gmt'); // We use gmt because we want the value represented by string 'YYYYMMDD'
2019 $jour = (int) dol_print_date($daykey, '%d', 'gmt'); // We use gmt because we want the value represented by string 'YYYYMMDD'
2020
2021 //print 'event daykey='.$daykey.' dol_print_date(daykey)='.dol_print_date($daykey, 'dayhour', 'gmt').' jour='.$jour.' mois='.$mois.' annee='.$annee."<br>\n";
2022 //print 'event daykey='.$daykey.' dol_print_date(daykey)='.dol_print_date($daykey, 'dayhour', 'gmt').' day='.$day.' month='.$month.' year='.$year."<br>\n";
2023
2024 if ($day == $jour && $month == $mois && $year == $annee) {
2025 foreach ($eventarray[$daykey] as $index => $event) {
2026 if ($i < $maxprint || $maxprint == 0 || getDolGlobalString('MAIN_JS_SWITCH_AGENDA')) {
2027 $keysofuserassigned = array_keys($event->userassigned);
2028
2029 // Define $color (Hex string like '0088FF') and $cssclass of event
2030 $color = -1;
2031 $cssclass = '';
2032 $colorindex = -1;
2033 if (in_array($user->id, $keysofuserassigned)) {
2034 $cssclass = 'family_mytasks';
2035
2036 if (empty($cacheusers[$event->userownerid])) {
2037 $newuser = new User($db);
2038 $newuser->fetch($event->userownerid);
2039 $cacheusers[$event->userownerid] = $newuser;
2040 }
2041 //var_dump($cacheusers[$event->userownerid]->color);
2042
2043 // We decide to choose color of owner of event (event->userownerid is user id of owner, event->userassigned contains all users assigned to event)
2044 if (!empty($cacheusers[$event->userownerid]->color)) {
2045 $color = $cacheusers[$event->userownerid]->color;
2046 }
2047
2048 /* May be we need this: if (getDolGlobalString('AGENDA_USE_COLOR_PER_EVENT_TYPE')) {
2049 $color = $event->type_color;
2050 }*/
2051 } elseif ($event->type_code == 'ICALEVENT') { // Event come from external ical file
2052 $numical++;
2053 if (!empty($event->icalname)) {
2054 if (!isset($numicals[dol_string_nospecial($event->icalname)])) {
2055 $numicals[dol_string_nospecial($event->icalname)] = 0;
2056 }
2057 $numicals[dol_string_nospecial($event->icalname)]++;
2058 }
2059
2060 $color = ($event->icalcolor ? $event->icalcolor : -1);
2061 $cssclass = (!empty($event->icalname) ? 'family_ext'.md5($event->icalname) : 'family_other');
2062 } elseif ($event->type_code == 'BIRTHDAY') {
2063 $numbirthday++;
2064 $colorindex = 2;
2065 $cssclass = 'family_birthday ';
2066 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
2067 } elseif ($event->type == 'bookcal_calendar') {
2068 $numbirthday++;
2069 $colorindex = 3;
2070 $cssclass = 'family_bookcal_calendar_'.(!empty($bookcalcalendarsarray["availabilitieslink"]) ? $bookcalcalendarsarray["availabilitieslink"][$event->fk_bookcal_calendar] : "");
2071 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
2072 } else {
2073 $numother++;
2074 $color = ($event->icalcolor ? $event->icalcolor : -1);
2075 $cssclass = (!empty($event->icalname) ? 'family_ext'.md5($event->icalname) : 'family_other');
2076
2077 if (empty($cacheusers[$event->userownerid])) {
2078 $newuser = new User($db);
2079 $newuser->fetch($event->userownerid);
2080 $cacheusers[$event->userownerid] = $newuser;
2081 }
2082 //var_dump($cacheusers[$event->userownerid]->color);
2083
2084 // We decide to choose color of owner of event (event->userownerid is user id of owner, event->userassigned contains all users assigned to event)
2085 if (!empty($cacheusers[$event->userownerid]->color)) {
2086 $color = $cacheusers[$event->userownerid]->color;
2087 }
2088 }
2089
2090 if ($color < 0) { // Color was not set on user card. Set color according to color index.
2091 // Define color index if not yet defined
2092 $idusertouse = ($event->userownerid ? $event->userownerid : 0);
2093 if (isset($colorindexused[$idusertouse])) {
2094 $colorindex = $colorindexused[$idusertouse]; // Color already assigned to this user
2095 } else {
2096 $colorindex = $nextindextouse;
2097 $colorindexused[$idusertouse] = $colorindex;
2098 if (!empty($theme_datacolor[$nextindextouse + 1])) {
2099 $nextindextouse++; // Prepare to use next color
2100 }
2101 }
2102 if (isset($theme_datacolor[$colorindex])) {
2103 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
2104 } elseif (getDolGlobalString('THEME_ELDY_BACKBODY')) {
2105 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2106 $color = colorArrayToHex(colorStringToArray(getDolGlobalString('THEME_ELDY_BACKBODY'), array()), '');
2107 } else {
2108 $color = "ffffff";
2109 }
2110 }
2111 $cssclass = $cssclass.' eventday_'.$ymd;
2112
2113 // Defined style to disable drag and drop feature
2114 if ($event->type_code == 'AC_OTH_AUTO') {
2115 $cssclass .= " unmovable";
2116 } elseif ($event->type_code == 'HOLIDAY') {
2117 $cssclass .= " unmovable";
2118 } elseif ($event->type_code == 'BIRTHDAY') {
2119 $cssclass .= " unmovable";
2120 } elseif ($event->type_code == 'ICALEVENT') {
2121 $cssclass .= " unmovable";
2122 } 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)) {
2123 // If the event is on several days
2124 $tmpyearend = dol_print_date($event->date_start_in_calendar, '%Y', 'tzuserrel');
2125 $tmpmonthend = dol_print_date($event->date_start_in_calendar, '%m', 'tzuserrel');
2126 $tmpdayend = dol_print_date($event->date_start_in_calendar, '%d', 'tzuserrel');
2127 //var_dump($tmpyearend.' '.$tmpmonthend.' '.$tmpdayend);
2128 if ($tmpyearend != $annee || $tmpmonthend != $mois || $tmpdayend != $jour) {
2129 $cssclass .= " unmovable unmovable-mustusefirstdaytodrag";
2130 } else {
2131 $cssclass .= ' movable cursormove';
2132 }
2133 } else {
2134 if ($user->hasRight('agenda', 'allactions', 'create') ||
2135 (($event->authorid == $user->id || $event->userownerid == $user->id) && $user->hasRight('agenda', 'myactions', 'create'))) {
2136 $cssclass .= " movable cursormove";
2137 } else {
2138 $cssclass .= " unmovable";
2139 }
2140 }
2141
2142 $h = '';
2143 $nowrapontd = 1;
2144 if ($mode == 'show_day') {
2145 $h = 'height: 100%; ';
2146 $nowrapontd = 0;
2147 }
2148 if ($mode == 'show_week') {
2149 $h = 'height: 100%; ';
2150 $nowrapontd = 0;
2151 }
2152
2153 // Show event box
2154 print "\n";
2155 print '<!-- start event '.$i.' -->'."\n";
2156
2157 $morecss = '';
2158 if ($maxprint && $ireallyshown >= $maxprint) {
2159 $morecss = 'showifmore';
2160 }
2161 if ($event->type == 'birthdate' && !GETPOST('check_birthday')) {
2162 $morecss = 'hidden';
2163 }
2164 if ($event->type == 'holiday' && !GETPOST('check_holiday')) {
2165 $morecss = 'hidden';
2166 }
2167 /* I comment this because it hides event recorded from bookcal online page
2168 if ($event->type == 'bookcal_calendar' && !GETPOST('check_bookcal_calendar_'.$bookcalcalendarsarray["availabilitieslink"][$event->fk_bookcal_calendar])) {
2169 $morecss = 'hidden';
2170 } */
2171 if ($morecss != 'hidden') {
2172 $itoshow++;
2173 }
2174 if ($morecss != 'showifmore' && $morecss != 'hidden') {
2175 $ireallyshown++;
2176 }
2177
2178 //var_dump($event->type.' - '.$morecss.' - '.$cssclass.' - '.$i.' - '.$ireallyshown.' - '.$itoshow);
2179 if (isModEnabled("bookcal") && $event->type == 'bookcal_calendar') {
2180 print '<div id="event_'.$ymd.'_'.$i.'" class="event family_'.$event->type.'_'.$bookcalcalendarsarray["availabilitieslink"][$event->fk_bookcal_calendar].' '.$cssclass.($morecss ? ' '.$morecss : '').'"';
2181 } else {
2182 print '<div id="event_'.$ymd.'_'.$i.'" class="event family_'.$event->type.' '.$cssclass.($morecss ? ' '.$morecss : '').'"';
2183 }
2184 //print ' style="height: 100px;';
2185 //print ' position: absolute; top: 40px; width: 50%;';
2186 //print '"';
2187 print '>';
2188
2189 //var_dump($event->userassigned);
2190 //var_dump($event->transparency);
2191 print '<table class="centpercent cal_event';
2192 print(empty($event->transparency) ? ' cal_event_notbusy' : ' cal_event_busy');
2193 //if (empty($event->transparency) && empty($conf->global->AGENDA_NO_TRANSPARENT_ON_NOT_BUSY)) print ' opacitymedium'; // Not busy
2194 print '" style="'.$h;
2195 $colortouse = $color;
2196 // If colortouse is similar than background, we force to change it.
2197 if (empty($event->transparency) && !getDolGlobalString('AGENDA_NO_TRANSPARENT_ON_NOT_BUSY')) {
2198 print 'background: #f0f0f0;';
2199 print 'border-left: 5px solid #'.$colortouse.';';
2200 } else {
2201 print 'background: #f0f0f0;';
2202 print 'border-left: 5px solid #'.dol_color_minus($colortouse, -3).';';
2203 //print 'background: -webkit-gradient(linear, left top, left bottom, from(#'.dol_color_minus($colortouse, -3).'), to(#'.dol_color_minus($colortouse, -1).'));';
2204 }
2205 //print 'background: #'.$colortouse.';';
2206 //print 'background: -webkit-gradient(linear, left top, left bottom, from(#'.dol_color_minus($color, -3).'), to(#'.dol_color_minus($color, -1).'));';
2207 //if (!empty($event->transparency)) print 'background: #'.$color.'; background: -webkit-gradient(linear, left top, left bottom, from(#'.$color.'), to(#'.dol_color_minus($color,1).'));';
2208 //else print 'background-color: transparent !important; background: none; border: 1px solid #bbb;';
2209 //print ' -moz-border-radius:4px;"';
2210 //print 'border: 1px solid #ccc" width="100%"';
2211 print '">';
2212
2213 // First the tr of the event (only one tr for event is used, but several td)
2214 print '<tr>';
2215 print '<td class="tdoverflow nobottom small centpercent '.($nowrapontd ? 'nowrap ' : '').'cal_event'.($event->type_code == 'BIRTHDAY' ? ' cal_event_birthday' : '').'">';
2216 print '<!-- left section of event -->';
2217
2218 $daterange = '';
2219
2220 $parameters = array();
2221 $reshook = $hookmanager->executeHooks('eventOptions', $parameters, $event, $action); // Note that $action and $object may have been modified by some hooks
2222 if ($reshook < 0) {
2223 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2224 } else {
2225 '@phan-var-force ActionComm $event';
2226 if (empty($reshook)) {
2227 // Other calendar
2228 /*
2229 if (empty($event->fulldayevent)) {
2230 //print $event->getNomUrl(2).' ';
2231 }
2232 */
2233
2234 if ($event->type_code == 'BIRTHDAY') {
2235 // It's birthday calendar
2236 $picb = img_picto('', 'birthday-cake', 'class="pictofixedwidth"');
2237 print $picb.$langs->trans("Birthday").'<br>';
2238 }
2239
2240 // Date
2241 if ($event->type_code != 'HOLIDAY' && $event->type_code != 'BIRTHDAY') {
2242 if (empty($event->fulldayevent)) {
2243 // Show hours (start ... end)
2244 $tmpyearstart = dol_print_date($event->date_start_in_calendar, '%Y', 'tzuserrel');
2245 $tmpmonthstart = dol_print_date($event->date_start_in_calendar, '%m', 'tzuserrel');
2246 $tmpdaystart = dol_print_date($event->date_start_in_calendar, '%d', 'tzuserrel');
2247 $tmpyearend = dol_print_date($event->date_end_in_calendar, '%Y', 'tzuserrel');
2248 $tmpmonthend = dol_print_date($event->date_end_in_calendar, '%m', 'tzuserrel');
2249 $tmpdayend = dol_print_date($event->date_end_in_calendar, '%d', 'tzuserrel');
2250
2251 // Hour start
2252 if ($tmpyearstart == $annee && $tmpmonthstart == $mois && $tmpdaystart == $jour) {
2253 $daterange .= dol_print_date($event->date_start_in_calendar, 'hour', 'tzuserrel');
2254 if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) {
2255 if ($tmpyearstart == $tmpyearend && $tmpmonthstart == $tmpmonthend && $tmpdaystart == $tmpdayend) {
2256 $daterange .= '-';
2257 }
2258 //else
2259 //print '...';
2260 }
2261 }
2262 if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) {
2263 if ($tmpyearstart != $tmpyearend || $tmpmonthstart != $tmpmonthend || $tmpdaystart != $tmpdayend) {
2264 $daterange .= '...';
2265 }
2266 }
2267 // Hour end
2268 if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) {
2269 if ($tmpyearend == $annee && $tmpmonthend == $mois && $tmpdayend == $jour) {
2270 $daterange .= dol_print_date($event->date_end_in_calendar, 'hour', 'tzuserrel');
2271 }
2272 }
2273 } else {
2274 if ($showinfo) {
2275 print $langs->trans("EventOnFullDay")."<br>\n";
2276 }
2277 }
2278 }
2279
2280 // Show title
2281 $titletoshow = $daterange;
2282 $titletoshow .= ($titletoshow ? ' ' : '').dol_escape_htmltag($event->label);
2283
2284 if ($event->type_code != 'ICALEVENT' && $event->type_code != 'BIRTHDAY') {
2285 $savlabel = $event->label;
2286 $event->label = $titletoshow;
2287 // Note: List of users are inside $event->userassigned. Link may be clickable depending on permissions of user.
2288 $titletoshow = (($event->type_picto || $event->type_code) ? $event->getTypePicto() : '');
2289 $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 '...'
2290 $event->label = $savlabel;
2291 }
2292
2293 // Loop on each assigned user
2294 $listofusertoshow = '';
2295 $posuserassigned = 0;
2296 foreach ($event->userassigned as $tmpid => $tmpdata) {
2297 if (!$posuserassigned && $titletoshow) {
2298 $listofusertoshow .= '<br>';
2299 }
2300 $posuserassigned++;
2301 if (empty($cacheusers[$tmpid])) {
2302 $newuser = new User($db);
2303 $newuser->fetch($tmpid);
2304 $cacheusers[$tmpid] = $newuser;
2305 }
2306
2307 $listofusertoshow .= $cacheusers[$tmpid]->getNomUrl(-3, '', 0, 0, 0, 0, '', 'valignmiddle inline-block');
2308 }
2309
2310 if ($event->type_code != 'BIRTHDAY' && $event->type_code != 'HOLIDAY') {
2311 print $titletoshow;
2312 print $listofusertoshow.' &nbsp;';
2313 }
2314
2315 if ($event->type_code == 'ICALEVENT') {
2316 print '<br>('.dol_trunc($event->icalname, $maxnbofchar).')';
2317 }
2318
2319 $thirdparty_id = ($event->socid > 0 ? $event->socid : ((is_object($event->societe) && $event->societe->id > 0) ? $event->societe->id : 0));
2320 $contact_id = ($event->contact_id > 0 ? $event->contact_id : ((is_object($event->contact) && $event->contact->id > 0) ? $event->contact->id : 0));
2321
2322 // If action related to company / contact
2323 $linerelatedto = '';
2324 if ($thirdparty_id > 0) {
2325 if (!isset($cachethirdparties[$thirdparty_id]) || !is_object($cachethirdparties[$thirdparty_id])) {
2326 $thirdparty = new Societe($db);
2327 $thirdparty->fetch($thirdparty_id);
2328 $cachethirdparties[$thirdparty_id] = $thirdparty;
2329 } else {
2330 $thirdparty = $cachethirdparties[$thirdparty_id];
2331 }
2332 if (!empty($thirdparty->id)) {
2333 $linerelatedto .= $thirdparty->getNomUrl(1, '', 0, 0, -1, 0, '', 'valignmiddle inline'); // using inline-block make the content completely replace with ... when too large
2334 }
2335 }
2336 if (!empty($contact_id) && $contact_id > 0) {
2337 if (empty($cachecontacts[$contact_id]) || !is_object($cachecontacts[$contact_id])) {
2338 $contact = new Contact($db);
2339 $contact->fetch($contact_id);
2340 $cachecontacts[$contact_id] = $contact;
2341 } else {
2342 $contact = $cachecontacts[$contact_id];
2343 }
2344 if ($linerelatedto) {
2345 $linerelatedto .= '&nbsp;';
2346 }
2347 if (!empty($contact->id)) {
2348 $linerelatedto .= $contact->getNomUrl(1, '', 0, '', -1, 0, 'valignmiddle inline'); // using inline-block make the content completely replace with ... when too large
2349 }
2350 }
2351 if (!empty($event->fk_element) && $event->fk_element > 0 && !empty($event->elementtype) && getDolGlobalString('AGENDA_SHOW_LINKED_OBJECT')) {
2352 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2353 if ($linerelatedto) {
2354 $linerelatedto .= '<br>';
2355 }
2356 $linerelatedto .= dolGetElementUrl($event->fk_element, $event->elementtype, 1);
2357 }
2358 if ($linerelatedto) {
2359 print ' '.$linerelatedto;
2360 }
2361 } elseif (!empty($reshook)) {
2362 print $hookmanager->resPrint;
2363 }
2364 }
2365
2366 if ($event->type_code == 'HOLIDAY') {
2367 // It's holiday calendar
2368 $tmpholiday->fetch($event->id);
2369
2370 print $tmpholiday->getNomUrl(1, -1, 0, 'valignmiddle inline-block');
2371
2372 $tmpid = $tmpholiday->fk_user;
2373 if (empty($cacheusers[$tmpid])) {
2374 $newuser = new User($db);
2375 $newuser->fetch($tmpid);
2376 $cacheusers[$tmpid] = $newuser;
2377 }
2378
2379 $listofusertoshow = '';
2380 $listofusertoshow .= "\n".'<br>'.$cacheusers[$tmpid]->getNomUrl(-1, '', 0, 0, 0, 0, '', 'paddingright valignmiddle inline-block')."\n";
2381 print $listofusertoshow;
2382 }
2383
2384 // Show location
2385 if ($showinfo) {
2386 if ($event->location) {
2387 print '<br>';
2388 print $langs->trans("Location").': '.$event->location;
2389 }
2390 }
2391
2392 print '</td>';
2393
2394 // Status - Percent
2395 $withstatus = 0;
2396 if ($event->type_code != 'HOLIDAY' && $event->type_code != 'BIRTHDAY' && $event->type_code != 'ICALEVENT') {
2397 $withstatus = 1;
2398 if ($event->percentage >= 0) {
2399 $withstatus = 2;
2400 }
2401 }
2402 print '<td class="nobottom right nowrap cal_event_right'.($withstatus >= 2 ? ' cal_event_right_status' : '').'">';
2403 if ($withstatus) {
2404 print $event->getLibStatut(3, 1);
2405 } else {
2406 print '&nbsp;';
2407 }
2408 print '</td></tr></table>';
2409 print '</div><!-- end event '.$i.' -->'."\n";
2410
2411 $i++;
2412 } else {
2413 print '<a href="'.DOL_URL_ROOT.'/comm/action/index.php?mode='.$mode.'&maxprint=0&month='.((int) $monthshown).'&year='.((int) $year);
2414 print($status ? '&status='.$status : '').($filter ? '&filter='.urlencode($filter) : '');
2415 print($filtert ? '&search_filtert='.urlencode((string) $filtert) : '');
2416 print($usergroup ? '&search_usergroup='.urlencode((string) $usergroup) : '');
2417 print($actioncode != '' ? '&search_actioncode='.urlencode($actioncode) : '');
2418 print '">'.img_picto("all", "1downarrow_selected.png").' ...';
2419 print ' +'.(count($eventarray[$daykey]) - $maxprint);
2420 print '</a>';
2421 break;
2422 //$ok=false; // To avoid to show twice the link
2423 }
2424 }
2425
2426 break;
2427 }
2428 }
2429 if (!$i) { // No events
2430 print '&nbsp;';
2431 }
2432
2433 if (getDolGlobalString('MAIN_JS_SWITCH_AGENDA') && $itoshow > $ireallyshown && $maxprint) {
2434 print '<div class="center cursorpointer" id="more_'.$ymd.'">'.img_picto("All", "angle-double-down", 'class="warning"').' +'.($itoshow - $ireallyshown).'</div>';
2435 //print ' +'.(count($eventarray[$daykey])-$maxprint);
2436
2437 print '<script type="text/javascript">'."\n";
2438 print 'jQuery(document).ready(function () {'."\n";
2439 print ' var open=0;'."\n";
2440 print ' jQuery("#more_'.$ymd.'").click(function() { console.log("Click on showmore for '.$ymd.'"); reinit_day_'.$ymd.'(); event.stopImmediatePropagation(); });'."\n";
2441 print ' function reinit_day_'.$ymd.'() {'."\n";
2442 print ' jQuery(".eventday_'.$ymd.'.showifmore").toggle();'."\n";
2443 print ' open = open + 1; if (open > 1) { open = 0; }'."\n";
2444 print ' if (open) { ';
2445 print ' jQuery("#more_'.$ymd.'").html(\''.img_picto("All", "angle-double-up", 'class="warning"').'\');'."\n";
2446 print ' } else { ';
2447 print ' jQuery("#more_'.$ymd.'").html(\''.img_picto("All", "angle-double-down", 'class="warning"').' +'.($itoshow - $ireallyshown).'\');'."\n";
2448 print ' }'."\n";
2449 print ' }'."\n";
2450 print '});'."\n";
2451 print '</script>'."\n";
2452 }
2453
2454 print '</div></div>'; // td tr
2455
2456 print '</div>'; // table
2457 print "\n";
2458}
2459
2460
2469function dol_color_minus($color, $minus, $minusunit = 16)
2470{
2471 $newcolor = $color;
2472 if ($minusunit == 16 && is_array($newcolor)) {
2473 $newcolor[0] = dechex(max(min(hexdec($newcolor[0]) - $minus, 15), 0));
2474 $newcolor[2] = dechex(max(min(hexdec($newcolor[2]) - $minus, 15), 0));
2475 $newcolor[4] = dechex(max(min(hexdec($newcolor[4]) - $minus, 15), 0));
2476 } else {
2477 // Not yet implemented
2478 }
2479 return $newcolor;
2480}
2481
2489function sort_events_by_date($a, $b)
2490{
2491 // Sort holidays at first
2492 if ($a->type_code === 'HOLIDAY') {
2493 return -1;
2494 }
2495 if ($b->type_code === 'HOLIDAY') {
2496 return 1;
2497 }
2498
2499 // datep => Event start time
2500 // datef => Event end time
2501
2502 // Events have different start time
2503 if ($a->datep !== $b->datep) {
2504 return $a->datep - $b->datep;
2505 }
2506
2507 // Events have same start time and no end time
2508 if ((!is_numeric($b->datef)) || (!is_numeric($a->datef))) {
2509 return sort_events_by_percentage($a, $b);
2510 }
2511
2512 // Events have the same start time and same end time
2513 if ($b->datef === $a->datef) {
2514 return sort_events_by_percentage($a, $b);
2515 }
2516
2517 // Events have the same start time, but have different end time -> longest event first
2518 return $b->datef - $a->datef;
2519}
2520
2528function sort_events_by_percentage($a, $b)
2529{
2530 // Sort events with no percentage before each other
2531 // (useful to sort holidays, sick days or similar on the top)
2532
2533 if ($a->percentage < 0) {
2534 return -1;
2535 }
2536
2537 if ($b->percentage < 0) {
2538 return 1;
2539 }
2540
2541 return $b->percentage - $a->percentage;
2542}
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:1597
$cacheusers
Definition index.php:1595
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.