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