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