dolibarr  20.0.0-beta
perday.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2010 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2010 François Legastelois <flegastelois@teclib.com>
6  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
7  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
29 require "../../main.inc.php";
30 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
38 
39 // Load translation files required by the page
40 $langs->loadLangs(array('projects', 'users', 'companies'));
41 
42 $action = GETPOST('action', 'aZ09');
43 $mode = GETPOST("mode", 'alpha');
44 $id = GETPOSTINT('id');
45 $taskid = GETPOSTINT('taskid');
46 
47 $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'perdaycard';
48 
49 $mine = 0;
50 if ($mode == 'mine') {
51  $mine = 1;
52 }
53 
54 $projectid = GETPOSTISSET("id") ? GETPOSTINT("id", 1) : GETPOSTINT("projectid");
55 
56 $hookmanager->initHooks(array('timesheetperdaycard'));
57 
58 // Security check
59 $socid = 0;
60 // For external user, no check is done on company because readability is managed by public status of project and assignment.
61 //if ($user->socid > 0) $socid=$user->socid;
62 $result = restrictedArea($user, 'projet', $projectid);
63 
64 $now = dol_now();
65 
66 $year = GETPOSTINT('reyear') ? GETPOSTINT('reyear') : (GETPOSTINT("year") ? GETPOSTINT("year") : (GETPOSTINT("addtimeyear") ? GETPOSTINT("addtimeyear") : date("Y")));
67 $month = GETPOSTINT('remonth') ? GETPOSTINT('remonth') : (GETPOSTINT("month") ? GETPOSTINT("month") : (GETPOSTINT("addtimemonth") ? GETPOSTINT("addtimemonth") : date("m")));
68 $day = GETPOSTINT('reday') ? GETPOSTINT('reday') : (GETPOSTINT("day") ? GETPOSTINT("day") : (GETPOSTINT("addtimeday") ? GETPOSTINT("addtimeday") : date("d")));
69 $week = GETPOSTINT("week") ? GETPOSTINT("week") : date("W");
70 
71 $day = (int) $day;
72 
73 //$search_categ = GETPOST("search_categ", 'alpha');
74 $search_usertoprocessid = GETPOSTINT('search_usertoprocessid');
75 $search_task_ref = GETPOST('search_task_ref', 'alpha');
76 $search_task_label = GETPOST('search_task_label', 'alpha');
77 $search_project_ref = GETPOST('search_project_ref', 'alpha');
78 $search_thirdparty = GETPOST('search_thirdparty', 'alpha');
79 $search_declared_progress = GETPOST('search_declared_progress', 'alpha');
80 
81 $sortfield = GETPOST('sortfield', 'aZ09comma');
82 $sortorder = GETPOST('sortorder', 'aZ09comma');
83 
84 $monthofday = GETPOST('addtimemonth');
85 $dayofday = GETPOST('addtimeday');
86 $yearofday = GETPOST('addtimeyear');
87 
88 //var_dump(GETPOST('remonth'));
89 //var_dump(GETPOST('button_search_x'));
90 //var_dump(GETPOST('button_addtime'));
91 
92 $daytoparse = $now;
93 if ($year && $month && $day) {
94  $daytoparse = dol_mktime(0, 0, 0, $month, $day, $year); // this are value submitted after submit of action 'submitdateselect'
95 } elseif ($yearofday && $monthofday && $dayofday) {
96  $daytoparse = dol_mktime(0, 0, 0, $monthofday, $dayofday, $yearofday); // xxxofday is value of day after submit action 'addtime'
97 }
98 
99 $daytoparsegmt = dol_now('gmt');
100 if ($yearofday && $monthofday && $dayofday) {
101  $daytoparsegmt = dol_mktime(0, 0, 0, $monthofday, $dayofday, $yearofday, 'gmt');
102 } elseif ($year && $month && $day) { // xxxofday is value of day after submit action 'addtime'
103  $daytoparsegmt = dol_mktime(0, 0, 0, $month, $day, $year, 'gmt');
104 } // this are value submitted after submit of action 'submitdateselect'
105 
106 if (empty($search_usertoprocessid) || $search_usertoprocessid == $user->id) {
107  $usertoprocess = $user;
108  $search_usertoprocessid = $usertoprocess->id;
109 } elseif ($search_usertoprocessid > 0) {
110  $usertoprocess = new User($db);
111  $usertoprocess->fetch($search_usertoprocessid);
112  $search_usertoprocessid = $usertoprocess->id;
113 } else {
114  $usertoprocess = new User($db);
115 }
116 
117 $object = new Task($db);
118 $project = new Project($db);
119 
120 // Extra fields
121 $extrafields = new ExtraFields($db);
122 
123 // fetch optionals attributes and labels
124 $extrafields->fetch_name_optionals_label($object->table_element);
125 
126 // Definition of fields for list
127 $arrayfields = array();
128 $arrayfields['t.planned_workload'] = array('label' => 'PlannedWorkload', 'checked' => 1, 'enabled' => 1, 'position' => 0);
129 $arrayfields['t.progress'] = array('label' => 'ProgressDeclared', 'checked' => 1, 'enabled' => 1, 'position' => 0);
130 $arrayfields['timeconsumed'] = array('label' => 'TimeConsumed', 'checked' => 1, 'enabled' => 1, 'position' => 15);
131 /*$arrayfields=array(
132  // Project
133  'p.opp_amount'=>array('label'=>$langs->trans("OpportunityAmountShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>103),
134  'p.fk_opp_status'=>array('label'=>$langs->trans("OpportunityStatusShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>104),
135  'p.opp_percent'=>array('label'=>$langs->trans("OpportunityProbabilityShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>105),
136  'p.budget_amount'=>array('label'=>$langs->trans("Budget"), 'checked'=>0, 'position'=>110),
137  'p.usage_bill_time'=>array('label'=>$langs->trans("BillTimeShort"), 'checked'=>0, 'position'=>115),
138  );
139  */
140 // Extra fields
141 if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) {
142  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
143  if (!empty($extrafields->attributes[$object->table_element]['list'][$key])) {
144  $arrayfields["efpt.".$key] = array('label' => $extrafields->attributes[$object->table_element]['label'][$key], 'checked' => (($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1), 'position' => $extrafields->attributes[$object->table_element]['pos'][$key], 'enabled' => (abs((int) $extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key]));
145  }
146  }
147 }
148 $arrayfields = dol_sort_array($arrayfields, 'position');
149 
150 
151 $search_array_options_project = $extrafields->getOptionalsFromPost($project->table_element, '', 'search_');
152 $search_array_options_task = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_task_');
153 
154 
155 /*
156  * Actions
157  */
158 
159 $parameters = array('id' => $id, 'taskid' => $taskid, 'projectid' => $projectid);
160 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
161 if ($reshook < 0) {
162  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
163 }
164 // Purge criteria
165 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
166  $action = '';
167  //$search_categ = '';
168  $search_usertoprocessid = $user->id;
169  $search_task_ref = '';
170  $search_task_label = '';
171  $search_project_ref = '';
172  $search_thirdparty = '';
173  $search_declared_progress = '';
174 
175  $search_array_options_project = array();
176  $search_array_options_task = array();
177 
178  // We redefine $usertoprocess
179  $usertoprocess = $user;
180 }
181 if (GETPOST("button_search_x", 'alpha') || GETPOST("button_search.x", 'alpha') || GETPOST("button_search", 'alpha')) {
182  $action = '';
183 }
184 
185 if (GETPOST('submitdateselect')) {
186  if (GETPOSTINT('remonth') && GETPOSTINT('reday') && GETPOSTINT('reyear')) {
187  $daytoparse = dol_mktime(0, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
188  }
189 
190  $action = '';
191 }
192 
193 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
194 
195 if ($action == 'addtime' && $user->hasRight('projet', 'lire') && GETPOST('assigntask') && GETPOST('formfilteraction') != 'listafterchangingselectedfields') {
196  $action = 'assigntask';
197 
198  if ($taskid > 0) {
199  $result = $object->fetch($taskid, $ref);
200  if ($result < 0) {
201  $error++;
202  }
203  } else {
204  setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), null, 'errors');
205  $error++;
206  }
207  if (!GETPOST('type')) {
208  setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
209  $error++;
210  }
211  if (!$error) {
212  $idfortaskuser = $usertoprocess->id;
213  $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal');
214 
215  if ($result >= 0 || $result == -2) { // Contact add ok or already contact of task
216  // Test if we are already contact of the project (should be rare but sometimes we can add as task contact without being contact of project, like when admin user has been removed from contact of project)
217  $sql = 'SELECT ec.rowid FROM '.MAIN_DB_PREFIX.'element_contact as ec, '.MAIN_DB_PREFIX.'c_type_contact as tc WHERE tc.rowid = ec.fk_c_type_contact';
218  $sql .= ' AND ec.fk_socpeople = '.((int) $idfortaskuser)." AND ec.element_id = ".((int) $object->fk_project)." AND tc.element = 'project' AND source = 'internal'";
219  $resql = $db->query($sql);
220  if ($resql) {
221  $obj = $db->fetch_object($resql);
222  if (!$obj) { // User is not already linked to project, so we will create link to first type
223  $project = new Project($db);
224  $project->fetch($object->fk_project);
225  // Get type
226  $listofprojcontact = $project->liste_type_contact('internal');
227 
228  if (count($listofprojcontact)) {
229  $tmparray = array_keys($listofprojcontact);
230  $typeforprojectcontact = reset($tmparray);
231  $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal');
232  }
233  }
234  } else {
235  dol_print_error($db);
236  }
237  }
238  }
239 
240  if ($result < 0) {
241  $error++;
242  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
243  $langs->load("errors");
244  setEventMessages($langs->trans("ErrorTaskAlreadyAssigned"), null, 'warnings');
245  } else {
246  setEventMessages($object->error, $object->errors, 'errors');
247  }
248  }
249 
250  if (!$error) {
251  setEventMessages("TaskAssignedToEnterTime", null);
252  $taskid = 0;
253  }
254 
255  $action = '';
256 }
257 
258 if ($action == 'addtime' && $user->hasRight('projet', 'lire') && GETPOST('formfilteraction') != 'listafterchangingselectedfields') {
259  $timespent_duration = array();
260 
261  if (is_array($_POST)) {
262  foreach ($_POST as $key => $time) {
263  if (intval($time) > 0) {
264  $matches = array();
265  // Hours or minutes of duration
266  if (preg_match("/([0-9]+)duration(hour|min)/", $key, $matches)) {
267  $id = $matches[1];
268  if ($id > 0) {
269  // We store HOURS in seconds
270  if ($matches[2] == 'hour') {
271  $timespent_duration[$id] += $time * 60 * 60;
272  }
273 
274  // We store MINUTES in seconds
275  if ($matches[2] == 'min') {
276  $timespent_duration[$id] += $time * 60;
277  }
278  }
279  }
280  }
281  }
282  }
283 
284  if (count($timespent_duration) > 0) {
285  foreach ($timespent_duration as $key => $val) {
286  $object->fetch($key);
287  $taskid = $object->id;
288 
289  if (GETPOSTISSET($taskid.'progress')) {
290  $object->progress = GETPOSTINT($taskid.'progress');
291  } else {
292  unset($object->progress);
293  }
294 
295  $object->timespent_duration = $val;
296  $object->timespent_fk_user = $usertoprocess->id;
297  $object->timespent_note = GETPOST($key.'note');
298  if (GETPOSTINT($key."hour") != '' && GETPOSTINT($key."hour") >= 0) { // If hour was entered
299  $object->timespent_datehour = dol_mktime(GETPOSTINT($key."hour"), GETPOSTINT($key."min"), 0, $monthofday, $dayofday, $yearofday);
300  $object->timespent_withhour = 1;
301  } else {
302  $object->timespent_datehour = dol_mktime(12, 0, 0, $monthofday, $dayofday, $yearofday);
303  }
304  $object->timespent_date = $object->timespent_datehour;
305 
306  if ($object->timespent_date > 0) {
307  $result = $object->addTimeSpent($user);
308  } else {
309  setEventMessages("ErrorBadDate", null, 'errors');
310  $error++;
311  break;
312  }
313 
314  if ($result < 0) {
315  setEventMessages($object->error, $object->errors, 'errors');
316  $error++;
317  break;
318  }
319  }
320 
321  if (!$error) {
322  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
323 
324  // Redirect to avoid submit twice on back
325  header('Location: '.$_SERVER["PHP_SELF"].'?'.($projectid ? 'id='.$projectid : '').($search_usertoprocessid ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : '').($mode ? '&mode='.$mode : '').'&year='.$yearofday.'&month='.$monthofday.'&day='.$dayofday);
326  exit;
327  }
328  } else {
329  setEventMessages($langs->trans("ErrorTimeSpentIsEmpty"), null, 'errors');
330  }
331 }
332 
333 
334 
335 /*
336  * View
337  */
338 
339 $form = new Form($db);
340 $formother = new FormOther($db);
341 $formcompany = new FormCompany($db);
342 $formproject = new FormProjets($db);
343 $projectstatic = new Project($db);
344 $project = new Project($db);
345 $taskstatic = new Task($db);
346 $thirdpartystatic = new Societe($db);
347 $holiday = new Holiday($db);
348 
349 $prev = dol_getdate($daytoparse - (24 * 3600));
350 $prev_year = $prev['year'];
351 $prev_month = $prev['mon'];
352 $prev_day = $prev['mday'];
353 
354 $next = dol_getdate($daytoparse + (24 * 3600));
355 $next_year = $next['year'];
356 $next_month = $next['mon'];
357 $next_day = $next['mday'];
358 
359 $title = $langs->trans("TimeSpent");
360 
361 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertoprocess, (empty($usertoprocess->id) ? 2 : 0), 1); // Return all project i have permission on (assigned to me+public). I want my tasks and some of my task may be on a public projet that is not my project
362 
363 if ($id) {
364  $project->fetch($id);
365  $project->fetch_thirdparty();
366 }
367 
368 $onlyopenedproject = 1; // or -1
369 $morewherefilter = '';
370 
371 if ($search_project_ref) {
372  $morewherefilter .= natural_search(array("p.ref", "p.title"), $search_project_ref);
373 }
374 if ($search_task_ref) {
375  $morewherefilter .= natural_search("t.ref", $search_task_ref);
376 }
377 if ($search_task_label) {
378  $morewherefilter .= natural_search(array("t.ref", "t.label"), $search_task_label);
379 }
380 if ($search_thirdparty) {
381  $morewherefilter .= natural_search("s.nom", $search_thirdparty);
382 }
383 if ($search_declared_progress) {
384  $morewherefilter .= natural_search("t.progress", $search_declared_progress, 1);
385 }
386 
387 $sql = &$morewherefilter;
388 
389 /*$search_array_options = $search_array_options_project;
390 $extrafieldsobjectprefix='efp.';
391 $search_options_pattern='search_options_';
392 $extrafieldsobjectkey='projet';
393 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
394 */
395 $search_array_options = $search_array_options_task;
396 $extrafieldsobjectprefix = 'efpt.';
397 $search_options_pattern = 'search_task_options_';
398 $extrafieldsobjectkey = 'projet_task';
399 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
400 
401 $tasksarray = $taskstatic->getTasksArray(0, 0, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0), 0, $extrafields); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later.
402 if ($morewherefilter) { // Get all task without any filter, so we can show total of time spent for not visible tasks
403  $tasksarraywithoutfilter = $taskstatic->getTasksArray(0, 0, ($project->id ? $project->id : 0), $socid, 0, '', $onlyopenedproject, '', ($search_usertoprocessid ? $search_usertoprocessid : 0)); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later.
404 }
405 $projectsrole = $taskstatic->getUserRolesForProjectsOrTasks($usertoprocess, null, ($project->id ? $project->id : 0), 0, $onlyopenedproject);
406 $tasksrole = $taskstatic->getUserRolesForProjectsOrTasks(null, $usertoprocess, ($project->id ? $project->id : 0), 0, $onlyopenedproject);
407 //var_dump($usertoprocess);
408 //var_dump($projectsrole);
409 //var_dump($taskrole);
410 
411 llxHeader("", $title, "", '', '', '', array('/core/js/timesheet.js'));
412 
413 //print_barre_liste($title, $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, "", $num, '', 'project');
414 
415 $param = '';
416 $param .= ($mode ? '&mode='.urlencode($mode) : '');
417 $param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : '');
418 $param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : '');
419 $param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : '');
420 $param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : '');
421 $param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : '');
422 
423 /*
424 $search_array_options = $search_array_options_project;
425 $search_options_pattern='search_options_';
426 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
427 */
428 
429 $search_array_options = $search_array_options_task;
430 $search_options_pattern = 'search_task_options_';
431 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
432 
433 // Show navigation bar
434 $nav = '<a class="inline-block valignmiddle" href="?year='.$prev_year."&month=".$prev_month."&day=".$prev_day.$param.'">'.img_previous($langs->trans("Previous"))."</a>\n";
435 $nav .= dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "%a").' ';
436 $nav .= ' <span id="month_name">'.dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "day")." </span>\n";
437 $nav .= '<a class="inline-block valignmiddle" href="?year='.$next_year."&month=".$next_month."&day=".$next_day.$param.'">'.img_next($langs->trans("Next"))."</a>\n";
438 $nav .= ' '.$form->selectDate(-1, '', 0, 0, 2, "addtime", 1, 1).' ';
439 $nav .= ' <button type="submit" name="button_search_x" value="x" class="bordertransp nobordertransp button_search"><span class="fa fa-search"></span></button>';
440 
441 $picto = 'clock';
442 
443 print '<form name="addtime" method="POST" action="'.$_SERVER["PHP_SELF"].($project->id > 0 ? '?id='.$project->id : '').'">';
444 print '<input type="hidden" name="token" value="'.newToken().'">';
445 print '<input type="hidden" name="action" value="addtime">';
446 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
447 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
448 print '<input type="hidden" name="mode" value="'.$mode.'">';
449 $tmp = dol_getdate($daytoparse);
450 print '<input type="hidden" name="addtimeyear" value="'.$tmp['year'].'">';
451 print '<input type="hidden" name="addtimemonth" value="'.$tmp['mon'].'">';
452 print '<input type="hidden" name="addtimeday" value="'.$tmp['mday'].'">';
453 
454 $head = project_timesheet_prepare_head($mode, $usertoprocess);
455 print dol_get_fiche_head($head, 'inputperday', $langs->trans('TimeSpent'), -1, $picto);
456 
457 // Show description of content
458 print '<div class="hideonsmartphone opacitymedium">';
459 if ($mine || ($usertoprocess->id == $user->id)) {
460  print $langs->trans("MyTasksDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
461 } else {
462  if (empty($usertoprocess->id) || $usertoprocess->id < 0) {
463  if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
464  print $langs->trans("ProjectsDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
465  } else {
466  print $langs->trans("ProjectsPublicTaskDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'<br>';
467  }
468  }
469 }
470 if ($mine || ($usertoprocess->id == $user->id)) {
471  print $langs->trans("OnlyYourTaskAreVisible").'<br>';
472 } else {
473  print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'<br>';
474 }
475 print '</div>';
476 
477 print dol_get_fiche_end();
478 
479 
480 print '<div class="'.($conf->dol_optimize_smallscreen ? 'center centpercent' : 'floatright right').'">'.$nav.'</div>'; // We move this before the assign to components so, the default submit button is not the assign to.
481 
482 print '<div class="colorbacktimesheet valignmiddle'.($conf->dol_optimize_smallscreen ? ' center' : ' float').'">';
483 $titleassigntask = $langs->transnoentities("AssignTaskToMe");
484 if ($usertoprocess->id != $user->id) {
485  $titleassigntask = $langs->transnoentities("AssignTaskToUser", $usertoprocess->getFullName($langs));
486 }
487 print '<div class="taskiddiv inline-block">';
488 print img_picto('', 'projecttask', 'class="pictofixedwidth"');
489 $formproject->selectTasks($socid ? $socid : -1, $taskid, 'taskid', 32, 0, '-- '.$langs->trans("ChooseANotYetAssignedTask").' --', 1, 0, 0, 'widthcentpercentminusx', '', 'all', $usertoprocess);
490 print '</div>';
491 print ' ';
492 print $formcompany->selectTypeContact($object, '', 'type', 'internal', 'position', 0, 'maxwidth150onsmartphone');
493 print '<input type="submit" class="button valignmiddle smallonsmartphone small" name="assigntask" value="'.dol_escape_htmltag($titleassigntask).'">';
494 print '</div>';
495 
496 print '<div class="clearboth" style="padding-bottom: 20px;"></div>';
497 
498 
499 $moreforfilter = '';
500 
501 // Filter on categories
502 /*if (isModEnabled("categorie")) {
503  require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
504  $moreforfilter.='<div class="divsearchfield">';
505  $moreforfilter.=$langs->trans('ProjectCategories'). ': ';
506  $moreforfilter.=$formother->select_categories('project', $search_categ, 'search_categ', 1, 1, 'maxwidth300');
507  $moreforfilter.='</div>';
508 }*/
509 
510 // If the user can view user other than himself
511 $moreforfilter .= '<div class="divsearchfield">';
512 $moreforfilter .= '<div class="inline-block hideonsmartphone"></div>';
513 $includeonly = 'hierarchyme';
514 if (!$user->hasRight('user', 'user', 'lire')) {
515  $includeonly = array($user->id);
516 }
517 $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('User'), 'user', 'class="paddingright pictofixedwidth"').$form->select_dolusers($search_usertoprocessid ? $search_usertoprocessid : $usertoprocess->id, 'search_usertoprocessid', 0, null, 0, $includeonly, null, 0, 0, 0, '', 0, '', 'maxwidth200');
518 $moreforfilter .= '</div>';
519 
520 if (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
521  $moreforfilter .= '<div class="divsearchfield">';
522  $moreforfilter .= '<div class="inline-block"></div>';
523  $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('Project'), 'project', 'class="paddingright pictofixedwidth"').'<input type="text" name="search_project_ref" class="maxwidth100" value="'.dol_escape_htmltag($search_project_ref).'">';
524  $moreforfilter .= '</div>';
525 
526  $moreforfilter .= '<div class="divsearchfield">';
527  $moreforfilter .= '<div class="inline-block"></div>';
528  $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('ThirdParty'), 'company', 'class="paddingright pictofixedwidth"').'<input type="text" name="search_thirdparty" class="maxwidth100" value="'.dol_escape_htmltag($search_thirdparty).'">';
529  $moreforfilter .= '</div>';
530 }
531 
532 if (!empty($moreforfilter)) {
533  print '<div class="liste_titre liste_titre_bydiv centpercent">';
534  print $moreforfilter;
535  $parameters = array();
536  $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
537  print $hookmanager->resPrint;
538  print '</div>';
539 }
540 
541 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
542 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
543 
544 // This must be after the $selectedfields
545 $addcolspan = 0;
546 if (!empty($arrayfields['t.planned_workload']['checked'])) {
547  $addcolspan++;
548 }
549 if (!empty($arrayfields['t.progress']['checked'])) {
550  $addcolspan++;
551 }
552 foreach ($arrayfields as $key => $val) {
553  if ($val['checked'] && substr($key, 0, 5) == 'efpt.') {
554  $addcolspan++;
555  }
556 }
557 
558 print '<div class="div-table-responsive">';
559 print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'" id="tablelines3">'."\n";
560 
561 print '<tr class="liste_titre_filter">';
562 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
563  print '<td class="liste_titre"><input type="text" size="4" name="search_project_ref" value="'.dol_escape_htmltag($search_project_ref).'"></td>';
564 }
565 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
566  print '<td class="liste_titre"><input type="text" size="4" name="search_thirdparty" value="'.dol_escape_htmltag($search_thirdparty).'"></td>';
567 }
568 print '<td class="liste_titre"><input type="text" size="4" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'"></td>';
569 // TASK fields
570 $search_options_pattern = 'search_task_options_';
571 $extrafieldsobjectkey = 'projet_task';
572 $extrafieldsobjectprefix = 'efpt.';
573 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
574 if (!empty($arrayfields['t.planned_workload']['checked'])) {
575  print '<td class="liste_titre"></td>';
576 }
577 if (!empty($arrayfields['t.progress']['checked'])) {
578  print '<td class="liste_titre right"><input type="text" size="4" name="search_declared_progress" value="'.dol_escape_htmltag($search_declared_progress).'"></td>';
579 }
580 if (!empty($arrayfields['timeconsumed']['checked'])) {
581  print '<td class="liste_titre"></td>';
582  print '<td class="liste_titre"></td>';
583 }
584 print '<td class="liste_titre"></td>';
585 print '<td class="liste_titre"></td>';
586 print '<td class="liste_titre"></td>';
587 // Action column
588 print '<td class="liste_titre nowrap right">';
589 $searchpicto = $form->showFilterAndCheckAddButtons(0);
590 print $searchpicto;
591 print '</td>';
592 print "</tr>\n";
593 
594 print '<tr class="liste_titre">';
595 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
596  print '<th>'.$langs->trans("Project").'</th>';
597 }
598 if (getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT')) {
599  print '<th>'.$langs->trans("ThirdParty").'</th>';
600 }
601 print '<th>'.$langs->trans("Task").'</th>';
602 // TASK fields
603 $extrafieldsobjectkey = 'projet_task';
604 $extrafieldsobjectprefix = 'efpt.';
605 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
606 if (!empty($arrayfields['t.planned_workload']['checked'])) {
607  print '<th class="leftborder plannedworkload minwidth75 maxwidth100 right" title="'.dol_escape_htmltag($langs->trans("PlannedWorkload")).'">'.$langs->trans("PlannedWorkload").'</th>';
608 }
609 if (!empty($arrayfields['t.progress']['checked'])) {
610  print '<th class="right minwidth75 maxwidth100 title="'.dol_escape_htmltag($langs->trans("ProgressDeclared")).'">'.$langs->trans("ProgressDeclared").'</th>';
611 }
612 if (!empty($arrayfields['timeconsumed']['checked'])) {
613  print '<th class="right maxwidth100">'.$langs->trans("TimeSpentSmall").'<br>';
614  print '<span class="nowraponall">';
615  print '<span class="opacitymedium nopadding userimg"><img alt="Photo" class="photouserphoto userphoto" src="'.DOL_URL_ROOT.'/theme/common/everybody.png"></span>';
616  print '<span class="opacitymedium paddingleft">'.$langs->trans("EverybodySmall").'</span>';
617  print '</span>';
618  print '</th>';
619  print '<th class="right maxwidth75 maxwidth100">'.$langs->trans("TimeSpentSmall").($usertoprocess->firstname ? '<br><span class="nowraponall">'.$usertoprocess->getNomUrl(-2).'<span class="opacitymedium paddingleft">'.dol_trunc($usertoprocess->firstname, 10).'</span></span>' : '').'</th>';
620 }
621 print '<th class="center leftborder">'.$langs->trans("HourStart").'</td>';
622 
623 // By default, we can edit only tasks we are assigned to
624 $restrictviewformytask = ((!isset($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED)) ? 2 : $conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED);
625 
626 $numendworkingday = 0;
627 $numstartworkingday = 0;
628 // Get if user is available or not for each day
629 $isavailable = array();
630 
631 // Assume from Monday to Friday if conf empty or badly formed
632 $numstartworkingday = 1;
633 $numendworkingday = 5;
634 
635 if (getDolGlobalString('MAIN_DEFAULT_WORKING_DAYS')) {
636  $tmparray = explode('-', getDolGlobalString('MAIN_DEFAULT_WORKING_DAYS'));
637  if (count($tmparray) >= 2) {
638  $numstartworkingday = $tmparray[0];
639  $numendworkingday = $tmparray[1];
640  }
641 }
642 
643 $statusofholidaytocheck = Holiday::STATUS_APPROVED;
644 $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($usertoprocess->id, $daytoparse, $statusofholidaytocheck); // $daytoparse is a date with hours = 0
645 $isavailable[$daytoparse] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day
646 
647 $test = num_public_holiday($daytoparsegmt, $daytoparsegmt + 86400, $mysoc->country_code);
648 if ($test) {
649  $isavailable[$daytoparse] = array('morning' => false, 'afternoon' => false, 'morning_reason' => 'public_holiday', 'afternoon_reason' => 'public_holiday');
650 }
651 
652 $tmparray = dol_getdate($daytoparse, true); // detail of current day
653 // For monday, must be 0 for monday if MAIN_START_WEEK = 1, must be 1 for monday if MAIN_START_WEEK = 0
654 $idw = ($tmparray['wday'] - (!getDolGlobalString('MAIN_START_WEEK') ? 0 : 1));
655 // numstartworkingday and numendworkingday are default start and end date of working days (1 means sunday if MAIN_START_WEEK is 0, 1 means monday if MAIN_START_WEEK is 1)
656 $cssweekend = '';
657 if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css.
658  $cssweekend = 'weekend';
659 }
660 
661 $tmpday = dol_time_plus_duree($daytoparse, $idw, 'd');
662 
663 $cssonholiday = '';
664 if (!$isavailable[$daytoparse]['morning'] && !$isavailable[$daytoparse]['afternoon']) {
665  $cssonholiday .= 'onholidayallday ';
666 } elseif (!$isavailable[$daytoparse]['morning']) {
667  $cssonholiday .= 'onholidaymorning ';
668 } elseif (!$isavailable[$daytoparse]['afternoon']) {
669  $cssonholiday .= 'onholidayafternoon ';
670 }
671 
672 print '<th class="center'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'">'.$langs->trans("Duration").'</th>';
673 print '<th class="center">'.$langs->trans("Note").'</th>';
674 //print '<td class="center"></td>';
675 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
676 
677 print "</tr>\n";
678 
679 $colspan = 2 + (!getDolGlobalString('PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT') ? 0 : 2);
680 
681 if ($conf->use_javascript_ajax) {
682  print '<tr class="liste_total">';
683  print '<td class="liste_total" colspan="'.($colspan - 1 + $addcolspan).'">';
684  print $langs->trans("Total");
685  print '</td>';
686  if (!empty($arrayfields['timeconsumed']['checked'])) {
687  print '<td class="liste_total"></td>';
688  print '<td class="liste_total"></td>';
689  }
690  print '<td class="liste_total leftborder">';
691  //print ' - '.$langs->trans("ExpectedWorkedHours").': <strong>'.price($usertoprocess->weeklyhours, 1, $langs, 0, 0).'</strong>';
692  print '</td>';
693 
694  print '<td class="liste_total center'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'"><div class="totalDay0">&nbsp;</div></td>';
695 
696  print '<td class="liste_total"></td>';
697  print '<td class="liste_total"></td>';
698  print '</tr>';
699 }
700 
701 
702 if (count($tasksarray) > 0) {
703  //var_dump($tasksarray); // contains only selected tasks
704  //var_dump($tasksarraywithoutfilter); // contains all tasks (if there is a filter, not defined if no filter)
705  //var_dump($tasksrole);
706 
707  $j = 0;
708  $level = 0;
709  $totalforvisibletasks = projectLinesPerDay($j, 0, $usertoprocess, $tasksarray, $level, $projectsrole, $tasksrole, $mine, $restrictviewformytask, $daytoparse, $isavailable, 0, $arrayfields, $extrafields);
710  //var_dump($totalforvisibletasks);
711 
712  // Show total for all other tasks
713 
714  // Calculate total for all tasks
715  $listofdistinctprojectid = array(); // List of all distinct projects
716  if (!empty($tasksarraywithoutfilter) && is_array($tasksarraywithoutfilter) && count($tasksarraywithoutfilter)) {
717  foreach ($tasksarraywithoutfilter as $tmptask) {
718  $listofdistinctprojectid[$tmptask->fk_project] = $tmptask->fk_project;
719  }
720  }
721  //var_dump($listofdistinctprojectid);
722  $totalforeachday = array();
723  foreach ($listofdistinctprojectid as $tmpprojectid) {
724  $projectstatic->id = $tmpprojectid;
725  $projectstatic->loadTimeSpent($daytoparse, 0, $usertoprocess->id); // Load time spent from table element_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week
726  for ($idw = 0; $idw < 7; $idw++) {
727  $tmpday = dol_time_plus_duree($daytoparse, $idw, 'd');
728  $totalforeachday[$tmpday] += $projectstatic->weekWorkLoad[$tmpday];
729  }
730  }
731  //var_dump($totalforeachday);
732 
733  // Is there a diff between selected/filtered tasks and all tasks ?
734  $isdiff = 0;
735  if (count($totalforeachday)) {
736  $timeonothertasks = ($totalforeachday[$daytoparse] - $totalforvisibletasks[$daytoparse]);
737  if ($timeonothertasks) {
738  $isdiff = 1;
739  }
740  }
741 
742  // There is a diff between total shown on screen and total spent by user, so we add a line with all other cumulated time of user
743  if ($isdiff) {
744  print '<tr class="oddeven othertaskwithtime">';
745  print '<td colspan="'.($colspan - 1).'" class="opacitymedium">';
746  print $langs->trans("OtherFilteredTasks");
747  print '</td>';
748  if (!empty($arrayfields['timeconsumed']['checked'])) {
749  print '<td class="liste_total"></td>';
750  print '<td class="liste_total"></td>';
751  }
752  print '<td class="leftborder"></td>';
753  print '<td class="center">';
754  $timeonothertasks = ($totalforeachday[$daytoparse] - $totalforvisibletasks[$daytoparse]);
755  //if ($timeonothertasks)
756  //{
757  print '<span class="timesheetalreadyrecorded" title="texttoreplace"><input type="text" class="center width40" disabled="" id="timespent[-1][0]" name="task[-1][0]" value="';
758  if ($timeonothertasks) {
759  print convertSecondToTime($timeonothertasks, 'allhourmin');
760  }
761  print '"></span>';
762  //}
763  print '</td>';
764  print ' <td class="liste_total"></td>';
765  print ' <td class="liste_total"></td>';
766  print '</tr>';
767  }
768 
769  if ($conf->use_javascript_ajax) {
770  print '<tr class="liste_total">';
771  print '<td class="liste_total" colspan="'.($colspan - 1 + $addcolspan).'">';
772  print $langs->trans("Total");
773  print '</td>';
774  if (!empty($arrayfields['timeconsumed']['checked'])) {
775  print '<td class="liste_total"></td>';
776  print '<td class="liste_total"></td>';
777  }
778  print '<td class="liste_total leftborder">';
779  //print ' - '.$langs->trans("ExpectedWorkedHours").': <strong>'.price($usertoprocess->weeklyhours, 1, $langs, 0, 0).'</strong>';
780  print '</td>';
781 
782  print '<td class="liste_total center'.($cssonholiday ? ' '.$cssonholiday : '').($cssweekend ? ' '.$cssweekend : '').'"><div class="totalDay0">&nbsp;</div></td>';
783 
784  print '<td class="liste_total"></td>
785  <td class="liste_total"></td>
786  </tr>';
787  }
788 } else {
789  print '<tr><td colspan="14"><span class="opacitymedium">'.$langs->trans("NoAssignedTasks").'</span></td></tr>';
790 }
791 print "</table>";
792 print '</div>';
793 
794 print '<input type="hidden" id="numberOfLines" name="numberOfLines" value="'.count($tasksarray).'"/>'."\n";
795 
796 print '<div class="center">';
797 print '<input type="submit" name="button_addtime" class="button button-save"'.(!empty($disabledtask) ? ' disabled' : '').' value="'.$langs->trans("Save").'">';
798 print '</div>';
799 
800 print '</form>';
801 
802 if (!empty($conf->use_javascript_ajax)) {
803  $modeinput = 'hours';
804  print "\n<!-- JS CODE TO ENABLE Tooltips on all object with class classfortooltip -->\n";
805  print '<script type="text/javascript">'."\n";
806  print "jQuery(document).ready(function () {\n";
807  print " updateTotal(0, '".dol_escape_js($modeinput)."');\n";
808  print ' jQuery(".timesheetalreadyrecorded").tooltip({
809  show: { collision: "flipfit", effect:\'toggle\', delay:50 },
810  hide: { effect:\'toggle\', delay: 50 },
811  tooltipClass: "mytooltip",
812  content: function () {
813  return \''.dol_escape_js($langs->trans("TimeAlreadyRecorded", $usertoprocess->getFullName($langs))).'\';
814  }
815  });'."\n";
816  print " jQuery('.inputhour, .inputminute').bind('keyup', function(e) { updateTotal(0, '".dol_escape_js($modeinput)."') });";
817  print "\n});\n";
818  print '</script>';
819 }
820 
821 // End of page
822 llxFooter();
823 $db->close();
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:55
Class to manage standard extra fields.
Class to build HTML component for third parties management Only common components are here.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation de composants html autre Only common components are here.
Class to manage building of HTML components.
Class of the module paid holiday.
const STATUS_APPROVED
Approved.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Definition: task.class.php:41
Class to manage Dolibarr users.
Definition: user.class.php:50
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition: date.lib.php:124
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition: date.lib.php:242
num_public_holiday($timestampStart, $timestampEnd, $country_code='', $lastday=0, $includesaturday=-1, $includesunday=-1, $includefriday=-1, $includemonday=-1)
Return the number of non working days including Friday, Saturday and Sunday (or not) between 2 dates ...
Definition: date.lib.php:764
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...
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
dol_now($mode='auto')
Return date for now.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
img_previous($titlealt='default', $moreatt='')
Show previous logo.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_next($titlealt='default', $moreatt='')
Show next logo.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
projectLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak=0, $arrayfields=array(), $extrafields=null)
Output a task line into a pertime input mode.
project_timesheet_prepare_head($mode, $fuser=null)
Prepare array with list of tabs.
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.