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_');
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 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
606
607 $arrayofmassactions = array();
608 if ($user->hasRight('projet', 'creer')) {
609 $arrayofmassactions['preclonetasks'] = img_picto('', 'clone', 'class="pictofixedwidth"').$langs->trans("Clone");
610 }
611 if ($permissiontodelete) {
612 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
613 }
614 if (in_array($massaction, array('presend', 'predelete'))) {
615 $arrayofmassactions = array();
616 }
617 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
618
619 // Project card
620
621 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
622 $tmpurl = $_SESSION['pageforbacktolist']['project'];
623 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
624 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
625 } else {
626 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
627 }
628
629 $morehtmlref = '<div class="refidno">';
630 // Title
631 $morehtmlref .= $object->title;
632 // Thirdparty
633 if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
634 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1, 'project');
635 }
636 $morehtmlref .= '</div>';
637
638 // Define a complementary filter for search of next/prev ref.
639 if (!$user->hasRight('projet', 'all', 'lire')) {
640 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
641 $object->next_prev_filter = "rowid:IN:".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0');
642 }
643
644 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
645
646 print '<div class="fichecenter">';
647 print '<div class="fichehalfleft">';
648 print '<div class="underbanner clearboth"></div>';
649
650 print '<table class="border tableforfield centpercent">';
651
652 // Usage
653 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
654 print '<tr><td class="tdtop">';
655 print $langs->trans("Usage");
656 print '</td>';
657 print '<td>';
658 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
659 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
660 $htmltext = $langs->trans("ProjectFollowOpportunity");
661 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
662 print '<br>';
663 }
664 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
665 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
666 $htmltext = $langs->trans("ProjectFollowTasks");
667 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
668 print '<br>';
669 }
670 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
671 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"' : '')).'"> ';
672 $htmltext = $langs->trans("ProjectBillTimeDescription");
673 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
674 print '<br>';
675 }
676 if (isModEnabled('eventorganization')) {
677 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"' : '')).'"> ';
678 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
679 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
680 }
681 print '</td></tr>';
682 }
683
684 // Budget
685 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
686 if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
687 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
688 }
689 print '</td></tr>';
690
691 // Date start - end project
692 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
693 $start = dol_print_date($object->date_start, 'day');
694 print($start ? $start : '?');
695 $end = dol_print_date($object->date_end, 'day');
696 print ' - ';
697 print($end ? $end : '?');
698 if ($object->hasDelay()) {
699 print img_warning("Late");
700 }
701 print '</td></tr>';
702
703 // Visibility
704 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
705 if ($object->public) {
706 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
707 print $langs->trans('SharedProject');
708 } else {
709 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
710 print $langs->trans('PrivateProject');
711 }
712 print '</td></tr>';
713
714 // Other attributes
715 $cols = 2;
716 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
717
718 print '</table>';
719
720 print '</div>';
721 print '<div class="fichehalfright">';
722 print '<div class="underbanner clearboth"></div>';
723
724 print '<table class="border tableforfield centpercent">';
725
726 // Categories
727 if (isModEnabled('category')) {
728 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
729 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
730 print "</td></tr>";
731 }
732
733 // Description
734 print '<tr><td class="titlefield'.($object->description ? ' noborderbottom' : '').'" colspan="2">'.$langs->trans("Description").'</td></tr>';
735 if ($object->description) {
736 print '<tr><td class="nottitleforfield" colspan="2">';
737 print '<div class="longmessagecut">';
738 print dolPrintHTML($object->description);
739 print '</div>';
740 print '</td></tr>';
741 }
742
743 print '</table>';
744
745 print '</div>';
746 print '</div>';
747
748 print '<div class="clearboth"></div>';
749
750
751 print dol_get_fiche_end();
752}
753
754
755if ($action == 'create' && $user->hasRight('projet', 'creer') && (empty($object->thirdparty->id) || $userWrite > 0)) {
756 if ($id > 0 || !empty($ref)) {
757 print '<br>';
758 }
759
760 print load_fiche_titre($langs->trans("NewTask"), '', 'projecttask');
761
762 $projectoktoentertime = 1;
763 if ($object->id > 0 && $object->status == Project::STATUS_CLOSED) {
764 $projectoktoentertime = 0;
765 print '<div class="warning">';
766 $langs->load("errors");
767 print $langs->trans("WarningProjectClosed");
768 print '</div>';
769 }
770
771 if ($object->id > 0 && $object->status == Project::STATUS_DRAFT) {
772 $projectoktoentertime = 0;
773 print '<div class="warning">';
774 $langs->load("errors");
775 print $langs->trans("WarningProjectDraft");
776 print '</div>';
777 }
778
779 print '<form action="'.$_SERVER['PHP_SELF'].'" method="POST">';
780 print '<input type="hidden" name="token" value="'.newToken().'">';
781 print '<input type="hidden" name="action" value="createtask">';
782 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
783 if (!empty($object->id)) {
784 print '<input type="hidden" name="id" value="'.$object->id.'">';
785 }
786
787 print dol_get_fiche_head();
788
789 print '<div class="div-table-responsive-no-min">';
790 print '<table class="border centpercent">';
791
792 $defaultref = '';
793 $classnamemodtask = getDolGlobalString('PROJECT_TASK_ADDON', 'mod_task_simple');
794 if (getDolGlobalString('PROJECT_TASK_ADDON') && is_readable(DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').".php")) {
795 require_once DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').'.php';
796 $modTask = new $classnamemodtask();
797 '@phan-var-force ModeleNumRefTask $modTask';
798 $tasktmp = new Task($db); // Numbering modules expect a Task object (and use its creation date), not the project
799 $tasktmp->fk_project = $object->id;
800 $defaultref = $modTask->getNextValue($object->thirdparty, $tasktmp);
801 }
802
803 if (is_numeric($defaultref) && $defaultref <= 0) {
804 $defaultref = '';
805 }
806
807 // Ref
808 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
809 if (empty($duplicate_code_error)) {
810 print(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref);
811 } else {
812 print $defaultref;
813 }
814 print '<input type="hidden" name="taskref" value="'.(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref).'">';
815 print '</td></tr>';
816
817 // Label
818 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td>';
819 print '<input type="text" name="label" autofocus class="minwidth500" value="'.$label.'">';
820 print '</td></tr>';
821
822 // Project
823 print '<tr><td class="fieldrequired">'.$langs->trans("ChildOfProjectTask").'</td><td>';
824 print img_picto('', 'project', 'class="pictofixedwidth"');
825 if ($projectoktoentertime) {
826 $formother->selectProjectTasks(GETPOSTINT('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '0,1', 'maxwidth500 widthcentpercentminusxx');
827 } else {
828 $formother->selectProjectTasks(GETPOSTINT('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '', 'maxwidth500 widthcentpercentminusxx');
829 }
830 print '</td></tr>';
831
832 $contactsofproject = (empty($object->id) ? '' : $object->getListContactId('internal'));
833
834 // Assigned to
835 print '<tr><td>'.$langs->trans("AffectedTo").'</td><td>';
836 print img_picto('', 'user', 'class="pictofixedwidth"');
837 if (is_array($contactsofproject) && count($contactsofproject)) {
838 print $form->select_dolusers('-4', 'userid', 0, null, 0, '', $contactsofproject, '0', 0, 0, '(statut:=:1)', 4, '', 'maxwidth500 widthcentpercentminusx');
839 } else {
840 if ((isset($projectid) && $projectid > 0) || $object->id > 0) {
841 print '<span class="opacitymedium">'.$langs->trans("NoUserAssignedToTheProject").'</span>';
842 } else {
843 print $form->select_dolusers('-4', 'userid', 0, null, 0, '', '', '0', 0, 0, '(statut:=:1)', 4, '', 'maxwidth500 widthcentpercentminusx');
844 }
845 }
846 print '</td></tr>';
847
848 // Billable
849 print '<tr><td>'.$langs->trans("Billable").'</td><td>';
850 print $form->selectyesno('billable');
851 print '</td></tr>';
852
853 // Date start task
854 print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
855 print img_picto('', 'action', 'class="pictofixedwidth"');
856 print $form->selectDate((!empty($date_start) ? $date_start : ''), 'date_start', 1, 1, 0, '', 1, 1);
857 print '</td></tr>';
858
859 // Date end task
860 print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
861 print img_picto('', 'action', 'class="pictofixedwidth"');
862 print $form->selectDate((!empty($date_end) ? $date_end : -1), 'date_end', -1, 1, 0, '', 1, 1);
863 print '</td></tr>';
864
865 // Planned workload
866 print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td>';
867 print img_picto('', 'clock', 'class="pictofixedwidth"');
868 print $form->select_duration('planned_workload', $planned_workload, 0, 'text');
869 print '</td></tr>';
870
871 // Progress
872 print '<tr><td>'.$langs->trans("ProgressDeclared").'</td><td colspan="3">';
873 print img_picto('', 'fa-percent', 'class="pictofixedwidth"');
874 print $formother->select_percent($progress, 'progress', 0, 5, 0, 100, 1);
875 print '</td></tr>';
876
877 // Description
878 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
879 print '<td>';
880
881 // WYSIWYG editor
882 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
883 $nbrows = 0;
884 if (getDolGlobalString('MAIN_INPUT_DESC_HEIGHT')) {
885 $nbrows = getDolGlobalString('MAIN_INPUT_DESC_HEIGHT');
886 }
887 $doleditor = new DolEditor('description', $object->description, '', 80, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), $nbrows, '90%');
888 print $doleditor->Create();
889
890 print '</td></tr>';
891
892 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
893 print img_picto('', 'currency', 'class="pictofixedwidth"');
894 print '<input size="8" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'"></td>';
895 print '</tr>';
896
897 // Other options
898 $parameters = array('arrayfields' => &$arrayfields);
899 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $taskstatic, $action); // Note that $action and $object may have been modified by hook
900 print $hookmanager->resPrint;
901
902 if (empty($reshook) && !empty($extrafields->attributes[$taskstatic->table_element]['label'])) {
903 print $taskstatic->showOptionals($extrafields, 'edit'); // Do not use $object here that is object of project but use $taskstatic
904 }
905
906 print '</table>';
907 print '</div>';
908
909 print dol_get_fiche_end();
910
911 print $form->buttonsSaveCancel("Add");
912
913 print '</form>';
914} elseif ($id > 0 || !empty($ref)) {
915 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
916
917 // Projet card in view mode
918
919 print '<br>';
920
921 // Link to create task
922 $linktocreatetaskParam = array();
923 $linktocreatetaskUserRight = false;
924 if ($user->hasRight('projet', 'all', 'creer') || $user->hasRight('projet', 'creer')) {
925 if ($object->public || $userWrite > 0) {
926 $linktocreatetaskUserRight = true;
927 } else {
928 $linktocreatetaskParam['attr']['title'] = $langs->trans("NotOwnerOfProject");
929 }
930 }
931
932 $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);
933
934 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
935 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
936 print '<input type="hidden" name="token" value="'.newToken().'">';
937 print '<input type="hidden" name="action" value="list">';
938 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
939 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
940 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
941 print '<input type="hidden" name="page" value="'.$page.'">';
942 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
943
944 $title = $langs->trans("ListOfTasks");
945 $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss' => 'reposition btnTitleSelected'));
946 $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'));
947
948 //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1);
949 print load_fiche_titre($title, $linktotasks.' &nbsp; '.$linktocreatetask, 'projecttask', 0, '', '', $massactionbutton);
950
951 $objecttmp = new Task($db);
952 $trackid = 'task'.$taskstatic->id;
953 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
954
955 // Get list of tasks in tasksarray and taskarrayfiltered
956 // 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).
957 $filteronthirdpartyid = $socid;
958 $tasksarray = $taskstatic->getTasksArray(null, null, $object->id, $filteronthirdpartyid, 0, '', '-1', $morewherefilter, 0, 0, $extrafields, 1, $search_array_options, 1, 1, $sortfield, $sortorder);
959
960 // We load also tasks limited to a particular user
961 $tmpuser = new User($db);
962 if ($search_user_id > 0) {
963 $tmpuser->fetch($search_user_id);
964 }
965
966 $tasksrole = ($tmpuser->id > 0 ? $taskstatic->getUserRolesForProjectsOrTasks(null, $tmpuser, (string) $object->id, 0) : '');
967 //var_dump($tasksarray);
968 //var_dump($tasksrole);
969
970 if (!empty($conf->use_javascript_ajax)) {
971 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
972 }
973
974 // Filter on assigned users
975 $moreforfilter = '';
976 $moreforfilter .= '<div class="divsearchfield">';
977 $moreforfilter .= img_picto('', 'user', 'class="pictofixedwidth"');
978 $moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', $langs->trans("TasksAssignedTo"), null, 0, '', '');
979 $moreforfilter .= '</div>';
980 if ($moreforfilter) {
981 print '<div class="liste_titre liste_titre_bydiv centpercent">';
982 print $moreforfilter;
983 print '</div>';
984 }
985
986 // Show the massaction checkboxes only when this page is not opened from the Extended POS
987 if ($massactionbutton && $contextpage != 'poslist') {
988 $selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
989 }
990
991 print '<div class="div-table-responsive">';
992 print '<table id="tablelines" class="tagtable nobottom liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
993
994 // Fields title search
995 print '<tr class="liste_titre_filter">';
996
997 // Action column
998 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
999 print '<td class="liste_titre maxwidthsearch">';
1000 $searchpicto = $form->showFilterButtons();
1001 print $searchpicto;
1002 print '</td>';
1003 }
1004
1005 if (!empty($arrayfields['t.ref']['checked'])) {
1006 print '<td class="liste_titre">';
1007 print '<input class="flat searchstring maxwidth50" type="text" name="search_taskref" value="'.dol_escape_htmltag($search_taskref).'">';
1008 print '</td>';
1009 }
1010
1011 if (!empty($arrayfields['t.label']['checked'])) {
1012 print '<td class="liste_titre">';
1013 print '<input class="flat searchstring maxwidth100" type="text" name="search_tasklabel" value="'.dol_escape_htmltag($search_tasklabel).'">';
1014 print '</td>';
1015 }
1016
1017 if (!empty($arrayfields['t.description']['checked'])) {
1018 print '<td class="liste_titre">';
1019 print '<input class="flat searchstring maxwidth100" type="text" name="search_taskdescription" value="'.dol_escape_htmltag($search_taskdescription).'">';
1020 print '</td>';
1021 }
1022
1023 if (!empty($arrayfields['t.dateo']['checked'])) {
1024 print '<td class="liste_titre center">';
1025 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartday" value="'.$search_dtstartday.'">';
1026 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartmonth" value="'.$search_dtstartmonth.'"></span>';
1027 print $formother->selectyear($search_dtstartyear ? $search_dtstartyear : -1, 'search_dtstartyear', 1, 20, 5);*/
1028 print '<div class="nowrapfordate">';
1029 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'));
1030 print '</div>';
1031 print '<div class="nowrapfordate">';
1032 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'));
1033 print '</div>';
1034 print '</td>';
1035 }
1036
1037 if (!empty($arrayfields['t.datee']['checked'])) {
1038 print '<td class="liste_titre center">';
1039 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendday" value="'.$search_dtendday.'">';
1040 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendmonth" value="'.$search_dtendmonth.'"></span>';
1041 print $formother->selectyear($search_dtendyear ? $search_dtendyear : -1, 'search_dtendyear', 1, 20, 5);*/
1042 print '<div class="nowrapfordate">';
1043 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'));
1044 print '</div>';
1045 print '<div class="nowrapfordate">';
1046 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'));
1047 print '</div>';
1048 print '</td>';
1049 }
1050
1051 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1052 print '<td class="liste_titre right">';
1053 print '<input class="flat" type="text" size="4" name="search_planedworkload" value="'.$search_planedworkload.'">';
1054 print '</td>';
1055 }
1056
1057 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1058 print '<td class="liste_titre right">';
1059 print '<input class="flat" type="text" size="4" name="search_timespend" value="'.$search_timespend.'">';
1060 print '</td>';
1061 }
1062
1063 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1064 print '<td class="liste_titre right">';
1065 print '<input class="flat" type="text" size="4" name="search_progresscalc" value="'.$search_progresscalc.'">';
1066 print '</td>';
1067 }
1068
1069 if (!empty($arrayfields['t.progress']['checked'])) {
1070 print '<td class="liste_titre right">';
1071 print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
1072 print '</td>';
1073 }
1074
1075 // progress resume not searchable
1076 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1077 print '<td class="liste_titre right"></td>';
1078 }
1079
1080 if (!empty($arrayfields['t.fk_statut']['checked'])) {
1081 print '<td class="liste_titre center">';
1082 $arrayofstatus = array();
1083 foreach ($taskstatic->labelStatusShort as $key => $val) {
1084 $arrayofstatus[$key] = $langs->trans($val);
1085 }
1086 print $form->selectarray('search_status', $arrayofstatus, $search_status, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100');
1087 print '</td>';
1088 }
1089
1090 if ($object->usage_bill_time) {
1091 if (!empty($arrayfields['t.tobill']['checked'])) {
1092 print '<td class="liste_titre right">';
1093 print '</td>';
1094 }
1095
1096 if (!empty($arrayfields['t.billed']['checked'])) {
1097 print '<td class="liste_titre right">';
1098 print '</td>';
1099 }
1100 }
1101
1102 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1103 print '<td class="liste_titre center">';
1104 print '<input type="text" class="flat" name="search_task_budget_amount" value="'.$search_task_budget_amount.'" size="4">';
1105 print '</td>';
1106 }
1107
1108 if (!empty($arrayfields['c.assigned']['checked'])) {
1109 print '<td class="liste_titre right">';
1110 print '</td>';
1111 }
1112
1113 if (!empty($arrayfields['t.billable']['checked'])) {
1114 print '<td class="liste_titre center">';
1115 print $form->selectyesno('search_task_billable', $search_task_billable, 0, false, 1);
1116 print '</td>';
1117 }
1118
1119 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1120
1121 // Fields from hook
1122 $parameters = array('arrayfields' => $arrayfields);
1123 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1124 print $hookmanager->resPrint;
1125
1126 print '<td class="liste_titre maxwidthsearch">&nbsp;</td>';
1127
1128 // Action column
1129 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1130 print '<td class="liste_titre maxwidthsearch">';
1131 $searchpicto = $form->showFilterButtons();
1132 print $searchpicto;
1133 print '</td>';
1134 }
1135
1136 print "</tr>\n";
1137
1138 print '<tr class="liste_titre nodrag nodrop">';
1139 // Action column
1140 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1141 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1142 }
1143 // print '<td>'.$langs->trans("Project").'</td>';
1144 if (!empty($arrayfields['t.ref']['checked'])) {
1145 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1146 print_liste_field_titre($arrayfields['t.ref']['label'], $_SERVER["PHP_SELF"], 't.ref', '', $param, '', $sortfield, $sortorder, '');
1147 }
1148 if (!empty($arrayfields['t.label']['checked'])) {
1149 print_liste_field_titre($arrayfields['t.label']['label'], $_SERVER["PHP_SELF"], "t.label", '', $param, '', $sortfield, $sortorder, '');
1150 }
1151 if (!empty($arrayfields['t.description']['checked'])) {
1152 print_liste_field_titre($arrayfields['t.description']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, '');
1153 }
1154 if (!empty($arrayfields['t.dateo']['checked'])) {
1155 print_liste_field_titre($arrayfields['t.dateo']['label'], $_SERVER["PHP_SELF"], "t.dateo", '', $param, '', $sortfield, $sortorder, 'center ');
1156 }
1157 if (!empty($arrayfields['t.datee']['checked'])) {
1158 print_liste_field_titre($arrayfields['t.datee']['label'], $_SERVER["PHP_SELF"], "t.datee", '', $param, '', $sortfield, $sortorder, 'center ');
1159 }
1160 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1161 print_liste_field_titre($arrayfields['t.planned_workload']['label'], $_SERVER["PHP_SELF"], "t.planned_workload", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1162 }
1163 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1164 print_liste_field_titre($arrayfields['t.duration_effective']['label'], $_SERVER["PHP_SELF"], "t.duration_effective", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1165 }
1166 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1167 print_liste_field_titre($arrayfields['t.progress_calculated']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1168 }
1169 if (!empty($arrayfields['t.progress']['checked'])) {
1170 print_liste_field_titre($arrayfields['t.progress']['label'], $_SERVER["PHP_SELF"], "t.progress", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1171 }
1172 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1173 print_liste_field_titre($arrayfields['t.progress_summary']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '', 1);
1174 }
1175 if (!empty($arrayfields['t.fk_statut']['checked'])) {
1176 print_liste_field_titre($arrayfields['t.fk_statut']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1177 }
1178 if ($object->usage_bill_time) {
1179 if (!empty($arrayfields['t.tobill']['checked'])) {
1180 print_liste_field_titre($arrayfields['t.tobill']['label'], $_SERVER["PHP_SELF"], "t.tobill", '', $param, '', $sortfield, $sortorder, 'right ');
1181 }
1182 if (!empty($arrayfields['t.billed']['checked'])) {
1183 print_liste_field_titre($arrayfields['t.billed']['label'], $_SERVER["PHP_SELF"], "t.billed", '', $param, '', $sortfield, $sortorder, 'right ');
1184 }
1185 }
1186
1187 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1188 print_liste_field_titre($arrayfields['t.budget_amount']['label'], $_SERVER["PHP_SELF"], "t.budget_amount", "", $param, '', $sortfield, $sortorder, 'center ');
1189 }
1190
1191 if (!empty($arrayfields['c.assigned']['checked'])) {
1192 print_liste_field_titre($arrayfields['c.assigned']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1193 }
1194
1195 if (!empty($arrayfields['t.billable']['checked'])) {
1196 print_liste_field_titre($arrayfields['t.billable']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1197 }
1198
1199 // Extra fields
1200 $disablesortlink = 1;
1201 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1202 // Hook fields
1203 $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
1204 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1205 print $hookmanager->resPrint;
1206 print '<td></td>';
1207 // Action column
1208 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1209 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1210 }
1211 print "</tr>\n";
1212
1213 $nboftaskshown = 0;
1214 if (count($tasksarray) > 0) {
1215 // Show all lines in taskarray (recursive function to go down on tree)
1216 $j = 0;
1217 $level = 0;
1218 $nboftaskshown = projectLinesa($j, 0, $tasksarray, $level, '', 0, $tasksrole, (string) $object->id, 1, $object->id, '', ($object->usage_bill_time ? 1 : 0), $arrayfields, $arrayofselected);
1219 } else {
1220 $colspan = count($arrayfields);
1221 if ($object->usage_bill_time) {
1222 $colspan += 2;
1223 }
1224 print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoTasks").'</span></td></tr>';
1225 }
1226
1227 print "</table>";
1228 print '</div>';
1229
1230 print '</form>';
1231
1232
1233 // Test if database is clean. If not we clean it.
1234 //print 'mode='.$_REQUEST["mode"].' $nboftaskshown='.$nboftaskshown.' count($tasksarray)='.count($tasksarray).' count($tasksrole)='.count($tasksrole).'<br>';
1235 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)
1236 if ($search_user_id == $user->id) {
1237 if ($nboftaskshown < count($tasksrole)) {
1238 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1239 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1240 }
1241 } else {
1242 if ($nboftaskshown < count($tasksarray) && !GETPOSTINT('search_user_id')) {
1243 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1244 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1245 }
1246 }
1247 }
1248}
1249
1250// End of page
1251llxFooter();
1252$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:385
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.