dolibarr 21.0.0-alpha
tasks.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28require "../main.inc.php";
29require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
30require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
31require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
35require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
36if (isModEnabled('category')) {
37 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
38}
39
40// Load translation files required by the page
41$langsLoad = array('projects', 'users', 'companies');
42if (isModEnabled('eventorganization')) {
43 $langsLoad[] = 'eventorganization';
44}
45
46$langs->loadLangs($langsLoad);
47
48$action = GETPOST('action', 'aZ09');
49$massaction = GETPOST('massaction', 'alpha');
50//$show_files = GETPOSTINT('show_files');
51$confirm = GETPOST('confirm', 'alpha');
52$cancel = GETPOST('cancel', 'aZ09');
53$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'projecttasklist';
54$backtopage = GETPOST('backtopage', 'alpha'); // if not set, a default page will be used
55//$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); // if not set, $backtopage will be used
56//$backtopagejsfields = GETPOST('backtopagejsfields', 'alpha');
57$optioncss = GETPOST('optioncss', 'aZ');
58$backtopage = GETPOST('backtopage', 'alpha');
59$toselect = GETPOST('toselect', 'array');
60
61$id = GETPOSTINT('id');
62$ref = GETPOST('ref', 'alpha');
63$taskref = GETPOST('taskref', 'alpha');
64
65// Load variable for pagination
66$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
67$sortfield = GETPOST('sortfield', 'aZ09comma');
68$sortorder = GETPOST('sortorder', 'aZ09comma');
69$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
70if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
71 $page = 0;
72} // If $page is not defined, or '' or -1 or if we click on clear filters
73$offset = $limit * $page;
74$pageprev = $page - 1;
75$pagenext = $page + 1;
76
77$search_user_id = GETPOSTINT('search_user_id');
78$search_taskref = GETPOST('search_taskref');
79$search_tasklabel = GETPOST('search_tasklabel');
80$search_taskdescription = GETPOST('search_taskdescription');
81$search_dtstartday = GETPOST('search_dtstartday');
82$search_dtstartmonth = GETPOST('search_dtstartmonth');
83$search_dtstartyear = GETPOST('search_dtstartyear');
84$search_dtendday = GETPOST('search_dtendday');
85$search_dtendmonth = GETPOST('search_dtendmonth');
86$search_dtendyear = GETPOST('search_dtendyear');
87$search_planedworkload = GETPOST('search_planedworkload');
88$search_timespend = GETPOST('search_timespend');
89$search_progresscalc = GETPOST('search_progresscalc');
90$search_progressdeclare = GETPOST('search_progressdeclare');
91$search_task_budget_amount = GETPOST('search_task_budget_amount');
92$search_task_billable = GETPOST('search_task_billable');
93
94$search_date_start_startmonth = GETPOSTINT('search_date_start_startmonth');
95$search_date_start_startyear = GETPOSTINT('search_date_start_startyear');
96$search_date_start_startday = GETPOSTINT('search_date_start_startday');
97$search_date_start_start = dol_mktime(0, 0, 0, $search_date_start_startmonth, $search_date_start_startday, $search_date_start_startyear); // Use tzserver
98$search_date_start_endmonth = GETPOSTINT('search_date_start_endmonth');
99$search_date_start_endyear = GETPOSTINT('search_date_start_endyear');
100$search_date_start_endday = GETPOSTINT('search_date_start_endday');
101$search_date_start_end = dol_mktime(23, 59, 59, $search_date_start_endmonth, $search_date_start_endday, $search_date_start_endyear); // Use tzserver
102
103$search_date_end_startmonth = GETPOSTINT('search_date_end_startmonth');
104$search_date_end_startyear = GETPOSTINT('search_date_end_startyear');
105$search_date_end_startday = GETPOSTINT('search_date_end_startday');
106$search_date_end_start = dol_mktime(0, 0, 0, $search_date_end_startmonth, $search_date_end_startday, $search_date_end_startyear); // Use tzserver
107$search_date_end_endmonth = GETPOSTINT('search_date_end_endmonth');
108$search_date_end_endyear = GETPOSTINT('search_date_end_endyear');
109$search_date_end_endday = GETPOSTINT('search_date_end_endday');
110$search_date_end_end = dol_mktime(23, 59, 59, $search_date_end_endmonth, $search_date_end_endday, $search_date_end_endyear); // Use tzserver
111
112//if (! $user->rights->projet->all->lire) $mine=1; // Special for projects
113
114$object = new Project($db);
115$taskstatic = new Task($db);
116$extrafields = new ExtraFields($db);
117
118include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
119if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($object, 'fetchComments') && empty($object->comments)) {
120 $object->fetchComments();
121}
122
123if ($id > 0 || !empty($ref)) {
124 // fetch optionals attributes and labels
125 $extrafields->fetch_name_optionals_label($object->table_element);
126}
127$extrafields->fetch_name_optionals_label($taskstatic->table_element);
128$search_array_options = $extrafields->getOptionalsFromPost($taskstatic->table_element, '', 'search_');
129
130
131// Default sort order (if not yet defined by previous GETPOST)
132/* if (!$sortfield) {
133 reset($object->fields); $sortfield="t.".key($object->fields);
134} // Set here default search field. By default 1st field in definition. Reset is required to avoid key() to return null.
135if (!$sortorder) {
136 $sortorder = "ASC";
137} */
138
139
140// Security check
141$socid = 0;
142
143// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
144$hookmanager->initHooks(array('projecttaskscard', 'globalcard'));
145
146//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignment.
147$result = restrictedArea($user, 'projet', $id, 'projet&project');
148
149$diroutputmassaction = $conf->project->dir_output.'/tasks/temp/massgeneration/'.$user->id;
150
151$progress = GETPOSTINT('progress');
152$budget_amount = GETPOSTFLOAT('budget_amount');
153$billable = (GETPOST('billable', 'aZ') == 'yes' ? 1 : 0);
154$label = GETPOST('label', 'alpha');
155$description = GETPOST('description', 'restricthtml');
156$planned_workloadhour = (GETPOSTISSET('planned_workloadhour') ? GETPOSTINT('planned_workloadhour') : '');
157$planned_workloadmin = (GETPOSTISSET('planned_workloadmin') ? GETPOSTINT('planned_workloadmin') : '');
158if (GETPOSTISSET('planned_workloadhour') || GETPOSTISSET('planned_workloadmin')) {
159 $planned_workload = (int) $planned_workloadhour * 3600 + (int) $planned_workloadmin * 60;
160} else {
161 $planned_workload = '';
162}
163
164// Definition of fields for list
165$arrayfields = array(
166 't.ref' => array('label' => "RefTask", 'checked' => 1, 'position' => 1),
167 't.label' => array('label' => "LabelTask", 'checked' => 1, 'position' => 2),
168 't.description' => array('label' => "Description", 'checked' => 0, 'position' => 3),
169 't.dateo' => array('label' => "DateStart", 'checked' => 1, 'position' => 4),
170 't.datee' => array('label' => "Deadline", 'checked' => 1, 'position' => 5),
171 't.planned_workload' => array('label' => "PlannedWorkload", 'checked' => 1, 'position' => 6),
172 't.duration_effective' => array('label' => "TimeSpent", 'checked' => 1, 'position' => 7),
173 't.progress_calculated' => array('label' => "ProgressCalculated", 'checked' => 1, 'position' => 8),
174 't.progress' => array('label' => "ProgressDeclared", 'checked' => 1, 'position' => 9),
175 't.progress_summary' => array('label' => "TaskProgressSummary", 'checked' => 1, 'position' => 10),
176 't.budget_amount' => array('label' => "Budget", 'checked' => 0, 'position' => 11),
177 'c.assigned' => array('label' => "TaskRessourceLinks", 'checked' => 1, 'position' => 12),
178);
179if ($object->usage_bill_time) {
180 $arrayfields['t.tobill'] = array('label' => $langs->trans("TimeToBill"), 'checked' => 0, 'position' => 11);
181 $arrayfields['t.billed'] = array('label' => $langs->trans("TimeBilled"), 'checked' => 0, 'position' => 12);
182 $arrayfields['t.billable'] = array('label' => $langs->trans("Billable"), 'checked' => 1, 'position' => 13);
183}
184
185// Extra fields
186$extrafieldsobjectkey = $taskstatic->table_element;
187$extrafieldsobjectprefix = 'efpt.';
188include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
189
190$arrayfields = dol_sort_array($arrayfields, 'position');
191'@phan-var-force array<string,array{label:string,checked?:int<0,1>,position?:int,help?:string}> $arrayfields'; // dol_sort_array looses type for Phan
192
193$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
194
195
196/*
197 * Actions
198 */
199
200if ($cancel) {
201 if (!empty($backtopageforcancel)) {
202 header("Location: ".$backtopageforcancel);
203 exit;
204 } elseif (!empty($backtopage)) {
205 header("Location: ".$backtopage);
206 exit;
207 }
208 $action = 'list';
209 $massaction = '';
210}
211if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
212 $massaction = '';
213}
214
215$parameters = array('id' => $id);
216$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
217if ($reshook < 0) {
218 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
219}
220
221if (empty($reshook)) {
222 // Selection of new fields
223 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
224
225 // Purge search criteria
226 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
227 $search_user_id = "";
228 $search_taskref = '';
229 $search_tasklabel = '';
230 $search_dtstartday = '';
231 $search_dtstartmonth = '';
232 $search_dtstartyear = '';
233 $search_dtendday = '';
234 $search_dtendmonth = '';
235 $search_dtendyear = '';
236 $search_planedworkload = '';
237 $search_timespend = '';
238 $search_progresscalc = '';
239 $search_progressdeclare = '';
240 $search_task_budget_amount = '';
241 $search_task_billable = '';
242 $toselect = array();
243 $search_array_options = array();
244 $search_date_start_startmonth = "";
245 $search_date_start_startyear = "";
246 $search_date_start_startday = "";
247 $search_date_start_start = "";
248 $search_date_start_endmonth = "";
249 $search_date_start_endyear = "";
250 $search_date_start_endday = "";
251 $search_date_start_end = "";
252 $search_date_end_startmonth = "";
253 $search_date_end_startyear = "";
254 $search_date_end_startday = "";
255 $search_date_end_start = "";
256 $search_date_end_endmonth = "";
257 $search_date_end_endyear = "";
258 $search_date_end_endday = "";
259 $search_date_end_end = "";
260 }
261
262 // Mass actions
263 $objectclass = 'Task';
264 $objectlabel = 'Tasks';
265 $permissiontoread = $user->hasRight('projet', 'lire');
266 $permissiontodelete = $user->hasRight('projet', 'supprimer');
267 $uploaddir = $conf->project->dir_output.'/tasks';
268 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
269}
270
271$morewherefilterarray = array();
272
273if (!empty($search_taskref)) {
274 $morewherefilterarray[] = natural_search('t.ref', $search_taskref, 0, 1);
275}
276
277if (!empty($search_tasklabel)) {
278 $morewherefilterarray[] = natural_search('t.label', $search_tasklabel, 0, 1);
279}
280
281$moresql = dolSqlDateFilter('t.dateo', $search_dtstartday, $search_dtstartmonth, $search_dtstartyear, 1);
282if ($moresql) {
283 $morewherefilterarray[] = $moresql;
284}
285
286$moresql = dolSqlDateFilter('t.datee', $search_dtendday, $search_dtendmonth, $search_dtendyear, 1);
287if ($moresql) {
288 $morewherefilterarray[] = $moresql;
289}
290
291if ($search_date_start_start) {
292 $morewherefilterarray[] = " t.dateo >= '".$db->idate($search_date_start_start)."'";
293}
294if ($search_date_start_end) {
295 $morewherefilterarray[] = " t.dateo <= '".$db->idate($search_date_start_end)."'";
296}
297
298if ($search_date_end_start) {
299 $morewherefilterarray[] = " t.datee >= '".$db->idate($search_date_end_start)."'";
300}
301if ($search_date_end_end) {
302 $morewherefilterarray[] = " t.datee <= '".$db->idate($search_date_end_end)."'";
303}
304
305if (!empty($search_planedworkload)) {
306 $morewherefilterarray[] = natural_search('t.planned_workload', $search_planedworkload, 1, 1);
307}
308
309if (!empty($search_timespend)) {
310 $morewherefilterarray[] = natural_search('t.duration_effective', $search_timespend, 1, 1);
311}
312
313if (!empty($search_progressdeclare)) {
314 $morewherefilterarray[] = natural_search('t.progress', $search_progressdeclare, 1, 1);
315}
316if (!empty($search_progresscalc)) {
317 $morewherefilterarray[] = '(planned_workload IS NULL OR planned_workload = 0 OR '.natural_search('ROUND(100 * duration_effective / planned_workload, 2)', $search_progresscalc, 1, 1).')';
318 //natural_search('round(100 * $line->duration_effective / $line->planned_workload,2)', $filterprogresscalc, 1, 1).' {return 1;} else {return 0;}';
319}
320if ($search_task_budget_amount) {
321 $morewherefilterarray[] = natural_search('t.budget_amount', $search_task_budget_amount, 1, 1);
322}
323if ($search_task_billable) {
324 $morewherefilterarray[] = " t.billable = ".($search_task_billable == "yes" ? 1 : 0);
325}
326//var_dump($morewherefilterarray);
327
328$morewherefilter = '';
329if (count($morewherefilterarray) > 0) {
330 $morewherefilter = ' AND '.implode(' AND ', $morewherefilterarray);
331}
332
333if ($action == 'createtask' && $user->hasRight('projet', 'creer')) {
334 $error = 0;
335
336 // If we use user timezone, we must change also view/list to use user timezone everywhere
337 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), 0, GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
338 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), 0, GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
339
340 if (!$cancel) {
341 if (empty($taskref)) {
342 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
343 $action = 'create';
344 $error++;
345 }
346 if (empty($label)) {
347 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
348 $action = 'create';
349 $error++;
350 } elseif (!GETPOST('task_parent')) {
351 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ChildOfProjectTask")), null, 'errors');
352 $action = 'create';
353 $error++;
354 }
355
356 if (!$error) {
357 $tmparray = explode('_', GETPOST('task_parent'));
358 $projectid = empty($tmparray[0]) ? $id : (int) $tmparray[0];
359 $task_parent = empty($tmparray[1]) ? 0 : $tmparray[1];
360
361 $task = new Task($db);
362
363 $task->fk_project = $projectid;
364 $task->entity = $object->entity; // Task have the same entity of project
365 $task->ref = $taskref;
366 $task->label = $label;
367 $task->description = $description;
368 $task->planned_workload = $planned_workload;
369 $task->fk_task_parent = $task_parent;
370 $task->date_c = dol_now();
371 $task->date_start = $date_start;
372 $task->date_end = $date_end;
373 $task->progress = $progress;
374 $task->budget_amount = $budget_amount;
375 $task->billable = $billable;
376
377 // Fill array 'array_options' with data from add form
378 $ret = $extrafields->setOptionalsFromPost(null, $task);
379
380 $taskid = $task->create($user);
381
382 if ($taskid > 0) {
383 $result = $task->add_contact(GETPOSTINT("userid"), 'TASKEXECUTIVE', 'internal');
384 } else {
385 if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
386 $langs->load("projects");
387 setEventMessages($langs->trans('NewTaskRefSuggested'), null, 'warnings');
388 $duplicate_code_error = true;
389 } else {
390 setEventMessages($task->error, $task->errors, 'errors');
391 }
392 $action = 'create';
393 $error++;
394 }
395 }
396
397 if (!$error) {
398 if (!empty($backtopage)) {
399 header("Location: ".$backtopage);
400 exit;
401 } elseif (empty($projectid)) {
402 header("Location: ".DOL_URL_ROOT.'/projet/tasks/list.php'.(empty($mode) ? '' : '?mode='.$mode));
403 exit;
404 }
405 $id = $projectid;
406 }
407 } else {
408 if (!empty($backtopage)) {
409 header("Location: ".$backtopage);
410 exit;
411 } elseif (empty($id)) {
412 // We go back on task list
413 header("Location: ".DOL_URL_ROOT.'/projet/tasks/list.php'.(empty($mode) ? '' : '?mode='.$mode));
414 exit;
415 }
416 }
417}
418
419
420/*
421 * View
422 */
423
424$now = dol_now();
425$form = new Form($db);
426$formother = new FormOther($db);
427$socstatic = new Societe($db);
428$projectstatic = new Project($db);
429$taskstatic = new Task($db);
430$userstatic = new User($db);
431
432$title = $langs->trans("Tasks").' - '.$object->ref.' '.$object->name;
433if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/projectnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->name) {
434 $title = $object->ref.' '.$object->name.' - '.$langs->trans("Tasks");
435}
436if ($action == 'create') {
437 $title = $langs->trans("NewTask");
438}
439$help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
440
441llxHeader("", $title, $help_url, '', 0, 0, '', '', '', 'mod-project page-card_tasks');
442
443$arrayofselected = is_array($toselect) ? $toselect : array();
444
445if ($id > 0 || !empty($ref)) {
446 $result = $object->fetch($id, $ref);
447 if ($result < 0) {
448 setEventMessages(null, $object->errors, 'errors');
449 }
450 $result = $object->fetch_thirdparty();
451 if ($result < 0) {
452 setEventMessages(null, $object->errors, 'errors');
453 }
454 $result = $object->fetch_optionals();
455 if ($result < 0) {
456 setEventMessages(null, $object->errors, 'errors');
457 }
458
459
460 // To verify role of users
461 //$userAccess = $object->restrictedProjectArea($user,'read');
462 $userWrite = $object->restrictedProjectArea($user, 'write');
463 //$userDelete = $object->restrictedProjectArea($user,'delete');
464 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
465
466
467 $tab = (GETPOSTISSET('tab') ? GETPOST('tab') : 'tasks');
468
469 $head = project_prepare_head($object);
470 print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
471
472 $param = '&id='.$object->id;
473 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
474 $param .= '&contextpage='.urlencode($contextpage);
475 }
476 if ($search_user_id) {
477 $param .= '&search_user_id='.urlencode((string) ($search_user_id));
478 }
479 if ($search_taskref) {
480 $param .= '&search_taskref='.urlencode($search_taskref);
481 }
482 if ($search_tasklabel) {
483 $param .= '&search_tasklabel='.urlencode($search_tasklabel);
484 }
485 if ($search_taskdescription) {
486 $param .= '&search_taskdescription='.urlencode($search_taskdescription);
487 }
488 if ($search_dtstartday) {
489 $param .= '&search_dtstartday='.urlencode($search_dtstartday);
490 }
491 if ($search_dtstartmonth) {
492 $param .= '&search_dtstartmonth='.urlencode($search_dtstartmonth);
493 }
494 if ($search_dtstartyear) {
495 $param .= '&search_dtstartyear='.urlencode($search_dtstartyear);
496 }
497 if ($search_dtendday) {
498 $param .= '&search_dtendday='.urlencode($search_dtendday);
499 }
500 if ($search_dtendmonth) {
501 $param .= '&search_dtendmonth='.urlencode($search_dtendmonth);
502 }
503 if ($search_dtendyear) {
504 $param .= '&search_dtendyear='.urlencode($search_dtendyear);
505 }
506 if ($search_date_start_startmonth) {
507 $param .= '&search_date_start_startmonth='.urlencode((string) ($search_date_start_startmonth));
508 }
509 if ($search_date_start_startyear) {
510 $param .= '&search_date_start_startyear='.urlencode((string) ($search_date_start_startyear));
511 }
512 if ($search_date_start_startday) {
513 $param .= '&search_date_start_startday='.urlencode((string) ($search_date_start_startday));
514 }
515 if ($search_date_start_start) {
516 $param .= '&search_date_start_start='.urlencode($search_date_start_start);
517 }
518 if ($search_date_start_endmonth) {
519 $param .= '&search_date_start_endmonth='.urlencode((string) ($search_date_start_endmonth));
520 }
521 if ($search_date_start_endyear) {
522 $param .= '&search_date_start_endyear='.urlencode((string) ($search_date_start_endyear));
523 }
524 if ($search_date_start_endday) {
525 $param .= '&search_date_start_endday='.urlencode((string) ($search_date_start_endday));
526 }
527 if ($search_date_start_end) {
528 $param .= '&search_date_start_end='.urlencode($search_date_start_end);
529 }
530 if ($search_date_end_startmonth) {
531 $param .= '&search_date_end_startmonth='.urlencode((string) ($search_date_end_startmonth));
532 }
533 if ($search_date_end_startyear) {
534 $param .= '&search_date_end_startyear='.urlencode((string) ($search_date_end_startyear));
535 }
536 if ($search_date_end_startday) {
537 $param .= '&search_date_end_startday='.urlencode((string) ($search_date_end_startday));
538 }
539 if ($search_date_end_start) {
540 $param .= '&search_date_end_start='.urlencode($search_date_end_start);
541 }
542 if ($search_date_end_endmonth) {
543 $param .= '&search_date_end_endmonth='.urlencode((string) ($search_date_end_endmonth));
544 }
545 if ($search_date_end_endyear) {
546 $param .= '&search_date_end_endyear='.urlencode((string) ($search_date_end_endyear));
547 }
548 if ($search_date_end_endday) {
549 $param .= '&search_date_end_endday='.urlencode((string) ($search_date_end_endday));
550 }
551 if ($search_date_end_end) {
552 $param .= '&search_date_end_end=' . urlencode($search_date_end_end);
553 }
554 if ($search_planedworkload) {
555 $param .= '&search_planedworkload='.urlencode($search_planedworkload);
556 }
557 if ($search_timespend) {
558 $param .= '&search_timespend='.urlencode($search_timespend);
559 }
560 if ($search_progresscalc) {
561 $param .= '&search_progresscalc='.urlencode($search_progresscalc);
562 }
563 if ($search_progressdeclare) {
564 $param .= '&search_progressdeclare='.urlencode($search_progressdeclare);
565 }
566 if ($search_task_budget_amount) {
567 $param .= '&search_task_budget_amount='.urlencode($search_task_budget_amount);
568 }
569 if ($search_task_billable) {
570 $param .= '&search_task_billable='.urlencode($search_task_billable);
571 }
572 if ($optioncss != '') {
573 $param .= '&optioncss='.urlencode($optioncss);
574 }
575 // Add $param from extra fields
576 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
577
578 $arrayofmassactions = array();
579 if ($user->hasRight('projet', 'creer')) {
580 $arrayofmassactions['preclonetasks'] = img_picto('', 'clone', 'class="pictofixedwidth"').$langs->trans("Clone");
581 }
582 if ($permissiontodelete) {
583 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
584 }
585 if (in_array($massaction, array('presend', 'predelete'))) {
586 $arrayofmassactions = array();
587 }
588 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
589
590 // Project card
591
592 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
593 $tmpurl = $_SESSION['pageforbacktolist']['project'];
594 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
595 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
596 } else {
597 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
598 }
599
600 $morehtmlref = '<div class="refidno">';
601 // Title
602 $morehtmlref .= $object->title;
603 // Thirdparty
604 if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
605 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1, 'project');
606 }
607 $morehtmlref .= '</div>';
608
609 // Define a complementary filter for search of next/prev ref.
610 if (!$user->hasRight('projet', 'all', 'lire')) {
611 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
612 $object->next_prev_filter = "rowid IN (".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0').")";
613 }
614
615 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
616
617 print '<div class="fichecenter">';
618 print '<div class="fichehalfleft">';
619 print '<div class="underbanner clearboth"></div>';
620
621 print '<table class="border tableforfield centpercent">';
622
623 // Usage
624 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
625 print '<tr><td class="tdtop">';
626 print $langs->trans("Usage");
627 print '</td>';
628 print '<td>';
629 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
630 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
631 $htmltext = $langs->trans("ProjectFollowOpportunity");
632 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
633 print '<br>';
634 }
635 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
636 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
637 $htmltext = $langs->trans("ProjectFollowTasks");
638 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
639 print '<br>';
640 }
641 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
642 print '<input type="checkbox" disabled name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')).'"> ';
643 $htmltext = $langs->trans("ProjectBillTimeDescription");
644 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
645 print '<br>';
646 }
647 if (isModEnabled('eventorganization')) {
648 print '<input type="checkbox" disabled name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_organize_event ? ' checked="checked"' : '')).'"> ';
649 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
650 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
651 }
652 print '</td></tr>';
653 }
654
655 // Visibility
656 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
657 if ($object->public) {
658 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
659 print $langs->trans('SharedProject');
660 } else {
661 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
662 print $langs->trans('PrivateProject');
663 }
664 print '</td></tr>';
665
666 // Budget
667 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
668 if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
669 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
670 }
671 print '</td></tr>';
672
673 // Date start - end project
674 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
675 $start = dol_print_date($object->date_start, 'day');
676 print($start ? $start : '?');
677 $end = dol_print_date($object->date_end, 'day');
678 print ' - ';
679 print($end ? $end : '?');
680 if ($object->hasDelay()) {
681 print img_warning("Late");
682 }
683 print '</td></tr>';
684
685 // Other attributes
686 $cols = 2;
687 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
688
689 print '</table>';
690
691 print '</div>';
692 print '<div class="fichehalfright">';
693 print '<div class="underbanner clearboth"></div>';
694
695 print '<table class="border tableforfield centpercent">';
696
697 // Description
698 print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
699 print dol_htmlentitiesbr($object->description);
700 print '</td></tr>';
701
702 // Categories
703 if (isModEnabled('category')) {
704 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
705 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
706 print "</td></tr>";
707 }
708
709 print '</table>';
710
711 print '</div>';
712 print '</div>';
713
714 print '<div class="clearboth"></div>';
715
716
717 print dol_get_fiche_end();
718}
719
720
721if ($action == 'create' && $user->hasRight('projet', 'creer') && (empty($object->thirdparty->id) || $userWrite > 0)) {
722 if ($id > 0 || !empty($ref)) {
723 print '<br>';
724 }
725
726 print load_fiche_titre($langs->trans("NewTask"), '', 'projecttask');
727
728 $projectoktoentertime = 1;
729 if ($object->id > 0 && $object->status == Project::STATUS_CLOSED) {
730 $projectoktoentertime = 0;
731 print '<div class="warning">';
732 $langs->load("errors");
733 print $langs->trans("WarningProjectClosed");
734 print '</div>';
735 }
736
737 if ($object->id > 0 && $object->status == Project::STATUS_DRAFT) {
738 $projectoktoentertime = 0;
739 print '<div class="warning">';
740 $langs->load("errors");
741 print $langs->trans("WarningProjectDraft");
742 print '</div>';
743 }
744
745 print '<form action="'.$_SERVER['PHP_SELF'].'" method="POST">';
746 print '<input type="hidden" name="token" value="'.newToken().'">';
747 print '<input type="hidden" name="action" value="createtask">';
748 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
749 if (!empty($object->id)) {
750 print '<input type="hidden" name="id" value="'.$object->id.'">';
751 }
752
753 print dol_get_fiche_head();
754
755 print '<div class="div-table-responsive-no-min">';
756 print '<table class="border centpercent">';
757
758 $defaultref = '';
759 $classnamemodtask = getDolGlobalString('PROJECT_TASK_ADDON', 'mod_task_simple');
760 if (getDolGlobalString('PROJECT_TASK_ADDON') && is_readable(DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').".php")) {
761 require_once DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').'.php';
762 $modTask = new $classnamemodtask();
763 '@phan-var-force ModeleNumRefTask $modTask';
764 $defaultref = $modTask->getNextValue($object->thirdparty, $object);
765 }
766
767 if (is_numeric($defaultref) && $defaultref <= 0) {
768 $defaultref = '';
769 }
770
771 // Ref
772 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
773 if (empty($duplicate_code_error)) {
774 print(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref);
775 } else {
776 print $defaultref;
777 }
778 print '<input type="hidden" name="taskref" value="'.(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref).'">';
779 print '</td></tr>';
780
781 // Label
782 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td>';
783 print '<input type="text" name="label" autofocus class="minwidth500" value="'.$label.'">';
784 print '</td></tr>';
785
786 // Project
787 print '<tr><td class="fieldrequired">'.$langs->trans("ChildOfProjectTask").'</td><td>';
788 print img_picto('', 'project', 'class="pictofixedwidth"');
789 if ($projectoktoentertime) {
790 $formother->selectProjectTasks(GETPOST('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '0,1', 'maxwidth500 widthcentpercentminusxx');
791 } else {
792 $formother->selectProjectTasks(GETPOST('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '', 'maxwidth500 widthcentpercentminusxx');
793 }
794 print '</td></tr>';
795
796 $contactsofproject = (empty($object->id) ? '' : $object->getListContactId('internal'));
797
798 // Assigned to
799 print '<tr><td>'.$langs->trans("AffectedTo").'</td><td>';
800 print img_picto('', 'user', 'class="pictofixedwidth"');
801 if (is_array($contactsofproject) && count($contactsofproject)) {
802 print $form->select_dolusers($user->id, 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
803 } else {
804 if ((isset($projectid) && $projectid > 0) || $object->id > 0) {
805 print '<span class="opacitymedium">'.$langs->trans("NoUserAssignedToTheProject").'</span>';
806 } else {
807 print $form->select_dolusers($user->id, 'userid', 0, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
808 }
809 }
810 print '</td></tr>';
811
812 // Billable
813 print '<tr><td>'.$langs->trans("Billable").'</td><td>';
814 print $form->selectyesno('billable');
815 print '</td></tr>';
816
817 // Date start task
818 print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
819 print img_picto('', 'action', 'class="pictofixedwidth"');
820 print $form->selectDate((!empty($date_start) ? $date_start : ''), 'date_start', 1, 1, 0, '', 1, 1);
821 print '</td></tr>';
822
823 // Date end task
824 print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
825 print img_picto('', 'action', 'class="pictofixedwidth"');
826 print $form->selectDate((!empty($date_end) ? $date_end : -1), 'date_end', -1, 1, 0, '', 1, 1);
827 print '</td></tr>';
828
829 // Planned workload
830 print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td>';
831 print img_picto('', 'clock', 'class="pictofixedwidth"');
832 print $form->select_duration('planned_workload', $planned_workload, 0, 'text');
833 print '</td></tr>';
834
835 // Progress
836 print '<tr><td>'.$langs->trans("ProgressDeclared").'</td><td colspan="3">';
837 print img_picto('', 'fa-percent', 'class="pictofixedwidth"');
838 print $formother->select_percent($progress, 'progress', 0, 5, 0, 100, 1);
839 print '</td></tr>';
840
841 // Description
842 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
843 print '<td>';
844
845 // WYSIWYG editor
846 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
847 $nbrows = 0;
848 if (getDolGlobalString('MAIN_INPUT_DESC_HEIGHT')) {
849 $nbrows = getDolGlobalString('MAIN_INPUT_DESC_HEIGHT');
850 }
851 $doleditor = new DolEditor('description', $object->description, '', 80, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), $nbrows, '90%');
852 print $doleditor->Create();
853
854 print '</td></tr>';
855
856 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
857 print img_picto('', 'currency', 'class="pictofixedwidth"');
858 print '<input size="8" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'"></td>';
859 print '</tr>';
860
861 // Other options
862 $parameters = array('arrayfields' => &$arrayfields);
863 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $taskstatic, $action); // Note that $action and $object may have been modified by hook
864 print $hookmanager->resPrint;
865
866 if (empty($reshook) && !empty($extrafields->attributes[$taskstatic->table_element]['label'])) {
867 print $taskstatic->showOptionals($extrafields, 'edit'); // Do not use $object here that is object of project but use $taskstatic
868 }
869
870 print '</table>';
871 print '</div>';
872
873 print dol_get_fiche_end();
874
875 print $form->buttonsSaveCancel("Add");
876
877 print '</form>';
878} elseif ($id > 0 || !empty($ref)) {
879 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
880
881 // Projet card in view mode
882
883 print '<br>';
884
885 // Link to create task
886 $linktocreatetaskParam = array();
887 $linktocreatetaskUserRight = false;
888 if ($user->hasRight('projet', 'all', 'creer') || $user->hasRight('projet', 'creer')) {
889 if ($object->public || $userWrite > 0) {
890 $linktocreatetaskUserRight = true;
891 } else {
892 $linktocreatetaskParam['attr']['title'] = $langs->trans("NotOwnerOfProject");
893 }
894 }
895
896 $linktocreatetask = dolGetButtonTitle($langs->trans('AddTask'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/tasks.php?action=create'.$param.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$object->id), '', (int) $linktocreatetaskUserRight, $linktocreatetaskParam);
897
898 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
899 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
900 print '<input type="hidden" name="token" value="'.newToken().'">';
901 print '<input type="hidden" name="action" value="list">';
902 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
903 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
904 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
905 print '<input type="hidden" name="page" value="'.$page.'">';
906 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
907
908 $title = $langs->trans("ListOfTasks");
909 $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss' => 'reposition btnTitleSelected'));
910 $linktotasks .= dolGetButtonTitle($langs->trans('ViewGantt'), '', 'fa fa-stream imgforviewmode', DOL_URL_ROOT.'/projet/ganttview.php?id='.$object->id.'&withproject=1', '', 1, array('morecss' => 'reposition marginleftonly'));
911
912 //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1);
913 print load_fiche_titre($title, $linktotasks.' &nbsp; '.$linktocreatetask, 'projecttask', 0, '', '', $massactionbutton);
914
915 $objecttmp = new Task($db);
916 $trackid = 'task'.$taskstatic->id;
917 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
918
919 // Get list of tasks in tasksarray and taskarrayfiltered
920 // We need all tasks (even not limited to a user because a task to user can have a parent that is not affected to him).
921 $filteronthirdpartyid = $socid;
922 $tasksarray = $taskstatic->getTasksArray(0, 0, $object->id, $filteronthirdpartyid, 0, '', -1, $morewherefilter, 0, 0, $extrafields, 1, $search_array_options, 1, 1, $sortfield, $sortorder);
923
924 // We load also tasks limited to a particular user
925 $tmpuser = new User($db);
926 if ($search_user_id > 0) {
927 $tmpuser->fetch($search_user_id);
928 }
929
930 $tasksrole = ($tmpuser->id > 0 ? $taskstatic->getUserRolesForProjectsOrTasks(null, $tmpuser, $object->id, 0) : '');
931 //var_dump($tasksarray);
932 //var_dump($tasksrole);
933
934 if (!empty($conf->use_javascript_ajax)) {
935 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
936 }
937
938 // Filter on assigned users
939 $moreforfilter = '';
940 $moreforfilter .= '<div class="divsearchfield">';
941 $moreforfilter .= img_picto('', 'user', 'class="pictofixedwidth"');
942 $moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', $langs->trans("TasksAssignedTo"), null, 0, '', '');
943 $moreforfilter .= '</div>';
944 if ($moreforfilter) {
945 print '<div class="liste_titre liste_titre_bydiv centpercent">';
946 print $moreforfilter;
947 print '</div>';
948 }
949
950 // Show the massaction checkboxes only when this page is not opend from the Extended POS
951 if ($massactionbutton && $contextpage != 'poslist') {
952 $selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
953 }
954
955 print '<div class="div-table-responsive">';
956 print '<table id="tablelines" class="tagtable nobottom liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
957
958 // Fields title search
959 print '<tr class="liste_titre_filter">';
960
961 // Action column
962 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
963 print '<td class="liste_titre maxwidthsearch">';
964 $searchpicto = $form->showFilterButtons();
965 print $searchpicto;
966 print '</td>';
967 }
968
969 if (!empty($arrayfields['t.ref']['checked'])) {
970 print '<td class="liste_titre">';
971 print '<input class="flat searchstring maxwidth50" type="text" name="search_taskref" value="'.dol_escape_htmltag($search_taskref).'">';
972 print '</td>';
973 }
974
975 if (!empty($arrayfields['t.label']['checked'])) {
976 print '<td class="liste_titre">';
977 print '<input class="flat searchstring maxwidth100" type="text" name="search_tasklabel" value="'.dol_escape_htmltag($search_tasklabel).'">';
978 print '</td>';
979 }
980
981 if (!empty($arrayfields['t.description']['checked'])) {
982 print '<td class="liste_titre">';
983 print '<input class="flat searchstring maxwidth100" type="text" name="search_taskdescription" value="'.dol_escape_htmltag($search_taskdescription).'">';
984 print '</td>';
985 }
986
987 if (!empty($arrayfields['t.dateo']['checked'])) {
988 print '<td class="liste_titre center">';
989 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartday" value="'.$search_dtstartday.'">';
990 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartmonth" value="'.$search_dtstartmonth.'"></span>';
991 print $formother->selectyear($search_dtstartyear ? $search_dtstartyear : -1, 'search_dtstartyear', 1, 20, 5);*/
992 print '<div class="nowrapfordate">';
993 print $form->selectDate($search_date_start_start ? $search_date_start_start : -1, 'search_date_start_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
994 print '</div>';
995 print '<div class="nowrapfordate">';
996 print $form->selectDate($search_date_start_end ? $search_date_start_end : -1, 'search_date_start_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
997 print '</div>';
998 print '</td>';
999 }
1000
1001 if (!empty($arrayfields['t.datee']['checked'])) {
1002 print '<td class="liste_titre center">';
1003 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendday" value="'.$search_dtendday.'">';
1004 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendmonth" value="'.$search_dtendmonth.'"></span>';
1005 print $formother->selectyear($search_dtendyear ? $search_dtendyear : -1, 'search_dtendyear', 1, 20, 5);*/
1006 print '<div class="nowrapfordate">';
1007 print $form->selectDate($search_date_end_start ? $search_date_end_start : -1, 'search_date_end_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
1008 print '</div>';
1009 print '<div class="nowrapfordate">';
1010 print $form->selectDate($search_date_end_end ? $search_date_end_end : -1, 'search_date_end_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
1011 print '</div>';
1012 print '</td>';
1013 }
1014
1015 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1016 print '<td class="liste_titre right">';
1017 print '<input class="flat" type="text" size="4" name="search_planedworkload" value="'.$search_planedworkload.'">';
1018 print '</td>';
1019 }
1020
1021 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1022 print '<td class="liste_titre right">';
1023 print '<input class="flat" type="text" size="4" name="search_timespend" value="'.$search_timespend.'">';
1024 print '</td>';
1025 }
1026
1027 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1028 print '<td class="liste_titre right">';
1029 print '<input class="flat" type="text" size="4" name="search_progresscalc" value="'.$search_progresscalc.'">';
1030 print '</td>';
1031 }
1032
1033 if (!empty($arrayfields['t.progress']['checked'])) {
1034 print '<td class="liste_titre right">';
1035 print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
1036 print '</td>';
1037 }
1038
1039 // progress resume not searchable
1040 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1041 print '<td class="liste_titre right"></td>';
1042 }
1043
1044 if ($object->usage_bill_time) {
1045 if (!empty($arrayfields['t.tobill']['checked'])) {
1046 print '<td class="liste_titre right">';
1047 print '</td>';
1048 }
1049
1050 if (!empty($arrayfields['t.billed']['checked'])) {
1051 print '<td class="liste_titre right">';
1052 print '</td>';
1053 }
1054 }
1055 // Contacts of task, disabled because available by default just after
1056 /*
1057 if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) {
1058 print '<td class="liste_titre"></td>';
1059 }
1060 */
1061
1062 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1063 print '<td class="liste_titre center">';
1064 print '<input type="text" class="flat" name="search_task_budget_amount" value="'.$search_task_budget_amount.'" size="4">';
1065 print '</td>';
1066 }
1067
1068 if (!empty($arrayfields['c.assigned']['checked'])) {
1069 print '<td class="liste_titre right">';
1070 print '</td>';
1071 }
1072
1073 if (!empty($arrayfields['t.billable']['checked'])) {
1074 print '<td class="liste_titre center">';
1075 print $form->selectyesno('search_task_billable', $search_task_billable, 0, false, 1);
1076 print '</td>';
1077 }
1078
1079 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1080
1081 print '<td class="liste_titre maxwidthsearch">&nbsp;</td>';
1082
1083 // Action column
1084 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1085 print '<td class="liste_titre maxwidthsearch">';
1086 $searchpicto = $form->showFilterButtons();
1087 print $searchpicto;
1088 print '</td>';
1089 }
1090
1091 print "</tr>\n";
1092
1093 print '<tr class="liste_titre nodrag nodrop">';
1094 // Action column
1095 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1096 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1097 }
1098 // print '<td>'.$langs->trans("Project").'</td>';
1099 if (!empty($arrayfields['t.ref']['checked'])) {
1100 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1101 print_liste_field_titre($arrayfields['t.ref']['label'], $_SERVER["PHP_SELF"], 't.ref', '', $param, '', $sortfield, $sortorder, '');
1102 }
1103 if (!empty($arrayfields['t.label']['checked'])) {
1104 print_liste_field_titre($arrayfields['t.label']['label'], $_SERVER["PHP_SELF"], "t.label", '', $param, '', $sortfield, $sortorder, '');
1105 }
1106 if (!empty($arrayfields['t.description']['checked'])) {
1107 print_liste_field_titre($arrayfields['t.description']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, '');
1108 }
1109 if (!empty($arrayfields['t.dateo']['checked'])) {
1110 print_liste_field_titre($arrayfields['t.dateo']['label'], $_SERVER["PHP_SELF"], "t.dateo", '', $param, '', $sortfield, $sortorder, 'center ');
1111 }
1112 if (!empty($arrayfields['t.datee']['checked'])) {
1113 print_liste_field_titre($arrayfields['t.datee']['label'], $_SERVER["PHP_SELF"], "t.datee", '', $param, '', $sortfield, $sortorder, 'center ');
1114 }
1115 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1116 print_liste_field_titre($arrayfields['t.planned_workload']['label'], $_SERVER["PHP_SELF"], "t.planned_workload", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1117 }
1118 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1119 print_liste_field_titre($arrayfields['t.duration_effective']['label'], $_SERVER["PHP_SELF"], "t.duration_effective", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1120 }
1121 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1122 print_liste_field_titre($arrayfields['t.progress_calculated']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1123 }
1124 if (!empty($arrayfields['t.progress']['checked'])) {
1125 print_liste_field_titre($arrayfields['t.progress']['label'], $_SERVER["PHP_SELF"], "t.progress", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1126 }
1127 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1128 print_liste_field_titre($arrayfields['t.progress_summary']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '', 1);
1129 }
1130 if ($object->usage_bill_time) {
1131 if (!empty($arrayfields['t.tobill']['checked'])) {
1132 print_liste_field_titre($arrayfields['t.tobill']['label'], $_SERVER["PHP_SELF"], "t.tobill", '', $param, '', $sortfield, $sortorder, 'right ');
1133 }
1134 if (!empty($arrayfields['t.billed']['checked'])) {
1135 print_liste_field_titre($arrayfields['t.billed']['label'], $_SERVER["PHP_SELF"], "t.billed", '', $param, '', $sortfield, $sortorder, 'right ');
1136 }
1137 }
1138 // Contacts of task, disabled because available by default just after
1139 /*
1140 if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) {
1141 print_liste_field_titre("TaskRessourceLinks", $_SERVER["PHP_SELF"], '', '', $param, $sortfield, $sortorder);
1142 }
1143 */
1144
1145 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1146 print_liste_field_titre($arrayfields['t.budget_amount']['label'], $_SERVER["PHP_SELF"], "t.budget_amount", "", $param, '', $sortfield, $sortorder, 'center ');
1147 }
1148
1149 if (!empty($arrayfields['c.assigned']['checked'])) {
1150 print_liste_field_titre($arrayfields['c.assigned']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1151 }
1152
1153 if (!empty($arrayfields['t.billable']['checked'])) {
1154 print_liste_field_titre($arrayfields['t.billable']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1155 }
1156 // Extra fields
1157 $disablesortlink = 1;
1158 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1159 // Hook fields
1160 $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
1161 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1162 print $hookmanager->resPrint;
1163 print '<td></td>';
1164 // Action column
1165 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1166 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1167 }
1168 print "</tr>\n";
1169
1170 $nboftaskshown = 0;
1171 if (count($tasksarray) > 0) {
1172 // Show all lines in taskarray (recursive function to go down on tree)
1173 $j = 0;
1174 $level = 0;
1175 $nboftaskshown = projectLinesa($j, 0, $tasksarray, $level, '', 0, $tasksrole, (string) $object->id, 1, $object->id, '', ($object->usage_bill_time ? 1 : 0), $arrayfields, $arrayofselected);
1176 } else {
1177 $colspan = count($arrayfields);
1178 if ($object->usage_bill_time) {
1179 $colspan += 2;
1180 }
1181 print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoTasks").'</span></td></tr>';
1182 }
1183
1184 print "</table>";
1185 print '</div>';
1186
1187 print '</form>';
1188
1189
1190 // Test if database is clean. If not we clean it.
1191 //print 'mode='.$_REQUEST["mode"].' $nboftaskshown='.$nboftaskshown.' count($tasksarray)='.count($tasksarray).' count($tasksrole)='.count($tasksrole).'<br>';
1192 if ($user->hasRight('projet', 'all', 'lire')) { // We make test to clean only if user has permission to see all (test may report false positive otherwise)
1193 if ($search_user_id == $user->id) {
1194 if ($nboftaskshown < count($tasksrole)) {
1195 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1196 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1197 }
1198 } else {
1199 if ($nboftaskshown < count($tasksarray) && !GETPOSTINT('search_user_id')) {
1200 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1201 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1202 }
1203 }
1204 }
1205}
1206
1207// End of page
1208llxFooter();
1209$db->close();
$id
Definition account.php:39
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($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:70
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
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 projects.
const STATUS_CLOSED
Closed status.
const STATUS_DRAFT
Draft status.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Class to manage Dolibarr users.
dolSqlDateFilter($datefield, $day_date, $month_date, $year_date, $excludefirstand=0, $gm=false)
Generate a SQL string to make a filter into a range (for second of date until last second of date).
Definition date.lib.php:378
llxFooter()
Footer empty.
Definition document.php:107
cleanCorruptedTree($db, $tabletocleantree, $fieldfkparent)
Clean corrupted database tree (orphelins linked to a not existing parent), record linked to themself,...
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...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
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.
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_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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId='', $addordertick=0, $projectidfortotallink=0, $dummy='', $showbilltime=0, $arrayfields=array(), $arrayofselected=array())
Show task lines with a particular parent.
project_prepare_head(Project $project, $moreparam='')
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.