dolibarr 25.0.0-alpha
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 = getDolGlobalInt('AGENDA_MAX_ON_SAME_PAGE', 5000); // 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 agenda_get_birthday_events($db, $langs, $user, $mode, $month, $day, $year, $eventarray, $nbevents);
1052}
1053
1054// LEAVE-HOLIDAY CALENDAR
1055if ($user->hasRight("holiday", "read")) {
1056 $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";
1057 $sql .= " FROM ".MAIN_DB_PREFIX."holiday as x, ".MAIN_DB_PREFIX."user as u";
1058 $sql .= " WHERE u.rowid = x.fk_user";
1059 $sql .= " AND u.statut = '1'"; // Show only active users (0 = inactive user, 1 = active user)
1060 $sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
1061 // Restrict on current month (we get more, but we will filter later)
1062 $sql .= " AND x.date_debut < '".$db->idate(dol_get_last_day($year, $month))."'";
1063 $sql .= " AND x.date_fin >= '".$db->idate(dol_get_first_day($year, $month))."'";
1064 if (!$user->hasRight('holiday', 'readall')) {
1065 $sql .= " AND x.fk_user IN(".$db->sanitize(implode(", ", $user->getAllChildIds(1))).") ";
1066 }
1067
1068 $resql = $db->query($sql);
1069 if ($resql) {
1070 $num = $db->num_rows($resql);
1071 $i = 0;
1072
1073 while ($i < $num) {
1074 $obj = $db->fetch_object($resql);
1075
1076 $event = new ActionComm($db);
1077
1078 // Need the id of the leave object for link to it
1079 $event->id = $obj->rowid;
1080 $event->ref = (string) $event->id;
1081
1082 $event->type_code = 'HOLIDAY';
1083 $event->type_label = '';
1084 $event->type_color = '';
1085 $event->type = 'holiday';
1086 $event->type_picto = 'holiday';
1087
1088 // date_debut and date_fin are dates without time, so they must be read and rendered in GMT to
1089 // stay independent from the server and user timezones (otherwise the calendar day box is shifted).
1090 $event->datep = (int) $db->jdate($obj->date_start, 'gmt') + ((empty($obj->halfday) || $obj->halfday == 1) ? 0 : 12) * 60 * 60;
1091 $event->datef = (int) $db->jdate($obj->date_end, 'gmt') + ((empty($obj->halfday) || $obj->halfday == -1) ? 24 : 12) * 60 * 60 - 1;
1092 $event->date_start_in_calendar = $event->datep;
1093 $event->date_end_in_calendar = $event->datef;
1094
1095 $event->transparency = 1;
1096
1097 $event->userownerid = $obj->uid; // user id of owner
1098 $event->userassigned = array($obj->uid => array('id' => $obj->uid, 'transparency' => 1));
1099
1100 if ($obj->status == 3) {
1101 // Show no symbol for leave with state "leave approved"
1102 $event->percentage = -1;
1103 } elseif ($obj->status == 2) {
1104 // Show TO-DO symbol for leave with state "leave wait for approval"
1105 $event->percentage = 0;
1106 }
1107
1108
1109 $daycursor = $event->date_start_in_calendar;
1110 $annee = (int) dol_print_date($daycursor, '%Y', 'gmt');
1111 $mois = (int) dol_print_date($daycursor, '%m', 'gmt');
1112 $jour = (int) dol_print_date($daycursor, '%d', 'gmt');
1113
1114 $daycursorend = $event->date_end_in_calendar;
1115 $anneeend = (int) dol_print_date($daycursorend, '%Y', 'gmt');
1116 $moisend = (int) dol_print_date($daycursorend, '%m', 'gmt');
1117 $jourend = (int) dol_print_date($daycursorend, '%d', 'gmt');
1118
1119 // daykey must be date that represent day box in calendar so must be a user time
1120 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1121 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1122 $ifornbofdays = 0;
1123 do {
1124 $ifornbofdays++;
1125
1126 $firstdayofholiday = ($ifornbofdays == 1);
1127 $lastdayofholiday = ($daykeygmt == dol_get_first_hour($event->date_end_in_calendar, 'gmt'));
1128
1129 //var_dump(dol_print_date($daykeygmt, 'dayhour', 'gmt'));
1130
1131 if ((in_array($obj->halfday, array(1, 2)) == 1 && $lastdayofholiday) || (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday)) {
1132 // We create a copy of event because we want tochange the label
1133 $newevent = dol_clone($event, 1);
1134 if (in_array($obj->halfday, array(1, 2)) && $lastdayofholiday) {
1135 $newevent->label .= ' ('.$langs->trans("Morning").')';
1136 } elseif (in_array($obj->halfday, array(-1, 2)) && $firstdayofholiday) {
1137 $newevent->label .= ' ('.$langs->trans("Afternoon").')';
1138 }
1139 $eventarray[$daykey][] = $newevent; // We need to use ->gtTypePicto, getXXXon object, so clone must be PHP clone.
1140 } else {
1141 $eventarray[$daykey][] = $event; // We can use the event unchanged
1142 }
1143
1144 $daykey += 60 * 60 * 24;
1145 $daykeygmt += 60 * 60 * 24;
1146 } while ($daykey <= $event->date_end_in_calendar);
1147
1148 $i++;
1149 }
1150 }
1151}
1152
1153// EXTERNAL CALENDAR
1154// Complete $eventarray with external import Ical
1155if (count($listofextcals)) {
1156 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/ical.class.php';
1157
1158 foreach ($listofextcals as $key => $extcal) {
1159 $url = $extcal['src']; // Example: https://www.google.com/calendar/ical/eldy10%40gmail.com/private-cde92aa7d7e0ef6110010a821a2aaeb/basic.ics
1160 $namecal = $extcal['name'];
1161 $offsettz = $extcal['offsettz'];
1162 $colorcal = $extcal['color'];
1163 $buggedfile = $extcal['buggedfile'];
1164
1165 $pathforcachefile = dol_sanitizePathName($conf->user->dir_temp).'/'.dol_sanitizeFileName('extcal_'.$namecal.'_user'.$user->id).'.cache';
1166 //var_dump($pathforcachefile);exit;
1167
1168 $ical = new ICal();
1169 $ical->parse($url, $pathforcachefile, $DELAYFORCACHE);
1170 if ($ical->error) {
1171 // Save error message for extcal
1172 $listofextcals[$key]['error'] = $ical->error;
1173 $s .= '<br><div class="warning">'.dol_escape_htmltag($listofextcals[$key]['name']).': '.$url.'<br>Error message: '.dol_escape_htmltag($ical->error).'</div>';
1174 }
1175
1176 // After this $ical->cal['VEVENT'] contains array of events, $ical->cal['DAYLIGHT'] contains daylight info, $ical->cal['STANDARD'] contains non daylight info, ...
1177 //var_dump($ical->cal); exit;
1178 $icalevents = array();
1179 if (is_array($ical->get_event_list())) {
1180 $icalevents = array_merge($icalevents, $ical->get_event_list()); // Add $ical->cal['VEVENT']
1181 }
1182 if (is_array($ical->get_freebusy_list())) {
1183 $icalevents = array_merge($icalevents, $ical->get_freebusy_list()); // Add $ical->cal['VFREEBUSY']
1184 }
1185
1186 if (count($icalevents) > 0) {
1187 // Duplicate all repeatable events into new entries
1188 $moreicalevents = array();
1189 foreach ($icalevents as $icalevent) {
1190 if (isset($icalevent['RRULE']) && is_array($icalevent['RRULE'])) { //repeatable event
1191 //if ($event->date_start_in_calendar < $firstdaytoshow) $event->date_start_in_calendar=$firstdaytoshow;
1192 //if ($event->date_end_in_calendar > $lastdaytoshow) $event->date_end_in_calendar=($lastdaytoshow-1);
1193 if ($icalevent['DTSTART;VALUE=DATE']) { //fullday event
1194 $datecurstart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
1195 $datecurend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
1196 } elseif (is_array($icalevent['DTSTART']) && !empty($icalevent['DTSTART']['unixtime'])) {
1197 $datecurstart = $icalevent['DTSTART']['unixtime']; // can't be empty
1198 $datecurend = $icalevent['DTEND']['unixtime'];
1199 if (!empty($ical->cal['DAYLIGHT']['DTSTART']) /* && $datecurstart */) {
1200 //var_dump($ical->cal);
1201 $tmpcurstart = $datecurstart;
1202 $tmpcurend = $datecurend;
1203 $tmpdaylightstart = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['DAYLIGHT']['DTSTART'];
1204 $tmpdaylightend = dol_mktime(0, 0, 0, 1, 1, 1970, 1) + (int) $ical->cal['STANDARD']['DTSTART'];
1205 //var_dump($tmpcurstart);var_dump($tmpcurend); var_dump($ical->cal['DAYLIGHT']['DTSTART']);var_dump($ical->cal['STANDARD']['DTSTART']);
1206 // Edit datecurstart and datecurend
1207 if ($tmpcurstart >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
1208 $datecurstart -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
1209 } else {
1210 $datecurstart -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
1211 }
1212 if ($tmpcurend >= $tmpdaylightstart && $tmpcurstart < $tmpdaylightend) {
1213 $datecurend -= ((int) $ical->cal['DAYLIGHT']['TZOFFSETTO']) * 36;
1214 } else {
1215 $datecurend -= ((int) $ical->cal['STANDARD']['TZOFFSETTO']) * 36;
1216 }
1217 }
1218 // datecurstart and datecurend are now GMT date
1219 //var_dump($datecurstart); var_dump($datecurend); exit;
1220 } else {
1221 // Not a recognized record
1222 dol_syslog("Found a not recognized repeatable record with unknown date start", LOG_ERR);
1223 continue;
1224 }
1225 //print 'xx'.$datecurstart;exit;
1226
1227 $interval = (empty($icalevent['RRULE']['INTERVAL']) ? 1 : $icalevent['RRULE']['INTERVAL']);
1228 $until = empty($icalevent['RRULE']['UNTIL']) ? 0 : dol_stringtotime($icalevent['RRULE']['UNTIL'], 1);
1229 $maxrepeat = empty($icalevent['RRULE']['COUNT']) ? 0 : $icalevent['RRULE']['COUNT'];
1230 if ($until && ($until + ($datecurend - $datecurstart)) < $firstdaytoshow) {
1231 continue; // We discard repeatable event that end before start date to show
1232 }
1233 if ($datecurstart >= $lastdaytoshow) {
1234 continue; // We discard repeatable event that start after end date to show
1235 }
1236
1237 $numofevent = 0;
1238 while (($datecurstart < $lastdaytoshow) && (empty($maxrepeat) || ($numofevent < $maxrepeat))) {
1239 if ($datecurend >= $firstdaytoshow) { // We add event
1240 $newevent = $icalevent;
1241 unset($newevent['RRULE']);
1242 if ($icalevent['DTSTART;VALUE=DATE']) {
1243 $newevent['DTSTART;VALUE=DATE'] = dol_print_date($datecurstart, '%Y%m%d');
1244 $newevent['DTEND;VALUE=DATE'] = dol_print_date($datecurend + 1, '%Y%m%d');
1245 } else {
1246 $newevent['DTSTART'] = $datecurstart;
1247 $newevent['DTEND'] = $datecurend;
1248 }
1249 $moreicalevents[] = $newevent;
1250 }
1251 // Jump on next occurrence
1252 $numofevent++;
1253 $savdatecurstart = $datecurstart;
1254 if ($icalevent['RRULE']['FREQ'] == 'DAILY') {
1255 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'd');
1256 $datecurend = dol_time_plus_duree($datecurend, $interval, 'd');
1257 }
1258 if ($icalevent['RRULE']['FREQ'] == 'WEEKLY') {
1259 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'w');
1260 $datecurend = dol_time_plus_duree($datecurend, $interval, 'w');
1261 } elseif ($icalevent['RRULE']['FREQ'] == 'MONTHLY') {
1262 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'm');
1263 $datecurend = dol_time_plus_duree($datecurend, $interval, 'm');
1264 } elseif ($icalevent['RRULE']['FREQ'] == 'YEARLY') {
1265 $datecurstart = dol_time_plus_duree($datecurstart, $interval, 'y');
1266 $datecurend = dol_time_plus_duree($datecurend, $interval, 'y');
1267 }
1268 // Test to avoid infinite loop ($datecurstart must increase)
1269 if ($savdatecurstart >= $datecurstart) {
1270 dol_syslog("Found a rule freq ".$icalevent['RRULE']['FREQ']." not managed by dolibarr code. Assume 1 week frequency.", LOG_ERR);
1271 $datecurstart += 3600 * 24 * 7;
1272 $datecurend += 3600 * 24 * 7;
1273 }
1274 }
1275 }
1276 }
1277 $icalevents = array_merge($icalevents, $moreicalevents);
1278
1279 // Loop on each entry into cal file to know if entry is qualified and add an ActionComm into $eventarray
1280 foreach ($icalevents as $icalevent) {
1281 //var_dump($icalevent);
1282
1283 //print $icalevent['SUMMARY'].'->';
1284 //var_dump($icalevent);exit;
1285 if (!empty($icalevent['RRULE'])) {
1286 continue; // We found a repeatable event. It was already split into unitary events, so we discard general rule.
1287 }
1288
1289 // Create a new object action
1290 $event = new ActionComm($db);
1291 $addevent = false;
1292 $datestart = null;
1293 $dateend = null;
1294 if (isset($icalevent['DTSTART;VALUE=DATE'])) { // fullday event
1295 // For full day events, date are also GMT but they won't but converted using tz during output
1296 $datestart = dol_stringtotime($icalevent['DTSTART;VALUE=DATE'], 1);
1297 if (empty($icalevent['DTEND;VALUE=DATE'])) {
1298 $dateend = $datestart + 86400 - 1;
1299 } else {
1300 $dateend = dol_stringtotime($icalevent['DTEND;VALUE=DATE'], 1) - 1; // We remove one second to get last second of day
1301 }
1302 //print 'x'.$datestart.'-'.$dateend;exit;
1303 //print dol_print_date($dateend,'dayhour','gmt');
1304 $event->fulldayevent = 1;
1305 $addevent = true;
1306 } elseif (!is_array($icalevent['DTSTART'])) { // not fullday event (DTSTART is not array. It is a value like '19700101T000000Z' for 00:00 in greenwitch)
1307 $datestart = $icalevent['DTSTART'];
1308 $dateend = empty($icalevent['DTEND']) ? $datestart : $icalevent['DTEND'];
1309
1310 $datestart += +($offsettz * 3600);
1311 $dateend += +($offsettz * 3600);
1312
1313 $addevent = true;
1314 //var_dump($offsettz);
1315 //var_dump(dol_print_date($datestart, 'dayhour', 'gmt'));
1316 } elseif (isset($icalevent['DTSTART']['unixtime'])) { // File contains a local timezone + a TZ (for example when using bluemind)
1317 $datestart = $icalevent['DTSTART']['unixtime'];
1318 $dateend = $icalevent['DTEND']['unixtime'];
1319
1320 $datestart += +($offsettz * 3600);
1321 $dateend += +($offsettz * 3600);
1322
1323 // $buggedfile is set to uselocalandtznodaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtznodaylight'
1324 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
1325 // TODO
1326 }
1327 // $buggedfile is set to uselocalandtzdaylight if conf->global->AGENDA_EXT_BUGGEDFILEx = 'uselocalandtzdaylight' (for example with bluemind)
1328 if ($buggedfile === 'uselocalandtzdaylight') { // unixtime is a local date that does take daylight into account, TZID is +2 for example for 'Europe/Paris' in summer
1329 $localtzs = new DateTimeZone((string) preg_replace('/"/', '', $icalevent['DTSTART']['TZID']));
1330 $localtze = new DateTimeZone((string) preg_replace('/"/', '', $icalevent['DTEND']['TZID']));
1331 $localdts = new DateTime(dol_print_date($datestart, 'dayrfc', 'gmt'), $localtzs);
1332 $localdte = new DateTime(dol_print_date($dateend, 'dayrfc', 'gmt'), $localtze);
1333 $tmps = -1 * $localtzs->getOffset($localdts);
1334 $tmpe = -1 * $localtze->getOffset($localdte);
1335 $datestart += $tmps;
1336 $dateend += $tmpe;
1337 //var_dump($datestart);
1338 }
1339 $addevent = true;
1340 }
1341
1342 if ($addevent && $datestart !== null && $dateend !== null) {
1343 $event->id = $icalevent['UID'];
1344 $event->ref = (string) $event->id;
1345 $userstatic = new User($db);
1346 $userId = $userstatic->findUserIdByEmail($namecal);
1347 if (!empty($userId) && $userId > 0) {
1348 $event->userassigned[$userId] = [
1349 'id' => $userId,
1350 'transparency' => 1,
1351 ];
1352 $event->percentage = -1;
1353 }
1354
1355 $event->type_code = "ICALEVENT";
1356 $event->type_label = $namecal;
1357 $event->type_color = $colorcal;
1358 $event->type = 'icalevent';
1359 $event->type_picto = 'rss';
1360
1361 $event->icalname = $namecal;
1362 $event->icalcolor = $colorcal;
1363 $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.
1364 $event->datep = (int) ($datestart + $usertime);
1365 $event->datef = (int) ($dateend + $usertime);
1366
1367 if (isset($icalevent['SUMMARY']) && $icalevent['SUMMARY']) {
1368 $event->label = dol_string_nohtmltag($icalevent['SUMMARY']);
1369 } elseif (isset($icalevent['DESCRIPTION']) && $icalevent['DESCRIPTION']) {
1370 $event->label = dol_nl2br(dol_string_nohtmltag($icalevent['DESCRIPTION']), 1);
1371 } else {
1372 $event->label = $langs->trans("ExtSiteNoLabel");
1373 }
1374
1375 // Priority (see https://www.kanzaki.com/docs/ical/priority.html)
1376 // LOW = 0 to 4
1377 // MEDIUM = 5
1378 // HIGH = 6 to 9
1379 if (!empty($icalevent['PRIORITY'])) {
1380 $event->priority = $icalevent['PRIORITY'];
1381 }
1382
1383 // Transparency (see https://www.kanzaki.com/docs/ical/transp.html)
1384 if (!empty($icalevent['TRANSP'])) {
1385 if ($icalevent['TRANSP'] == "TRANSPARENT") {
1386 $event->transparency = 0; // 0 = available / free
1387 }
1388 if ($icalevent['TRANSP'] == "OPAQUE") {
1389 $event->transparency = 1; // 1 = busy
1390 }
1391
1392 // TODO: MS outlook states
1393 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:TRANSPARENT => Available / Free
1394 // X-MICROSOFT-CDO-BUSYSTATUS:FREE + TRANSP:OPAQUE => Work another place
1395 // X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE + TRANSP:OPAQUE => With reservations
1396 // X-MICROSOFT-CDO-BUSYSTATUS:BUSY + TRANSP:OPAQUE => Busy
1397 // X-MICROSOFT-CDO-BUSYSTATUS:OOF + TRANSP:OPAQUE => Away from the office / off-site
1398 }
1399
1400 if (!empty($icalevent['LOCATION'])) {
1401 $event->location = $icalevent['LOCATION'];
1402 }
1403
1404 $event->date_start_in_calendar = $event->datep;
1405
1406 if ((int) $event->datef != 0 && $event->datef >= $event->datep) {
1407 $event->date_end_in_calendar = $event->datef;
1408 } else {
1409 $event->date_end_in_calendar = $event->datep;
1410 }
1411
1412 // Add event into $eventarray if date range are ok.
1413 if ($event->date_end_in_calendar < $firstdaytoshow || $event->date_start_in_calendar >= $lastdaytoshow) {
1414 //print 'x'.$datestart.'-'.$dateend;exit;
1415 //print 'x'.$datestart.'-'.$dateend;exit;
1416 //print 'x'.$datestart.'-'.$dateend;exit;
1417 // This record is out of visible range
1418 } else {
1419 if ($event->date_start_in_calendar < $firstdaytoshow) {
1420 $event->date_start_in_calendar = $firstdaytoshow;
1421 }
1422 if ($event->date_end_in_calendar >= $lastdaytoshow) {
1423 $event->date_end_in_calendar = ($lastdaytoshow - 1);
1424 }
1425
1426 // Add an entry in actionarray for each day
1427 $daycursor = $event->date_start_in_calendar;
1428 $annee = (int) dol_print_date($daycursor, '%Y', 'tzuserrel');
1429 $mois = (int) dol_print_date($daycursor, '%m', 'tzuserrel');
1430 $jour = (int) dol_print_date($daycursor, '%d', 'tzuserrel');
1431
1432 // Loop on each day covered by action to prepare an index to show on calendar
1433 $loop = true;
1434 $j = 0;
1435 // daykey must be date that represent day box in calendar so must be a user time
1436 $daykey = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1437 $daykeygmt = dol_mktime(0, 0, 0, $mois, $jour, $annee, 'gmt');
1438 do {
1439 //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').' ';
1440 $eventarray[$daykey][] = $event;
1441 $daykey += 60 * 60 * 24;
1442 $daykeygmt += 60 * 60 * 24; // Add one day
1443 if (($event->fulldayevent ? $daykeygmt : $daykey) > $event->date_end_in_calendar) {
1444 $loop = false;
1445 }
1446 } while ($loop);
1447 }
1448 }
1449 }
1450 }
1451 }
1452}
1453
1454// Complete $eventarray with events coming from external module
1455$parameters = array();
1456$object = null;
1457$reshook = $hookmanager->executeHooks('getCalendarEvents', $parameters, $object, $action);
1458if (!empty($hookmanager->resArray['eventarray'])) {
1459 foreach ($hookmanager->resArray['eventarray'] as $keyDate => $events) {
1460 if (!isset($eventarray[$keyDate])) {
1461 $eventarray[$keyDate] = array();
1462 }
1463 $eventarray[$keyDate] = array_merge($eventarray[$keyDate], $events);
1464 }
1465}
1466
1467// Sort events
1468/*
1469foreach ($eventarray as $keyDate => &$dateeventarray) {
1470 usort($dateeventarray, 'sort_events_by_date');
1471}
1472*/
1473
1474$maxnbofchar = 18;
1475$cachethirdparties = array();
1476$cachecontacts = array();
1477$cacheusers = array();
1478// default values
1479$theme_datacolor = array(
1480 array(137, 86, 161),
1481 array(60, 147, 183),
1482 array(250, 190, 80),
1483 array(80, 166, 90),
1484 array(190, 190, 100),
1485 array(91, 115, 247),
1486 array(140, 140, 220),
1487 array(190, 120, 120),
1488 array(115, 125, 150),
1489 array(100, 170, 20),
1490 array(150, 135, 125),
1491 array(85, 135, 150),
1492 array(150, 135, 80),
1493 array(150, 80, 150)
1494);
1495// Define theme_datacolor array
1496$color_file = DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/theme_vars.inc.php";
1497if (is_readable($color_file)) {
1498 include $color_file;
1499 global $theme_datacolor;
1500}
1501
1502$massactionbutton = '';
1503
1504$num = 0;
1505
1506print_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);
1507
1508$link = '';
1509
1510// Show div with list of calendars
1511print $s;
1512
1513// Top filters
1514print '<div class="liste_titre liste_titre_bydiv centpercent">';
1515print_actions_filter($form, $canedit, $search_status, $year, $month, $day, $showbirthday, '', (string) $filtert, '', $pid, $socid, $action, -1, $actioncode, $usergroup, '', $resourceid, $search_categ_cus);
1516print '</div>';
1517
1518
1519$newparam = $param; // newparam is for birthday links
1520$newparam = preg_replace('/showbirthday=/i', 'showbirthday_=', $newparam); // To avoid replacement when replace day= is done
1521$newparam = preg_replace('/mode=show_month&?/i', '', $newparam);
1522$newparam = preg_replace('/mode=show_week&?/i', '', $newparam);
1523$newparam = preg_replace('/day=[0-9]+&?/i', '', $newparam);
1524$newparam = preg_replace('/month=[0-9]+&?/i', '', $newparam);
1525$newparam = preg_replace('/year=[0-9]+&?/i', '', $newparam);
1526$newparam = preg_replace('/viewweek=[0-9]+&?/i', '', $newparam);
1527$newparam = preg_replace('/showbirthday_=/i', 'showbirthday=', $newparam); // Restore correct parameter
1528$newparam .= '&viewweek=1';
1529
1530echo '<input type="hidden" name="actionmove" value="mupdate">';
1531echo '<input type="hidden" name="backtopage" value="'.dol_escape_htmltag($_SERVER['PHP_SELF']).'?'.dol_escape_htmltag($_SERVER['QUERY_STRING']).'">';
1532echo '<input type="hidden" name="newdate" id="newdate">';
1533
1534
1535// Line header with list of days
1536
1537//print "begin_d=".$begin_d." end_d=".$end_d;
1538
1539$currentdaytoshow = $firstdaytoshow;
1540echo '<div class="div-table-responsive">';
1541//print dol_print_date($currentdaytoshow, 'dayhour', 'gmt');
1542
1543$colorsbytype = array();
1544
1545while ($currentdaytoshow < $lastdaytoshow) {
1546 echo '<table class="centpercent noborder nocellnopadd cal_month cal_peruser listwithfilterbefore">';
1547
1548 echo '<tr class="liste_titre">';
1549 echo '<td class="nopaddingtopimp nopaddingbottomimp nowraponsmartphone">';
1550
1551 if ($canedit /* && $mode == 'show_peruser' */) { // mode is forced to show_peruser
1552 // Filter on days
1553 print '<span class="hideonsmartphone" title="'.$langs->trans("VisibleDaysRange").'">';
1554 print img_picto('', 'clock', 'class="fawidth30 inline-block marginleftonly"');
1555 print $langs->trans("DaysOfWeek").'</span>';
1556 print "\n";
1557 print '<div class="ui-grid-a inline-block"><div class="ui-block-a nowraponall">';
1558 print '<input type="number" class="shortbis" name="begin_d" value="'.$begin_d.'" min="1" max="7">';
1559 if (empty($conf->dol_use_jmobile)) {
1560 print ' - ';
1561 } else {
1562 print '</div><div class="ui-block-b">';
1563 }
1564 print '<input type="number" class="shortbis" name="end_d" value="'.$end_d.'" min="1" max="7">';
1565 print '</div></div>';
1566 }
1567
1568 print '</td>';
1569 $i = 0; // 0 = sunday,
1570 while ($i < 7) {
1571 if (($i + 1) < $begin_d || ($i + 1) > $end_d) {
1572 $i++;
1573 continue;
1574 }
1575 echo '<td align="center" colspan="'.($end_h - $begin_h).'">';
1576 echo '<span class="bold spandayofweek">'.$langs->trans("Day".(($i + getDolGlobalInt('MAIN_START_WEEK', 1)) % 7)).'</span>';
1577 print "<br>";
1578 if ($i) {
1579 $valtoshow = dol_time_plus_duree($currentdaytoshow, $i, 'd');
1580 } else {
1581 $valtoshow = $currentdaytoshow;
1582 }
1583 if (dol_print_date($valtoshow, '%Y%m%d') == dol_print_date(dol_now(), '%Y%m%d')) {
1584 echo '<span class="badgeliketopmenu">';
1585 }
1586 print dol_print_date($valtoshow, 'dayreduceformat', 'tzuserrel');
1587 if (dol_print_date($valtoshow, '%Y%m%d') == dol_print_date(dol_now(), '%Y%m%d')) {
1588 echo '</span>';
1589 }
1590 echo "</td>\n";
1591 $i++;
1592 }
1593 echo "</tr>\n";
1594
1595 echo '<tr class="liste_titre">';
1596 echo '<td>';
1597
1598 // Filter on hours
1599 print '<span class="hideonsmartphone" title="'.$langs->trans("VisibleTimeRange").'">';
1600 print img_picto('', 'clock', 'class="fawidth30 inline-block marginleftonly"');
1601 print $langs->trans("Hours").'</span>';
1602 print "\n";
1603 print '<div class="ui-grid-a inline-block"><div class="ui-block-a nowraponall">';
1604 print '<input type="number" class="shortbis" name="begin_h" value="'.$begin_h.'" min="0" max="23">';
1605 if (empty($conf->dol_use_jmobile)) {
1606 print ' - ';
1607 } else {
1608 print '</div><div class="ui-block-b">';
1609 }
1610 print '<input type="number" class="shortbis" name="end_h" value="'.$end_h.'" min="1" max="24">';
1611 if (empty($conf->dol_use_jmobile)) {
1612 print ' '.$langs->trans("HourShort");
1613 }
1614 print '</div></div>';
1615
1616 echo '</td>';
1617 $i = 0;
1618 while ($i < 7) {
1619 if (($i + 1) < $begin_d || ($i + 1) > $end_d) {
1620 $i++;
1621 continue;
1622 }
1623 for ($h = $begin_h; $h < $end_h; $h++) {
1624 echo '<td class="center">';
1625 print '<small style="font-family: courier">'.sprintf("%02d", $h).'</small>';
1626 print "</td>";
1627 }
1628 echo "</td>\n";
1629 $i++;
1630 }
1631 echo "</tr>\n";
1632
1633
1634 // Define $usernames
1635 $usernames = array(); //init
1636 $usernamesid = array();
1637 /* Use this to have list of users only if users have events */
1638 if (getDolGlobalString('AGENDA_SHOWOWNERONLY_ONPERUSERVIEW')) {
1639 foreach ($eventarray as $daykey => $notused) {
1640 // Get all assigned users for each event
1641 foreach ($eventarray[$daykey] as $index => $event) {
1642 $event->fetch_userassigned();
1643 $listofuserid = $event->userassigned;
1644 foreach ($listofuserid as $userid => $tmp) {
1645 if (!in_array($userid, $usernamesid)) {
1646 $usernamesid[$userid] = $userid;
1647 }
1648 }
1649 }
1650 }
1651 } else {
1652 /* Use this list to have lines of all users to show */
1653 $sql = "SELECT u.rowid, u.lastname as lastname, u.firstname, u.statut, u.login, u.admin, u.entity";
1654 $sql .= " FROM ".$db->prefix()."user as u";
1655 if (isModEnabled('multicompany') && getDolGlobalInt('MULTICOMPANY_TRANSVERSE_MODE')) {
1656 $sql .= " WHERE u.rowid IN (";
1657 $sql .= " SELECT ug.fk_user FROM ".$db->prefix()."usergroup_user as ug";
1658 $sql .= " WHERE ug.entity IN (".getEntity('usergroup').")";
1659 if ($usergroup > 0) {
1660 $sql .= " AND ug.fk_usergroup = ".((int) $usergroup);
1661 }
1662 $sql .= ")";
1663 } else {
1664 if ($usergroup > 0) {
1665 $sql .= " LEFT JOIN ".$db->prefix()."usergroup_user as ug ON u.rowid = ug.fk_user";
1666 }
1667 $sql .= " WHERE u.entity IN (".getEntity('user').")";
1668 if ($usergroup > 0) {
1669 $sql .= " AND ug.fk_usergroup = ".((int) $usergroup);
1670 }
1671 }
1672 $sql .= " AND u.statut = 1";
1673 if ($filtert > 0) {
1674 $sql .= " AND u.rowid = ".((int) $filtert);
1675 }
1676 if ($usergroup > 0) {
1677 $sql .= " AND ug.fk_usergroup = ".((int) $usergroup);
1678 }
1679 if ($user->socid > 0) {
1680 // External users should see only contacts of their company
1681 $sql .= " AND u.fk_soc = ".((int) $user->socid);
1682 }
1683 // Filter on users in hierarchy
1684 if (!$canedit || $filtert == '-3') { // If we can't read event of others
1685 if (!$user->hasRight('user', 'user', 'lire') || $filtert == '-3') {
1686 $usersInHierarchy = $user->getAllChildIds(1);
1687 $sql .= " AND u.rowid IN (".$db->sanitize(implode(',', $usersInHierarchy)).")";
1688 }
1689 }
1690
1691 //print $sql;
1692 $resql = $db->query($sql);
1693 if ($resql) {
1694 $num = $db->num_rows($resql);
1695 $i = 0;
1696 if ($num) {
1697 while ($i < $num) {
1698 $obj = $db->fetch_object($resql);
1699 $usernamesid[$obj->rowid] = $obj->rowid;
1700 $i++;
1701 }
1702 }
1703 } else {
1705 }
1706 }
1707 //var_dump($usernamesid);
1708 foreach ($usernamesid as $id) {
1709 $tmpuser = new User($db);
1710 $result = $tmpuser->fetch($id);
1711 $usernames[] = $tmpuser;
1712 }
1713
1714 // Load array of colors by type
1715 $labelbytype = array();
1716 $sql = "SELECT code, color, libelle as label FROM ".MAIN_DB_PREFIX."c_actioncomm ORDER BY position";
1717 $resql = $db->query($sql);
1718 while ($obj = $db->fetch_object($resql)) {
1719 $colorsbytype[$obj->code] = $obj->color;
1720 $labelbytype[$obj->code] = $obj->label;
1721 }
1722
1723 // Loop on each user to show calendar
1724 $todayarray = dol_getdate($now, true);
1725 $sav = $tmpday;
1726 $showheader = true;
1727 $var = false;
1728 foreach ($usernames as $username) {
1729 //if ($username->login != 'admin') continue;
1730
1731 $var = !$var;
1732
1733 echo "<tr>";
1734 echo '<td class="tdoverflowmax100 cal_current_month cal_peruserviewname'.($var ? ' cal_impair' : '').' nopaddingtopimp nopaddingbottomimp noheightimp">';
1735 print '<span class="paddingrightimp">';
1736 print $username->getNomUrl(-1, '', 0, 0, 20, 1, '', 'paddingleft');
1737 print '</span>';
1738 print '</td>';
1739 $tmpday = $sav;
1740
1741 // Lopp on each day of week
1742 $i = 0;
1743 for ($iter_day = 0; $iter_day < 8; $iter_day++) {
1744 if (($i + 1) < $begin_d || ($i + 1) > $end_d) {
1745 $i++;
1746 continue;
1747 }
1748
1749 // Show days of the current week
1750 $curtime = dol_time_plus_duree($currentdaytoshow, $iter_day, 'd');
1751 // $curtime is a gmt time, but we want the day, month, year in user TZ
1752 $tmpday = (int) dol_print_date($curtime, "%d", "tzuserrel");
1753 $tmpmonth = (int) dol_print_date($curtime, "%m", "tzuserrel");
1754 $tmpyear = (int) dol_print_date($curtime, "%Y", "tzuserrel");
1755 //var_dump($curtime.' '.$tmpday.' '.$tmpmonth.' '.$tmpyear);
1756
1757 $style = 'cal_current_month';
1758 if ($iter_day == 6) {
1759 $style .= ' cal_other_month';
1760 }
1761 $today = 0;
1762 if ($todayarray['mday'] == $tmpday && $todayarray['mon'] == $tmpmonth && $todayarray['year'] == $tmpyear) {
1763 $today = 1;
1764 }
1765 if ($today) {
1766 $style = 'cal_today_peruser';
1767 }
1768
1769 show_day_events2($username, $tmpday, $tmpmonth, $tmpyear, 0, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, $showheader, $colorsbytype, $var);
1770
1771 $i++;
1772 }
1773 echo "</tr>\n";
1774 $showheader = false;
1775 }
1776
1777 echo "</table>\n";
1778 echo "<br>";
1779
1780 $currentdaytoshow = dol_time_plus_duree($currentdaytoshow, 7, 'd');
1781}
1782
1783echo '</div>';
1784
1785if (getDolGlobalString('AGENDA_USE_EVENT_TYPE') && getDolGlobalString('AGENDA_USE_COLOR_PER_EVENT_TYPE')) {
1786 $langs->load("commercial");
1787 print '<br>'.$langs->trans("Legend").': <br>';
1788 foreach ($colorsbytype as $code => $color) {
1789 if ($color) {
1790 print '<div style="float: left; padding: 2px; margin-right: 6px;"><div style="background: #'.$color.'; width:16px; float: left; margin-right: 4px;">&nbsp;</div>';
1791 print $langs->trans("Action".$code) != "Action".$code ? $langs->trans("Action".$code) : $labelbytype[$code];
1792 //print $code;
1793 print '</div>';
1794 }
1795 }
1796 //$color=sprintf("%02x%02x%02x",$theme_datacolor[0][0],$theme_datacolor[0][1],$theme_datacolor[0][2]);
1797 print '<div style="float: left; padding: 2px; margin-right: 6px;"><div class="peruser_busy" style="width:16px; float: left; margin-right: 4px;">&nbsp;</div>';
1798 print $langs->trans("Other");
1799 print '</div>';
1800 /* TODO Show this if at least one cumulated event
1801 print '<div style="float: left; padding: 2px; margin-right: 6px;"><div style="background: #222222; width:16px; float: left; margin-right: 4px;">&nbsp;</div>';
1802 print $langs->trans("SeveralEvents");
1803 print '</div>';
1804 */
1805}
1806
1807print "\n".'</form>';
1808
1809print "\n";
1810
1811// Add js code to manage click on a box
1812print '<script type="text/javascript">
1813jQuery(document).ready(function() {
1814 jQuery(".onclickopenref").click(function() {
1815 var ref=$(this).attr(\'ref\');
1816 var res = ref.split("_");
1817 var type = res[0];
1818 var userid = res[1];
1819 var year = res[2];
1820 var month = res[3];
1821 var day = res[4];
1822 var hour = res[5];
1823 var min = res[6];
1824 var ids = res[7];
1825
1826 console.log("We click on a class onclickopenref in page peruser with ref="+ref+" type="+type);
1827
1828 if (ids == \'none\') /* No event */
1829 {
1830 /* alert(\'no event\'); */
1831 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 : '')).'"
1832 window.location.href = url;
1833 }
1834 else if (ids.indexOf(",") > -1) /* There is several events */
1835 {
1836 /* alert(\'several events\'); */
1837 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;
1838 window.location.href = url;
1839 } else { /* One event */
1840 /* alert(\'one event\'); */
1841 if (type == \'holiday\') {
1842 url = "'.DOL_URL_ROOT.'/holiday/card.php?id="+ids
1843 } else {
1844 url = "'.DOL_URL_ROOT.'/comm/action/card.php?action=view&id="+ids
1845 }
1846 window.location.href = url;
1847 }
1848 });
1849});
1850</script>';
1851
1852// End of page
1853llxFooter();
1854$db->close();
1855
1856
1857
1858
1879function 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)
1880{
1881 global $db;
1882 global $user, $conf, $langs, $hookmanager, $action;
1883 global $filter, $filtert, $status, $actioncode; // Filters used into search form
1884 global $theme_datacolor; // Array with a list of different we can use (come from theme)
1885 global $cachethirdparties, $cachecontacts, $cacheusers, $cacheprojects, $colorindexused;
1886 global $begin_h, $end_h;
1887
1888 $cases1 = array(); // Color first half hour
1889 $cases2 = array(); // Color second half hour
1890 $cases3 = array(); // Color third half hour
1891 $cases4 = array(); // Color 4th half hour
1892
1899 '
1900 @phan-var-force array<int,array<int,array<string,string|int|bool>>> $cases1
1901 @phan-var-force array<int,array<int,array<string,string|int|bool>>> $cases2
1902 @phan-var-force array<int,array<int,array<string,string|int|bool>>> $cases3
1903 @phan-var-force array<int,array<int,array<string,string|int|bool>>> $cases4
1904 ';
1905
1906 $i = 0;
1907 $numother = 0;
1908 $numbirthday = 0;
1909 $numical = 0;
1910 $numicals = array();
1911 //$ymd = sprintf("%04d", $year).sprintf("%02d", $month).sprintf("%02d", $day);
1912
1913 $colorindexused[$user->id] = 0; // Color index for current user (user->id) is always 0
1914 $nextindextouse = count($colorindexused); // At first run this is 0, so first user has 0, next 1, ...
1915 //if ($username->id && $day==1) {
1916 //var_dump($eventarray);
1917 //}
1918 //var_dump("------ username=".$username->login." for day=".$day);
1919
1920 // We are in a particular day for $username, now we scan all events
1921 foreach ($eventarray as $daykey => $notused) {
1922 $annee = (int) dol_print_date($daykey, '%Y', 'tzuserrel');
1923 $mois = (int) dol_print_date($daykey, '%m', 'tzuserrel');
1924 $jour = (int) dol_print_date($daykey, '%d', 'tzuserrel');
1925 //var_dump("daykey=$daykey day=$day jour=$jour, month=$month mois=$mois, year=$year annee=$annee ".dol_print_date($daykey, 'dayhour', 'gmt'));
1926 //var_dump($notused);
1927
1928 if ($day == $jour && (int) $month == $mois && $year == $annee) { // Is it the day we are looking for when calling function ?
1929 //var_dump("day=$day jour=$jour month=$month mois=$mois year=$year annee=$annee");
1930
1931 // Scan all events for this date
1932 foreach ($eventarray[$daykey] as $index => $event) {
1933 //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";
1934 //var_dump($event);
1935
1936 $keysofuserassigned = array_keys($event->userassigned);
1937
1938 if (!in_array($username->id, $keysofuserassigned)) {
1939 continue; // We discard record if event is from another user than user we want to show
1940 }
1941 //if ($username->id != $event->userownerid) continue; // We discard record if event is from another user than user we want to show
1942
1943 $parameters = array();
1944 $reshook = $hookmanager->executeHooks('formatEvent', $parameters, $event, $action); // Note that $action and $object may have been modified by some hooks
1945 if ($reshook < 0) {
1946 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1947 }
1948
1949 // Define $color (Hex string like '0088FF') and $cssclass of event
1950 $color = -1;
1951 $cssclass = '';
1952 $colorindex = -1;
1953
1954 if ($event->type_code == 'HOLIDAY') {
1955 $cssclass = 'family_holiday';
1956 }
1957
1958 if (in_array($user->id, $keysofuserassigned)) {
1959 $cssclass = 'family_mytasks';
1960
1961 if (empty($cacheusers[$event->userownerid])) {
1962 $newuser = new User($db);
1963 $newuser->fetch($event->userownerid);
1964 $cacheusers[$event->userownerid] = $newuser;
1965 }
1966 //var_dump($cacheusers[$event->userownerid]->color);
1967
1968 // We decide to choose color of owner of event (event->userownerid is user id of owner, event->userassigned contains all users assigned to event)
1969 if (!empty($cacheusers[$event->userownerid]->color)) {
1970 $color = $cacheusers[$event->userownerid]->color;
1971 }
1972
1973 if (getDolGlobalString('AGENDA_USE_COLOR_PER_EVENT_TYPE')) {
1974 $color = $event->type_color;
1975 }
1976 } elseif ($event->type_code == 'ICALEVENT') {
1977 $numical++;
1978 if (!empty($event->icalname)) {
1979 if (!isset($numicals[dol_string_nospecial($event->icalname)])) {
1980 $numicals[dol_string_nospecial($event->icalname)] = 0;
1981 }
1982 $numicals[dol_string_nospecial($event->icalname)]++;
1983 }
1984
1985 $color = $event->icalcolor;
1986 $cssclass = (!empty($event->icalname) ? 'family_ext'.md5($event->icalname) : 'family_other unsortable');
1987 } elseif ($event->type_code == 'BIRTHDAY') {
1988 $numbirthday++;
1989 $colorindex = 2;
1990 $cssclass = 'family_birthday unsortable';
1991 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
1992 } else {
1993 $numother++;
1994 $color = ($event->icalcolor ? $event->icalcolor : -1);
1995 $cssclass = (!empty($event->icalname) ? 'family_ext'.md5($event->icalname) : 'family_other');
1996
1997 if (empty($cacheusers[$event->userownerid])) {
1998 $newuser = new User($db);
1999 $newuser->fetch($event->userownerid);
2000 $cacheusers[$event->userownerid] = $newuser;
2001 }
2002 //var_dump($cacheusers[$event->userownerid]->color);
2003
2004 // We decide to choose color of owner of event (event->userownerid is user id of owner, event->userassigned contains all users assigned to event)
2005 if (!empty($cacheusers[$event->userownerid]->color)) {
2006 $color = $cacheusers[$event->userownerid]->color;
2007 }
2008
2009 if (getDolGlobalString('AGENDA_USE_COLOR_PER_EVENT_TYPE')) {
2010 $color = $event->type_color;
2011 }
2012 }
2013
2014 if ($color < 0) { // Color was not set on user card. Set color according to color index.
2015 // Define color index if not yet defined
2016 $idusertouse = ($event->userownerid ? $event->userownerid : 0);
2017 if (isset($colorindexused[$idusertouse])) {
2018 $colorindex = $colorindexused[$idusertouse]; // Color already assigned to this user
2019 } else {
2020 $colorindex = $nextindextouse;
2021 $colorindexused[$idusertouse] = $colorindex;
2022 if (!empty($theme_datacolor[$nextindextouse + 1])) {
2023 $nextindextouse++; // Prepare to use next color
2024 }
2025 }
2026 // Define color
2027 $color = sprintf("%02x%02x%02x", $theme_datacolor[$colorindex][0], $theme_datacolor[$colorindex][1], $theme_datacolor[$colorindex][2]);
2028 }
2029
2030 // 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)
2031 for ($h = $begin_h; $h < $end_h; $h++) {
2032 //if ($username->id == 1 && $day==1) print 'h='.$h;
2033 $newcolor = ''; //init
2034 if (empty($event->fulldayevent)) {
2035 $a = dol_mktime((int) $h, 0, 0, $month, $day, $year, 'tzuserrel', 0);
2036 $b = dol_mktime((int) $h, 15, 0, $month, $day, $year, 'tzuserrel', 0);
2037 $b1 = dol_mktime((int) $h, 30, 0, $month, $day, $year, 'tzuserrel', 0);
2038 $b2 = dol_mktime((int) $h, 45, 0, $month, $day, $year, 'tzuserrel', 0);
2039 $c = dol_mktime((int) $h + 1, 0, 0, $month, $day, $year, 'tzuserrel', 0);
2040
2041 $dateendtouse = $event->date_end_in_calendar;
2042 if ($dateendtouse == $event->date_start_in_calendar) {
2043 $dateendtouse++;
2044 }
2045
2046 //print dol_print_date($event->date_start_in_calendar,'dayhour').'-'.dol_print_date($a,'dayhour').'-'.dol_print_date($b,'dayhour').'<br>';
2047 if ($event->date_start_in_calendar < $b && $dateendtouse > $a) {
2048 $busy = $event->transparency;
2049 $cases1[$h][$event->id]['busy'] = $busy;
2050 $cases1[$h][$event->id]['string'] = dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzuserrel');
2051 if ($event->date_end_in_calendar && $event->date_end_in_calendar != $event->date_start_in_calendar) {
2052 $tmpa = dol_getdate($event->date_start_in_calendar, true);
2053 $tmpb = dol_getdate($event->date_end_in_calendar, true);
2054 if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
2055 $cases1[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'hour', 'tzuserrel');
2056 } else {
2057 $cases1[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzuserrel');
2058 }
2059 }
2060 if ($event->label) {
2061 $cases1[$h][$event->id]['string'] .= ' - '.$event->label;
2062 }
2063 $cases1[$h][$event->id]['typecode'] = $event->type_code;
2064 if ($event->type_code == 'HOLIDAY') {
2065 $cases1[$h][$event->id]['css'] = 'peruser_holiday ';
2066 if (GETPOSTINT('check_holiday')) {
2067 $cases1[$h][$event->id]['css'] .= 'peruser_holiday_imp ';
2068 }
2069 } else {
2070 $cases1[$h][$event->id]['color'] = $color;
2071
2072 if ($event->fk_project > 0) {
2073 if (empty($cacheprojects[$event->fk_project])) {
2074 $tmpproj = new Project($db);
2075 $tmpproj->fetch($event->fk_project);
2076 $cacheprojects[$event->fk_project] = $tmpproj;
2077 }
2078 $cases1[$h][$event->id]['string'] .= ', '.$langs->trans("Project").': '.$cacheprojects[$event->fk_project]->ref.' - '.$cacheprojects[$event->fk_project]->title;
2079 }
2080 if ($event->socid > 0) {
2081 if (empty($cachethirdparties[$event->socid])) {
2082 $tmpthirdparty = new Societe($db);
2083 $tmpthirdparty->fetch($event->socid);
2084 $cachethirdparties[$event->socid] = $tmpthirdparty;
2085 }
2086 $cases1[$h][$event->id]['string'] .= ', '.$cachethirdparties[$event->socid]->name;
2087 }
2088 if ($event->contact_id > 0) {
2089 if (empty($cachecontacts[$event->contact_id])) {
2090 $tmpcontact = new Contact($db);
2091 $tmpcontact->fetch($event->contact_id);
2092 $cachecontacts[$event->contact_id] = $tmpcontact;
2093 }
2094 $cases1[$h][$event->id]['string'] .= ', '.$cachecontacts[$event->contact_id]->getFullName($langs);
2095 }
2096 }
2097 }
2098 if ($event->date_start_in_calendar < $b1 && $dateendtouse > $b) {
2099 $busy = $event->transparency;
2100 $cases2[$h][$event->id]['busy'] = $busy;
2101 $cases2[$h][$event->id]['string'] = dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzuserrel');
2102 if ($event->date_end_in_calendar && $event->date_end_in_calendar != $event->date_start_in_calendar) {
2103 $tmpa = dol_getdate($event->date_start_in_calendar, true);
2104 $tmpb = dol_getdate($event->date_end_in_calendar, true);
2105 if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
2106 $cases2[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'hour', 'tzuserrel');
2107 } else {
2108 $cases2[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzuserrel');
2109 }
2110 }
2111 if ($event->label) {
2112 $cases2[$h][$event->id]['string'] .= ' - '.$event->label;
2113 }
2114 $cases2[$h][$event->id]['typecode'] = $event->type_code;
2115 if ($event->type_code == 'HOLIDAY') {
2116 $cases2[$h][$event->id]['css'] = 'peruser_holiday ';
2117 if (GETPOSTINT('check_holiday')) {
2118 $cases2[$h][$event->id]['css'] .= 'peruser_holiday_imp ';
2119 }
2120 } else {
2121 $cases2[$h][$event->id]['color'] = $color;
2122
2123 if ($event->fk_project > 0) {
2124 if (empty($cacheprojects[$event->fk_project])) {
2125 $tmpproj = new Project($db);
2126 $tmpproj->fetch($event->fk_project);
2127 $cacheprojects[$event->fk_project] = $tmpproj;
2128 }
2129 $cases2[$h][$event->id]['string'] .= ', '.$langs->trans("Project").': '.$cacheprojects[$event->fk_project]->ref.' - '.$cacheprojects[$event->fk_project]->title;
2130 }
2131 if ($event->socid > 0) {
2132 if (empty($cachethirdparties[$event->socid])) {
2133 $tmpthirdparty = new Societe($db);
2134 $tmpthirdparty->fetch($event->socid);
2135 $cachethirdparties[$event->socid] = $tmpthirdparty;
2136 }
2137 $cases2[$h][$event->id]['string'] .= ', '.$cachethirdparties[$event->socid]->name;
2138 }
2139 if ($event->contact_id > 0) {
2140 if (empty($cachecontacts[$event->contact_id])) {
2141 $tmpcontact = new Contact($db);
2142 $tmpcontact->fetch($event->contact_id);
2143 $cachecontacts[$event->contact_id] = $tmpcontact;
2144 }
2145 $cases2[$h][$event->id]['string'] .= ', '.$cachecontacts[$event->contact_id]->getFullName($langs);
2146 }
2147 }
2148 }
2149 if ($event->date_start_in_calendar < $b2 && $dateendtouse > $b1) {
2150 $busy = $event->transparency;
2151 $cases3[$h][$event->id]['busy'] = $busy;
2152 $cases3[$h][$event->id]['string'] = dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzuserrel');
2153 if ($event->date_end_in_calendar && $event->date_end_in_calendar != $event->date_start_in_calendar) {
2154 $tmpa = dol_getdate($event->date_start_in_calendar, true);
2155 $tmpb = dol_getdate($event->date_end_in_calendar, true);
2156 if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
2157 $cases3[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'hour', 'tzuserrel');
2158 } else {
2159 $cases3[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzuserrel');
2160 }
2161 }
2162 if ($event->label) {
2163 $cases3[$h][$event->id]['string'] .= ' - '.$event->label;
2164 }
2165 $cases3[$h][$event->id]['typecode'] = $event->type_code;
2166 if ($event->type_code == 'HOLIDAY') {
2167 $cases3[$h][$event->id]['css'] .= 'peruser_holiday ';
2168 if (GETPOSTINT('check_holiday')) {
2169 $cases3[$h][$event->id]['css'] .= 'peruser_holiday_imp ';
2170 }
2171 } else {
2172 $cases3[$h][$event->id]['color'] = $color;
2173
2174 if ($event->fk_project > 0) {
2175 if (empty($cacheprojects[$event->fk_project])) {
2176 $tmpproj = new Project($db);
2177 $tmpproj->fetch($event->fk_project);
2178 $cacheprojects[$event->fk_project] = $tmpproj;
2179 }
2180 $cases3[$h][$event->id]['string'] .= ', '.$langs->trans("Project").': '.$cacheprojects[$event->fk_project]->ref.' - '.$cacheprojects[$event->fk_project]->title;
2181 }
2182 if ($event->socid > 0) {
2183 if (empty($cachethirdparties[$event->socid])) {
2184 $tmpthirdparty = new Societe($db);
2185 $tmpthirdparty->fetch($event->socid);
2186 $cachethirdparties[$event->socid] = $tmpthirdparty;
2187 }
2188 $cases3[$h][$event->id]['string'] .= ', '.$cachethirdparties[$event->socid]->name;
2189 }
2190 if ($event->contact_id > 0) {
2191 if (empty($cachecontacts[$event->contact_id])) {
2192 $tmpcontact = new Contact($db);
2193 $tmpcontact->fetch($event->contact_id);
2194 $cachecontacts[$event->contact_id] = $tmpcontact;
2195 }
2196 $cases3[$h][$event->id]['string'] .= ', '.$cachecontacts[$event->contact_id]->getFullName($langs);
2197 }
2198 }
2199 }
2200 if ($event->date_start_in_calendar < $c && $dateendtouse > $b2) {
2201 $busy = $event->transparency;
2202 $cases4[$h][$event->id]['busy'] = $busy;
2203 $cases4[$h][$event->id]['string'] = dol_print_date($event->date_start_in_calendar, 'dayhour', 'tzuserrel');
2204 if ($event->date_end_in_calendar && $event->date_end_in_calendar != $event->date_start_in_calendar) {
2205 $tmpa = dol_getdate($event->date_start_in_calendar, true);
2206 $tmpb = dol_getdate($event->date_end_in_calendar, true);
2207 if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
2208 $cases4[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'hour', 'tzuserrel');
2209 } else {
2210 $cases4[$h][$event->id]['string'] .= '-'.dol_print_date($event->date_end_in_calendar, 'dayhour', 'tzuserrel');
2211 }
2212 }
2213 if ($event->label) {
2214 $cases4[$h][$event->id]['string'] .= ' - '.$event->label;
2215 }
2216 $cases4[$h][$event->id]['typecode'] = $event->type_code;
2217 if ($event->type_code == 'HOLIDAY') {
2218 $cases4[$h][$event->id]['css'] = 'peruser_holiday ';
2219 if (GETPOSTINT('check_holiday')) {
2220 $cases4[$h][$event->id]['css'] .= 'peruser_holiday_imp ';
2221 }
2222 } else {
2223 $cases4[$h][$event->id]['color'] = $color;
2224
2225 if ($event->fk_project > 0) {
2226 if (empty($cacheprojects[$event->fk_project])) {
2227 $tmpproj = new Project($db);
2228 $tmpproj->fetch($event->fk_project);
2229 $cacheprojects[$event->fk_project] = $tmpproj;
2230 }
2231 $cases4[$h][$event->id]['string'] .= ', '.$langs->trans("Project").': '.$cacheprojects[$event->fk_project]->ref.' - '.$cacheprojects[$event->fk_project]->title;
2232 }
2233 if ($event->socid > 0) {
2234 if (empty($cachethirdparties[$event->socid])) {
2235 $tmpthirdparty = new Societe($db);
2236 $tmpthirdparty->fetch($event->socid);
2237 $cachethirdparties[$event->socid] = $tmpthirdparty;
2238 }
2239 $cases4[$h][$event->id]['string'] .= ', '.$cachethirdparties[$event->socid]->name;
2240 }
2241 if ($event->contact_id > 0) {
2242 if (empty($cachecontacts[$event->contact_id])) {
2243 $tmpcontact = new Contact($db);
2244 $tmpcontact->fetch($event->contact_id);
2245 $cachecontacts[$event->contact_id] = $tmpcontact;
2246 }
2247 $cases4[$h][$event->id]['string'] .= ', '.$cachecontacts[$event->contact_id]->getFullName($langs);
2248 }
2249 }
2250 }
2251 } else {
2252 $busy = $event->transparency;
2253 $cases1[$h][$event->id]['busy'] = $busy;
2254 $cases2[$h][$event->id]['busy'] = $busy;
2255 $cases3[$h][$event->id]['busy'] = $busy;
2256 $cases4[$h][$event->id]['busy'] = $busy;
2257 $cases1[$h][$event->id]['string'] = $event->label;
2258 $cases2[$h][$event->id]['string'] = $event->label;
2259 $cases3[$h][$event->id]['string'] = $event->label;
2260 $cases4[$h][$event->id]['string'] = $event->label;
2261 $cases1[$h][$event->id]['typecode'] = $event->type_code;
2262 $cases2[$h][$event->id]['typecode'] = $event->type_code;
2263 $cases3[$h][$event->id]['typecode'] = $event->type_code;
2264 $cases4[$h][$event->id]['typecode'] = $event->type_code;
2265 $cases1[$h][$event->id]['color'] = $color;
2266 $cases2[$h][$event->id]['color'] = $color;
2267 $cases3[$h][$event->id]['color'] = $color;
2268 $cases4[$h][$event->id]['color'] = $color;
2269 $cases1[$h][$event->id]['css'] = '';
2270 $cases2[$h][$event->id]['css'] = '';
2271 $cases3[$h][$event->id]['css'] = '';
2272 $cases4[$h][$event->id]['css'] = '';
2273 }
2274 }
2275 $i++;
2276 }
2277
2278 break; // We found the date we were looking for. No need to search anymore.
2279 }
2280 }
2281
2282 // Now output $casesX from start hour to end hour
2283 for ($h = $begin_h; $h < $end_h; $h++) {
2284 $color1 = '';
2285 $color2 = '';
2286 $color3 = '';
2287 $color4 = '';
2288 $style1 = 'onclickopenref ';
2289 $style2 = 'onclickopenref ';
2290 $style3 = 'onclickopenref ';
2291 $style4 = 'onclickopenref ';
2292 $string1 = '&nbsp;';
2293 $string2 = '&nbsp;';
2294 $string3 = '&nbsp;';
2295 $string4 = '&nbsp;';
2296 $title1 = '';
2297 $title2 = '';
2298 $title3 = '';
2299 $title4 = '';
2300 if (isset($cases1[$h])) {
2301 //$title1.=count($cases1[$h]).' '.(count($cases1[$h])==1?$langs->trans("Event"):$langs->trans("Events"));
2302 if (count($cases1[$h]) > 1) {
2303 $title1 .= count($cases1[$h]).' '.(count($cases1[$h]) == 1 ? $langs->trans("Event") : $langs->trans("Events"));
2304 }
2305
2306 $peruserbusyadded = 0;
2307 $perusernotbusyadded = 0;
2308 foreach ($cases1[$h] as $id => $ev) {
2309 if (!empty($ev['busy']) && !getDolGlobalString('AGENDA_NO_TRANSPARENT_ON_NOT_BUSY')) {
2310 $style1 .= $peruserbusyadded ? '' : ' peruser_busy';
2311 $peruserbusyadded++;
2312 } else {
2313 $style1 .= $perusernotbusyadded ? '' : 'peruser_notbusy ';
2314 $perusernotbusyadded++;
2315 }
2316 if (!empty($ev['css'])) {
2317 $style1 .= $ev['css'].' ';
2318 }
2319 }
2320 }
2321 if (isset($cases2[$h])) {
2322 //$title2.=count($cases2[$h]).' '.(count($cases2[$h])==1?$langs->trans("Event"):$langs->trans("Events"));
2323 if (count($cases2[$h]) > 1) {
2324 $title2 .= count($cases2[$h]).' '.(count($cases2[$h]) == 1 ? $langs->trans("Event") : $langs->trans("Events"));
2325 }
2326
2327 $peruserbusyadded = 0;
2328 $perusernotbusyadded = 0;
2329 foreach ($cases2[$h] as $id => $ev) {
2330 if (!empty($ev['busy']) && !getDolGlobalString('AGENDA_NO_TRANSPARENT_ON_NOT_BUSY')) {
2331 $style2 .= $peruserbusyadded ? '' : ' peruser_busy';
2332 $peruserbusyadded++;
2333 } else {
2334 $style2 .= $perusernotbusyadded ? '' : 'peruser_notbusy ';
2335 $perusernotbusyadded++;
2336 }
2337 if (!empty($ev['css'])) {
2338 $style2 .= $ev['css'].' ';
2339 }
2340 }
2341 }
2342 if (isset($cases3[$h])) {
2343 //$title3.=count($cases3[$h]).' '.(count($cases3[$h])==1?$langs->trans("Event"):$langs->trans("Events"));
2344 if (count($cases3[$h]) > 1) {
2345 $title3 .= count($cases3[$h]).' '.(count($cases3[$h]) == 1 ? $langs->trans("Event") : $langs->trans("Events"));
2346 }
2347
2348 $peruserbusyadded = 0;
2349 $perusernotbusyadded = 0;
2350 foreach ($cases3[$h] as $id => $ev) {
2351 if (!empty($ev['busy']) && !getDolGlobalString('AGENDA_NO_TRANSPARENT_ON_NOT_BUSY')) {
2352 $style3 .= $peruserbusyadded ? '' : ' peruser_busy';
2353 $peruserbusyadded++;
2354 } else {
2355 $style3 .= $perusernotbusyadded ? '' : 'peruser_notbusy ';
2356 $perusernotbusyadded++;
2357 }
2358 if (!empty($ev['css'])) {
2359 $style3 .= $ev['css'].' ';
2360 }
2361 }
2362 }
2363 if (isset($cases4[$h])) {
2364 //$title4.=count($cases3[$h]).' '.(count($cases3[$h])==1?$langs->trans("Event"):$langs->trans("Events"));
2365 if (count($cases4[$h]) > 1) {
2366 $title4 .= count($cases4[$h]).' '.(count($cases4[$h]) == 1 ? $langs->trans("Event") : $langs->trans("Events"));
2367 }
2368
2369 $peruserbusyadded = 0;
2370 $perusernotbusyadded = 0;
2371 foreach ($cases4[$h] as $id => $ev) {
2372 if (!empty($ev['busy']) && !getDolGlobalString('AGENDA_NO_TRANSPARENT_ON_NOT_BUSY')) {
2373 $style4 .= $peruserbusyadded ? '' : ' peruser_busy';
2374 $peruserbusyadded++;
2375 } else {
2376 $style4 .= $perusernotbusyadded ? '' : 'peruser_notbusy ';
2377 $perusernotbusyadded++;
2378 }
2379 if (!empty($ev['css'])) {
2380 $style4 .= $ev['css'].' ';
2381 }
2382 }
2383 }
2384
2385 $ids1 = '';
2386 $ids2 = '';
2387 $ids3 = '';
2388 $ids4 = '';
2389 if (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) && array_keys($cases1[$h])) {
2390 $ids1 = implode(', ', array_keys($cases1[$h]));
2391 }
2392 if (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) && array_keys($cases2[$h])) {
2393 $ids2 = implode(', ', array_keys($cases2[$h]));
2394 }
2395 if (!empty($cases3[$h]) && is_array($cases3[$h]) && count($cases3[$h]) && array_keys($cases3[$h])) {
2396 $ids3 = implode(',', array_keys($cases3[$h]));
2397 }
2398 if (!empty($cases4[$h]) && is_array($cases4[$h]) && count($cases4[$h]) && array_keys($cases4[$h])) {
2399 $ids4 = implode(',', array_keys($cases4[$h]));
2400 }
2401
2402 if ($h == $begin_h) {
2403 echo '<td class="'.$style.'_peruserleft cal_peruser'.($var ? ' cal_impair '.$style.'_impair' : '').'">';
2404 } else {
2405 echo '<td class="'.$style.' cal_peruser'.($var ? ' cal_impair '.$style.'_impair' : '').'">';
2406 }
2407
2408 // only 1 event in first quarter
2409 $ref1 = 'ref';
2410 if (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) == 1) {
2411 $output = array_slice($cases1[$h], 0, 1);
2412 if ($output[0]['typecode'] == 'HOLIDAY') {
2413 $ref1 = 'holiday';
2414 $title1 = $langs->trans("Holiday");
2415 } else {
2416 $title1 = $langs->trans("Ref").' '.$ids1.($title1 ? ' - '.$title1 : '');
2417 if ($output[0]['string']) {
2418 $title1 .= ' - '.$output[0]['string'];
2419 }
2420 }
2421 if ($output[0]['color']) {
2422 $color1 = $output[0]['color'];
2423 }
2424 } elseif (!empty($cases1[$h]) && is_array($cases1[$h]) && count($cases1[$h]) > 1) {
2425 $title1 = $langs->trans("Ref").' '.$ids1.($title1 ? ' - '.$title1 : '');
2426 $color1 = '222222';
2427 }
2428
2429 // only 1 event in second quarter
2430 $ref2 = 'ref';
2431 if (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) == 1) {
2432 $output = array_slice($cases2[$h], 0, 1);
2433 if ($output[0]['typecode'] == 'HOLIDAY') {
2434 $ref2 = 'holiday';
2435 $title2 = $langs->trans("Holiday");
2436 } else {
2437 $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : '');
2438 if ($output[0]['string']) {
2439 $title2 .= ' - '.$output[0]['string'];
2440 }
2441 }
2442 if ($output[0]['color']) {
2443 $color2 = $output[0]['color'];
2444 }
2445 } elseif (!empty($cases2[$h]) && is_array($cases2[$h]) && count($cases2[$h]) > 1) {
2446 $title2 = $langs->trans("Ref").' '.$ids2.($title2 ? ' - '.$title2 : '');
2447 $color2 = '222222';
2448 }
2449
2450 // only 1 event in third quarter
2451 $ref3 = 'ref';
2452 if (!empty($cases3[$h]) && is_array($cases3[$h]) && count($cases3[$h]) == 1) {
2453 $output = array_slice($cases3[$h], 0, 1);
2454 if ($output[0]['typecode'] == 'HOLIDAY') {
2455 $ref3 = 'holiday';
2456 $title3 = $langs->trans("Holiday");
2457 } else {
2458 $title3 = $langs->trans("Ref").' '.$ids3.($title3 ? ' - '.$title3 : '');
2459 if ($output[0]['string']) {
2460 $title3 .= ' - '.$output[0]['string'];
2461 }
2462 }
2463 if ($output[0]['color']) {
2464 $color3 = $output[0]['color'];
2465 }
2466 } elseif (!empty($cases3[$h]) && is_array($cases3[$h]) && count($cases3[$h]) > 1) {
2467 $title3 = $langs->trans("Ref").' '.$ids3.($title3 ? ' - '.$title3 : '');
2468 $color3 = '222222';
2469 }
2470
2471 // only 1 event in fourth quarter
2472 $ref4 = 'ref';
2473 if (!empty($cases4[$h]) && is_array($cases4[$h]) && count($cases4[$h]) == 1) {
2474 $output = array_slice($cases4[$h], 0, 1);
2475 if ($output[0]['typecode'] == 'HOLIDAY') {
2476 $ref4 = 'holiday';
2477 $title4 = $langs->trans("Holiday");
2478 } else {
2479 $title4 = $langs->trans("Ref").' '.$ids4.($title4 ? ' - '.$title4 : '');
2480 if ($output[0]['string']) {
2481 $title4 .= ' - '.$output[0]['string'];
2482 }
2483 }
2484 if ($output[0]['color']) {
2485 $color4 = $output[0]['color'];
2486 }
2487 } elseif (!empty($cases4[$h]) && is_array($cases4[$h]) && count($cases4[$h]) > 1) {
2488 $title4 = $langs->trans("Ref").' '.$ids4.($title4 ? ' - '.$title4 : '');
2489 $color4 = '222222';
2490 }
2491
2492 print '<table class="nobordernopadding case centpercent">';
2493 print '<tr>';
2494 print '<td ';
2495 if (preg_match('/peruser_notbusy/', $style1)) {
2496 print 'style="border: 1px solid #'.($color1 ? $color1 : "888").' !important" ';
2497 } elseif ($color1) {
2498 print 'style="background: #'.$color1.'; "';
2499 }
2500 print 'class="';
2501 print $style1;
2502 print 'center'.($title1 ? ' classfortooltip' : '').($title1 ? ' cursorpointer' : '').'"';
2503 print 'ref="'.$ref1.'_'.$username->id.'_'.sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day).'_'.sprintf("%02d", $h).'_00_'.($ids1 ? $ids1 : 'none').'"';
2504 print ($title1 ? ' title="'.$title1.'"' : '').'>';
2505 print $string1;
2506 print '</td>';
2507
2508 print '<td ';
2509 if (preg_match('/peruser_notbusy/', $style2)) {
2510 print 'style="border: 1px solid #'.($color2 ? $color2 : "888").' !important" ';
2511 } elseif ($color2) {
2512 print 'style="background: #'.$color2.'; "';
2513 }
2514 print 'class="';
2515 print $style2;
2516 print 'center'.($title2 ? ' classfortooltip' : '').($title2 ? ' cursorpointer' : '').'"';
2517 print ' ref="'.$ref2.'_'.$username->id.'_'.sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day).'_'.sprintf("%02d", $h).'_15_'.($ids2 ? $ids2 : 'none').'"';
2518 print ($title2 ? ' title="'.$title2.'"' : '').'>';
2519 print $string2;
2520 print '</td>';
2521
2522 print '<td ';
2523 if (preg_match('/peruser_notbusy/', $style3)) {
2524 print 'style="border: 1px solid #'.($color3 ? $color3 : "888").' !important" ';
2525 } elseif ($color3) {
2526 print 'style="background: #'.$color3.'; "';
2527 }
2528 print 'class="';
2529 print $style3;
2530 print 'center'.($title3 ? ' classfortooltip' : '').($title3 ? ' cursorpointer' : '').'"';
2531 print ' ref="'.$ref3.'_'.$username->id.'_'.sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day).'_'.sprintf("%02d", $h).'_30_'.($ids3 ? $ids3 : 'none').'"';
2532 print ($title3 ? ' title="'.$title3.'"' : '').'>';
2533 print $string3;
2534 print '</td>';
2535
2536 print '<td ';
2537 if (preg_match('/peruser_notbusy/', $style4)) {
2538 print 'style="border: 1px solid #'.($color4 ? $color4 : "888").' !important" ';
2539 } elseif ($color4) {
2540 print 'style="background: #'.$color4.'; "';
2541 }
2542 print 'class="';
2543 print $style4;
2544 print 'center'.($title4 ? ' classfortooltip' : '').($title4 ? ' cursorpointer' : '').'"';
2545 print ' ref="'.$ref4.'_'.$username->id.'_'.sprintf("%04d", $year).'_'.sprintf("%02d", $month).'_'.sprintf("%02d", $day).'_'.sprintf("%02d", $h).'_45_'.($ids4 ? $ids4 : 'none').'"';
2546 print ($title4 ? ' title="'.$title4.'"' : '').'>';
2547 print $string4;
2548 print '</td>';
2549
2550 print '</tr>';
2551 print '</table>';
2552 print '</td>';
2553 }
2554}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
agenda_get_birthday_events($db, $langs, $user, $mode, $month, $day, $year, &$eventarray, &$nbevents)
Complete an agenda calendar event array with contact birthday pseudo-events.
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:1217
$cacheusers
Definition index.php:1215
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...
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
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.
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).
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.
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)
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_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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...
Definition html.lib.php:172
conf($dolibarr_main_document_root, $realpathconf=null)
Load conf file (file must exists)
Definition inc.php:431
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
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.