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