dolibarr 24.0.0-beta
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-2026 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// Default to no permission
137$permissiontoread = 0;
138$permissiontodelete = 0;
139
140// Default sort order (if not yet defined by previous GETPOST)
141/* if (!$sortfield) {
142 reset($object->fields); $sortfield="t.".key($object->fields);
143} // Set here default search field. By default 1st field in definition. Reset is required to avoid key() to return null.
144if (!$sortorder) {
145 $sortorder = "ASC";
146} */
147
148
149// Security check
150$socid = 0;
151
152// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
153$hookmanager->initHooks(array('projecttaskscard', 'globalcard'));
154
155//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.
156$result = restrictedArea($user, 'projet', $id, 'projet&project');
157
158$diroutputmassaction = $conf->project->dir_output.'/tasks/temp/massgeneration/'.$user->id;
159
160$progress = GETPOSTINT('progress');
161$budget_amount = GETPOSTFLOAT('budget_amount');
162$billable = (GETPOST('billable', 'aZ') == 'yes' ? 1 : 0);
163$label = GETPOST('label', 'alpha');
164$description = GETPOST('description', 'restricthtml');
165$planned_workloadhour = (GETPOSTISSET('planned_workloadhour') ? GETPOSTINT('planned_workloadhour') : '');
166$planned_workloadmin = (GETPOSTISSET('planned_workloadmin') ? GETPOSTINT('planned_workloadmin') : '');
167if (GETPOSTISSET('planned_workloadhour') || GETPOSTISSET('planned_workloadmin')) {
168 $planned_workload = (int) $planned_workloadhour * 3600 + (int) $planned_workloadmin * 60;
169} else {
170 $planned_workload = '';
171}
172
173// Definition of fields for list
174$arrayfields = array(
175 't.ref' => array('label' => "RefTask", 'checked' => '1', 'position' => 1),
176 't.label' => array('label' => "LabelTask", 'checked' => '1', 'position' => 2),
177 't.description' => array('label' => "Description", 'checked' => '0', 'position' => 3),
178 't.dateo' => array('label' => "DateStart", 'checked' => '1', 'position' => 4),
179 't.datee' => array('label' => "Deadline", 'checked' => '1', 'position' => 5),
180 't.planned_workload' => array('label' => "PlannedWorkload", 'checked' => '1', 'position' => 6),
181 't.duration_effective' => array('label' => "TimeSpent", 'checked' => '1', 'position' => 7),
182 't.progress_calculated' => array('label' => "ProgressCalculated", 'checked' => '-1', 'position' => 8),
183 't.progress' => array('label' => "ProgressDeclared", 'checked' => '1', 'position' => 9),
184 't.progress_summary' => array('label' => "TaskProgressSummary", 'checked' => '1', 'position' => 10),
185 't.fk_statut' => array('label' => "Status", 'checked' => '1', 'position' => 11),
186 't.budget_amount' => array('label' => "Budget", 'checked' => '0', 'position' => 12),
187 'c.assigned' => array('label' => "TaskRessourceLinks", 'checked' => '1', 'position' => 13),
188
189);
190if ($object->usage_bill_time) {
191 $arrayfields['t.tobill'] = array('label' => $langs->trans("TimeToBill"), 'checked' => '0', 'position' => 11);
192 $arrayfields['t.billed'] = array('label' => $langs->trans("TimeBilled"), 'checked' => '0', 'position' => 12);
193 $arrayfields['t.billable'] = array('label' => $langs->trans("Billable"), 'checked' => '1', 'position' => 13);
194}
195
196// Extra fields
197$extrafieldsobjectkey = $taskstatic->table_element;
198$extrafieldsobjectprefix = 'efpt.';
199include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
200
201$arrayfields = dol_sort_array($arrayfields, 'position');
202
203$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
204
205
206/*
207 * Actions
208 */
209$error = 0;
210
211if ($cancel) {
212 if (!empty($backtopageforcancel)) {
213 header("Location: ".$backtopageforcancel);
214 exit;
215 } elseif (!empty($backtopage)) {
216 header("Location: ".$backtopage);
217 exit;
218 }
219 $action = 'list';
220 $massaction = '';
221}
222if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
223 $massaction = '';
224}
225
226$parameters = array('id' => $id);
227$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
228if ($reshook < 0) {
229 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
230}
231
232if (empty($reshook)) {
233 // Selection of new fields
234 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
235
236 // Purge search criteria
237 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
238 $search_user_id = "";
239 $search_taskref = '';
240 $search_tasklabel = '';
241 $search_dtstartday = '';
242 $search_dtstartmonth = '';
243 $search_dtstartyear = '';
244 $search_dtendday = '';
245 $search_dtendmonth = '';
246 $search_dtendyear = '';
247 $search_planedworkload = '';
248 $search_timespend = '';
249 $search_progresscalc = '';
250 $search_progressdeclare = '';
251 $search_task_budget_amount = '';
252 $search_task_billable = '';
253 $search_status = -1;
254 $toselect = array();
255 $search_array_options = array();
256 $search_date_start_startmonth = "";
257 $search_date_start_startyear = "";
258 $search_date_start_startday = "";
259 $search_date_start_start = "";
260 $search_date_start_endmonth = "";
261 $search_date_start_endyear = "";
262 $search_date_start_endday = "";
263 $search_date_start_end = "";
264 $search_date_end_startmonth = "";
265 $search_date_end_startyear = "";
266 $search_date_end_startday = "";
267 $search_date_end_start = "";
268 $search_date_end_endmonth = "";
269 $search_date_end_endyear = "";
270 $search_date_end_endday = "";
271 $search_date_end_end = "";
272 }
273
274 // Mass actions
275 $objectclass = 'Task';
276 $objectlabel = 'Tasks';
277 $permissiontoread = $user->hasRight('projet', 'lire');
278 $permissiontodelete = $user->hasRight('projet', 'supprimer');
279 $uploaddir = $conf->project->dir_output.'/tasks';
280 include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
281}
282
283$morewherefilterarray = array();
284
285if (!empty($search_taskref)) {
286 $morewherefilterarray[] = natural_search('t.ref', $search_taskref, 0, 1);
287}
288
289if (!empty($search_tasklabel)) {
290 $morewherefilterarray[] = natural_search('t.label', $search_tasklabel, 0, 1);
291}
292
293$moresql = dolSqlDateFilter('t.dateo', $search_dtstartday, $search_dtstartmonth, $search_dtstartyear, 1);
294if ($moresql) {
295 $morewherefilterarray[] = $moresql;
296}
297
298$moresql = dolSqlDateFilter('t.datee', $search_dtendday, $search_dtendmonth, $search_dtendyear, 1);
299if ($moresql) {
300 $morewherefilterarray[] = $moresql;
301}
302
303if ($search_date_start_start) {
304 $morewherefilterarray[] = " t.dateo >= '".$db->idate($search_date_start_start)."'";
305}
306if ($search_date_start_end) {
307 $morewherefilterarray[] = " t.dateo <= '".$db->idate($search_date_start_end)."'";
308}
309
310if ($search_date_end_start) {
311 $morewherefilterarray[] = " t.datee >= '".$db->idate($search_date_end_start)."'";
312}
313if ($search_date_end_end) {
314 $morewherefilterarray[] = " t.datee <= '".$db->idate($search_date_end_end)."'";
315}
316
317if (!empty($search_planedworkload)) {
318 $morewherefilterarray[] = natural_search('t.planned_workload', $search_planedworkload, 1, 1);
319}
320
321if (!empty($search_timespend)) {
322 $morewherefilterarray[] = natural_search('t.duration_effective', $search_timespend, 1, 1);
323}
324
325if (!empty($search_progressdeclare)) {
326 $morewherefilterarray[] = natural_search('t.progress', $search_progressdeclare, 1, 1);
327}
328if (!empty($search_progresscalc)) {
329 $morewherefilterarray[] = '(planned_workload IS NULL OR planned_workload = 0 OR '.natural_search('ROUND(100 * duration_effective / planned_workload, 2)', $search_progresscalc, 1, 1).')';
330 //natural_search('round(100 * $line->duration_effective / $line->planned_workload,2)', $filterprogresscalc, 1, 1).' {return 1;} else {return 0;}';
331}
332if ($search_status > -1 && $search_status != '') {
333 $morewherefilterarray[] = " t.fk_statut = ".((int) $search_status);
334}
335if ($search_task_budget_amount) {
336 $morewherefilterarray[] = natural_search('t.budget_amount', $search_task_budget_amount, 1, 1);
337}
338if ($search_task_billable && $search_task_billable != '-1') {
339 $morewherefilterarray[] = " t.billable = ".($search_task_billable == "yes" ? 1 : 0);
340}
341//var_dump($morewherefilterarray);
342
343$morewherefilter = '';
344if (count($morewherefilterarray) > 0) {
345 $morewherefilter = ' AND '.implode(' AND ', $morewherefilterarray);
346}
347
348if ($action == 'createtask' && $user->hasRight('projet', 'creer')) {
349 // If we use user timezone, we must change also view/list to use user timezone everywhere
350 $date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), 0, GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
351 $date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), 0, GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
352
353 if (!$cancel) {
354 if (empty($taskref)) {
355 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
356 $action = 'create';
357 $error++;
358 }
359 if (empty($label)) {
360 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
361 $action = 'create';
362 $error++;
363 } elseif (!GETPOST('task_parent')) {
364 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ChildOfProjectTask")), null, 'errors');
365 $action = 'create';
366 $error++;
367 }
368
369 if (!$error) {
370 $tmparray = explode('_', GETPOST('task_parent'));
371 $projectid = empty($tmparray[0]) ? $id : (int) $tmparray[0];
372 $task_parent = empty($tmparray[1]) ? 0 : $tmparray[1];
373
374 $task = new Task($db);
375
376 $task->fk_project = $projectid;
377 $task->entity = $object->entity; // Task have the same entity of project
378 $task->ref = $taskref;
379 $task->label = $label;
380 $task->description = $description;
381 $task->planned_workload = $planned_workload;
382 $task->fk_task_parent = $task_parent;
383 $task->date_c = dol_now();
384 $task->date_start = $date_start;
385 $task->date_end = $date_end;
386 $task->progress = $progress;
387 $task->budget_amount = $budget_amount;
388 $task->billable = $billable;
389 $task->status = Task::STATUS_VALIDATED;
390
391 // Fill array 'array_options' with data from add form
392 $ret = $extrafields->setOptionalsFromPost(null, $task);
393
394 $taskid = $task->create($user);
395
396 if ($taskid > 0) {
397 $userid = GETPOSTINT("userid");
398 if ($userid == -4) {
399 if (empty($object->id)) {
400 $object->fetch($projectid);
401 }
402 $contactlist = array();
403 foreach (array('internal', 'external') as $source) {
404 $contactlist = array_merge($contactlist, $object->liste_contact(-1, $source));
405 }
406 foreach ($contactlist as $key => $contact) {
407 $result = $task->add_contact(((int) $contact["id"]), ($contact["code"] == "PROJECTLEADER" ? 'TASKEXECUTIVE' : "TASKCONTRIBUTOR"), $contact["source"]);
408 }
409 } else {
410 $result = $task->add_contact(GETPOSTINT("userid"), 'TASKEXECUTIVE', 'internal');
411 }
412 } else {
413 if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
414 $langs->load("projects");
415 setEventMessages($langs->trans('NewTaskRefSuggested'), null, 'warnings');
416 $duplicate_code_error = true;
417 } else {
418 setEventMessages($task->error, $task->errors, 'errors');
419 }
420 $action = 'create';
421 $error++;
422 }
423 }
424
425 if (!$error) {
426 if (!empty($backtopage)) {
427 header("Location: ".$backtopage);
428 exit;
429 } elseif (empty($projectid)) {
430 header("Location: ".DOL_URL_ROOT.'/projet/tasks/list.php'.(empty($mode) ? '' : '?mode='.$mode));
431 exit;
432 }
433 $id = $projectid;
434 }
435 } else {
436 if (!empty($backtopage)) {
437 header("Location: ".$backtopage);
438 exit;
439 } elseif (empty($id)) {
440 // We go back on task list
441 header("Location: ".DOL_URL_ROOT.'/projet/tasks/list.php'.(empty($mode) ? '' : '?mode='.$mode));
442 exit;
443 }
444 }
445}
446
447/*
448 * View
449 */
450
451$now = dol_now();
452$form = new Form($db);
453$formother = new FormOther($db);
454$socstatic = new Societe($db);
455$projectstatic = new Project($db);
456$taskstatic = new Task($db);
457$userstatic = new User($db);
458
459$title = $langs->trans("Tasks").' - '.$object->ref.' '.$object->name;
460if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/projectnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->name) {
461 $title = $object->ref.' '.$object->name.' - '.$langs->trans("Tasks");
462}
463if ($action == 'create') {
464 $title = $langs->trans("NewTask");
465}
466$help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
467
468llxHeader("", $title, $help_url, '', 0, 0, '', '', '', 'mod-project page-card_tasks');
469
470$arrayofselected = is_array($toselect) ? $toselect : array();
471$param = '';
472$userWrite = 0;
473$massactionbutton = '';
474
475if ($id > 0 || !empty($ref)) {
476 $result = $object->fetch($id, $ref);
477 if ($result < 0) {
478 setEventMessages(null, $object->errors, 'errors');
479 }
480 $result = $object->fetch_thirdparty();
481 if ($result < 0) {
482 setEventMessages(null, $object->errors, 'errors');
483 }
484 $result = $object->fetch_optionals();
485 if ($result < 0) {
486 setEventMessages(null, $object->errors, 'errors');
487 }
488
489
490 // To verify role of users
491 //$userAccess = $object->restrictedProjectArea($user,'read');
492 $userWrite = $object->restrictedProjectArea($user, 'write');
493 //$userDelete = $object->restrictedProjectArea($user,'delete');
494 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
495
496
497 $tab = (GETPOSTISSET('tab') ? GETPOST('tab') : 'tasks');
498
499 $head = project_prepare_head($object);
500 print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
501
502 $param = '&id='.$object->id;
503 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
504 $param .= '&contextpage='.urlencode($contextpage);
505 }
506 if ($search_user_id) {
507 $param .= '&search_user_id='.urlencode((string) ($search_user_id));
508 }
509 if ($search_taskref) {
510 $param .= '&search_taskref='.urlencode($search_taskref);
511 }
512 if ($search_tasklabel) {
513 $param .= '&search_tasklabel='.urlencode($search_tasklabel);
514 }
515 if ($search_taskdescription) {
516 $param .= '&search_taskdescription='.urlencode($search_taskdescription);
517 }
518 if ($search_dtstartday) {
519 $param .= '&search_dtstartday='.urlencode($search_dtstartday);
520 }
521 if ($search_dtstartmonth) {
522 $param .= '&search_dtstartmonth='.urlencode($search_dtstartmonth);
523 }
524 if ($search_dtstartyear) {
525 $param .= '&search_dtstartyear='.urlencode($search_dtstartyear);
526 }
527 if ($search_dtendday) {
528 $param .= '&search_dtendday='.urlencode($search_dtendday);
529 }
530 if ($search_dtendmonth) {
531 $param .= '&search_dtendmonth='.urlencode($search_dtendmonth);
532 }
533 if ($search_dtendyear) {
534 $param .= '&search_dtendyear='.urlencode($search_dtendyear);
535 }
536 if ($search_date_start_startmonth) {
537 $param .= '&search_date_start_startmonth='.urlencode((string) ($search_date_start_startmonth));
538 }
539 if ($search_date_start_startyear) {
540 $param .= '&search_date_start_startyear='.urlencode((string) ($search_date_start_startyear));
541 }
542 if ($search_date_start_startday) {
543 $param .= '&search_date_start_startday='.urlencode((string) ($search_date_start_startday));
544 }
545 if ($search_date_start_start) {
546 $param .= '&search_date_start_start='.urlencode((string) $search_date_start_start);
547 }
548 if ($search_date_start_endmonth) {
549 $param .= '&search_date_start_endmonth='.urlencode((string) ($search_date_start_endmonth));
550 }
551 if ($search_date_start_endyear) {
552 $param .= '&search_date_start_endyear='.urlencode((string) ($search_date_start_endyear));
553 }
554 if ($search_date_start_endday) {
555 $param .= '&search_date_start_endday='.urlencode((string) ($search_date_start_endday));
556 }
557 if ($search_date_start_end) {
558 $param .= '&search_date_start_end='.urlencode((string) $search_date_start_end);
559 }
560 if ($search_date_end_startmonth) {
561 $param .= '&search_date_end_startmonth='.urlencode((string) ($search_date_end_startmonth));
562 }
563 if ($search_date_end_startyear) {
564 $param .= '&search_date_end_startyear='.urlencode((string) ($search_date_end_startyear));
565 }
566 if ($search_date_end_startday) {
567 $param .= '&search_date_end_startday='.urlencode((string) ($search_date_end_startday));
568 }
569 if ($search_date_end_start) {
570 $param .= '&search_date_end_start='.urlencode((string) $search_date_end_start);
571 }
572 if ($search_date_end_endmonth) {
573 $param .= '&search_date_end_endmonth='.urlencode((string) ($search_date_end_endmonth));
574 }
575 if ($search_date_end_endyear) {
576 $param .= '&search_date_end_endyear='.urlencode((string) ($search_date_end_endyear));
577 }
578 if ($search_date_end_endday) {
579 $param .= '&search_date_end_endday='.urlencode((string) ($search_date_end_endday));
580 }
581 if ($search_date_end_end) {
582 $param .= '&search_date_end_end=' . urlencode((string) $search_date_end_end);
583 }
584 if ($search_planedworkload) {
585 $param .= '&search_planedworkload='.urlencode($search_planedworkload);
586 }
587 if ($search_timespend) {
588 $param .= '&search_timespend='.urlencode($search_timespend);
589 }
590 if ($search_progresscalc) {
591 $param .= '&search_progresscalc='.urlencode($search_progresscalc);
592 }
593 if ($search_progressdeclare) {
594 $param .= '&search_progressdeclare='.urlencode($search_progressdeclare);
595 }
596 if ($search_status) {
597 $param .= '&search_status='.urlencode((string) ($search_status));
598 }
599 if ($search_task_budget_amount) {
600 $param .= '&search_task_budget_amount='.urlencode($search_task_budget_amount);
601 }
602 if ($search_task_billable) {
603 $param .= '&search_task_billable='.urlencode($search_task_billable);
604 }
605 if ($optioncss != '') {
606 $param .= '&optioncss='.urlencode($optioncss);
607 }
608 // Add $param from extra fields
609 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
610
611 $arrayofmassactions = array();
612 if ($user->hasRight('projet', 'creer')) {
613 $arrayofmassactions['preclonetasks'] = img_picto('', 'clone', 'class="pictofixedwidth"').$langs->trans("Clone");
614 }
615 if ($permissiontodelete) {
616 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
617 }
618 if (in_array($massaction, array('presend', 'predelete'))) {
619 $arrayofmassactions = array();
620 }
621 $massactionbutton = $form->selectMassAction('', $arrayofmassactions) ?? '';
622
623 // Project card
624
625 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
626 $tmpurl = $_SESSION['pageforbacktolist']['project'];
627 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
628 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
629 } else {
630 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
631 }
632
633 $morehtmlref = '<div class="refidno">';
634 // Title
635 $morehtmlref .= $object->title;
636 // Thirdparty
637 if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
638 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1, 'project');
639 }
640 $morehtmlref .= '</div>';
641
642 // Define a complementary filter for search of next/prev ref.
643 if (!$user->hasRight('projet', 'all', 'lire')) {
644 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
645 $object->next_prev_filter = "rowid:IN:".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0');
646 }
647
648 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
649
650 print '<div class="fichecenter">';
651 print '<div class="fichehalfleft">';
652 print '<div class="underbanner clearboth"></div>';
653
654 print '<table class="border tableforfield centpercent">';
655
656 // Usage
657 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
658 print '<tr><td class="tdtop">';
659 print $langs->trans("Usage");
660 print '</td>';
661 print '<td>';
662 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
663 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
664 $htmltext = $langs->trans("ProjectFollowOpportunity");
665 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
666 print '<br>';
667 }
668 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
669 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
670 $htmltext = $langs->trans("ProjectFollowTasks");
671 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
672 print '<br>';
673 }
674 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
675 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"' : '')).'"> ';
676 $htmltext = $langs->trans("ProjectBillTimeDescription");
677 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
678 print '<br>';
679 }
680 if (isModEnabled('eventorganization')) {
681 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"' : '')).'"> ';
682 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
683 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
684 }
685 print '</td></tr>';
686 }
687
688 // Budget
689 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
690 if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
691 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
692 }
693 print '</td></tr>';
694
695 // Date start - end project
696 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
697 $start = dol_print_date($object->date_start, 'day');
698 print($start ? $start : '?');
699 $end = dol_print_date($object->date_end, 'day');
700 print ' - ';
701 print($end ? $end : '?');
702 if ($object->hasDelay()) {
703 print img_warning("Late");
704 }
705 print '</td></tr>';
706
707 // Visibility
708 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
709 if ($object->public) {
710 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
711 print $langs->trans('SharedProject');
712 } else {
713 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
714 print $langs->trans('PrivateProject');
715 }
716 print '</td></tr>';
717
718 // Other attributes
719 $cols = 2;
720 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
721
722 print '</table>';
723
724 print '</div>';
725 print '<div class="fichehalfright">';
726 print '<div class="underbanner clearboth"></div>';
727
728 print '<table class="border tableforfield centpercent">';
729
730 // Categories
731 if (isModEnabled('category')) {
732 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
733 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
734 print "</td></tr>";
735 }
736
737 // Description
738 print '<tr><td class="titlefield'.($object->description ? ' noborderbottom' : '').'" colspan="2">'.$langs->trans("Description").'</td></tr>';
739 if ($object->description) {
740 print '<tr><td class="nottitleforfield" colspan="2">';
741 print '<div class="longmessagecut">';
742 print dolPrintHTML($object->description);
743 print '</div>';
744 print '</td></tr>';
745 }
746
747 print '</table>';
748
749 print '</div>';
750 print '</div>';
751
752 print '<div class="clearboth"></div>';
753
754
755 print dol_get_fiche_end();
756}
757
758
759if ($action == 'create' && $user->hasRight('projet', 'creer') && (empty($object->thirdparty->id) || $userWrite > 0)) {
760 if ($id > 0 || !empty($ref)) {
761 print '<br>';
762 }
763
764 print load_fiche_titre($langs->trans("NewTask"), '', 'projecttask');
765
766 $projectoktoentertime = 1;
767 if ($object->id > 0 && $object->status == Project::STATUS_CLOSED) {
768 $projectoktoentertime = 0;
769 print '<div class="warning">';
770 $langs->load("errors");
771 print $langs->trans("WarningProjectClosed");
772 print '</div>';
773 }
774
775 if ($object->id > 0 && $object->status == Project::STATUS_DRAFT) {
776 $projectoktoentertime = 0;
777 print '<div class="warning">';
778 $langs->load("errors");
779 print $langs->trans("WarningProjectDraft");
780 print '</div>';
781 }
782
783 print '<form action="'.$_SERVER['PHP_SELF'].'" method="POST">';
784 print '<input type="hidden" name="token" value="'.newToken().'">';
785 print '<input type="hidden" name="action" value="createtask">';
786 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
787 if (!empty($object->id)) {
788 print '<input type="hidden" name="id" value="'.$object->id.'">';
789 }
790
791 print dol_get_fiche_head();
792
793 print '<div class="div-table-responsive-no-min">';
794 print '<table class="border centpercent">';
795
796 $defaultref = '';
797 $classnamemodtask = getDolGlobalString('PROJECT_TASK_ADDON', 'mod_task_simple');
798 if (getDolGlobalString('PROJECT_TASK_ADDON') && is_readable(DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').".php")) {
799 require_once DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').'.php';
800 $modTask = new $classnamemodtask();
801 '@phan-var-force ModeleNumRefTask $modTask';
802 $defaultref = $modTask->getNextValue($object->thirdparty, $object);
803 }
804
805 if (is_numeric($defaultref) && $defaultref <= 0) {
806 $defaultref = '';
807 }
808
809 // Ref
810 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
811 if (empty($duplicate_code_error)) {
812 print(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref);
813 } else {
814 print $defaultref;
815 }
816 print '<input type="hidden" name="taskref" value="'.(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref).'">';
817 print '</td></tr>';
818
819 // Label
820 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td>';
821 print '<input type="text" name="label" autofocus class="minwidth500" value="'.$label.'">';
822 print '</td></tr>';
823
824 // Project
825 print '<tr><td class="fieldrequired">'.$langs->trans("ChildOfProjectTask").'</td><td>';
826 print img_picto('', 'project', 'class="pictofixedwidth"');
827 if ($projectoktoentertime) {
828 $formother->selectProjectTasks(GETPOSTINT('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '0,1', 'maxwidth500 widthcentpercentminusxx');
829 } else {
830 $formother->selectProjectTasks(GETPOSTINT('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '', 'maxwidth500 widthcentpercentminusxx');
831 }
832 print '</td></tr>';
833
834 $contactsofproject = (empty($object->id) ? '' : $object->getListContactId('internal'));
835
836 // Assigned to
837 print '<tr><td>'.$langs->trans("AffectedTo").'</td><td>';
838 print img_picto('', 'user', 'class="pictofixedwidth"');
839 if (is_array($contactsofproject) && count($contactsofproject)) {
840 print $form->select_dolusers('-4', 'userid', 0, null, 0, '', $contactsofproject, '0', 0, 0, '(statut:=:1)', 4, '', 'maxwidth500 widthcentpercentminusx');
841 } else {
842 if ((isset($projectid) && $projectid > 0) || $object->id > 0) {
843 print '<span class="opacitymedium">'.$langs->trans("NoUserAssignedToTheProject").'</span>';
844 } else {
845 print $form->select_dolusers('-4', 'userid', 0, null, 0, '', '', '0', 0, 0, '(statut:=:1)', 4, '', 'maxwidth500 widthcentpercentminusx');
846 }
847 }
848 print '</td></tr>';
849
850 // Billable
851 print '<tr><td>'.$langs->trans("Billable").'</td><td>';
852 print $form->selectyesno('billable');
853 print '</td></tr>';
854
855 // Date start task
856 print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
857 print img_picto('', 'action', 'class="pictofixedwidth"');
858 print $form->selectDate((!empty($date_start) ? $date_start : ''), 'date_start', 1, 1, 0, '', 1, 1);
859 print '</td></tr>';
860
861 // Date end task
862 print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
863 print img_picto('', 'action', 'class="pictofixedwidth"');
864 print $form->selectDate((!empty($date_end) ? $date_end : -1), 'date_end', -1, 1, 0, '', 1, 1);
865 print '</td></tr>';
866
867 // Planned workload
868 print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td>';
869 print img_picto('', 'clock', 'class="pictofixedwidth"');
870 print $form->select_duration('planned_workload', $planned_workload, 0, 'text');
871 print '</td></tr>';
872
873 // Progress
874 print '<tr><td>'.$langs->trans("ProgressDeclared").'</td><td colspan="3">';
875 print img_picto('', 'fa-percent', 'class="pictofixedwidth"');
876 print $formother->select_percent($progress, 'progress', 0, 5, 0, 100, 1);
877 print '</td></tr>';
878
879 // Description
880 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
881 print '<td>';
882
883 // WYSIWYG editor
884 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
885 $nbrows = 0;
886 if (getDolGlobalString('MAIN_INPUT_DESC_HEIGHT')) {
887 $nbrows = getDolGlobalString('MAIN_INPUT_DESC_HEIGHT');
888 }
889 $doleditor = new DolEditor('description', $object->description, '', 80, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), $nbrows, '90%');
890 print $doleditor->Create();
891
892 print '</td></tr>';
893
894 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
895 print img_picto('', 'currency', 'class="pictofixedwidth"');
896 print '<input size="8" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'"></td>';
897 print '</tr>';
898
899 // Other options
900 $parameters = array('arrayfields' => &$arrayfields);
901 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $taskstatic, $action); // Note that $action and $object may have been modified by hook
902 print $hookmanager->resPrint;
903
904 if (empty($reshook) && !empty($extrafields->attributes[$taskstatic->table_element]['label'])) {
905 print $taskstatic->showOptionals($extrafields, 'edit'); // Do not use $object here that is object of project but use $taskstatic
906 }
907
908 print '</table>';
909 print '</div>';
910
911 print dol_get_fiche_end();
912
913 print $form->buttonsSaveCancel("Add");
914
915 print '</form>';
916} elseif ($id > 0 || !empty($ref)) {
917 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, $conf->main_checkbox_left_column); // This also change content of $arrayfields
918
919 // Projet card in view mode
920
921 print '<br>';
922
923 // Link to create task
924 $linktocreatetaskParam = array();
925 $linktocreatetaskUserRight = false;
926 if ($user->hasRight('projet', 'all', 'creer') || $user->hasRight('projet', 'creer')) {
927 if ($object->public || $userWrite > 0) {
928 $linktocreatetaskUserRight = true;
929 } else {
930 $linktocreatetaskParam['attr']['title'] = $langs->trans("NotOwnerOfProject");
931 }
932 }
933
934 $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);
935
936 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
937 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
938 print '<input type="hidden" name="token" value="'.newToken().'">';
939 print '<input type="hidden" name="action" value="list">';
940 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
941 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
942 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
943 print '<input type="hidden" name="page" value="'.$page.'">';
944 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
945
946 $title = $langs->trans("ListOfTasks");
947 $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss' => 'reposition btnTitleSelected'));
948 $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'));
949
950 //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1);
951 print load_fiche_titre($title, $linktotasks.' &nbsp; '.$linktocreatetask, 'projecttask', 0, '', '', $massactionbutton);
952
953 $objecttmp = new Task($db);
954 $trackid = 'task'.$taskstatic->id;
955 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
956
957 // Get list of tasks in tasksarray and taskarrayfiltered
958 // 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).
959 $filteronthirdpartyid = $socid;
960 $tasksarray = $taskstatic->getTasksArray(null, null, $object->id, $filteronthirdpartyid, 0, '', '-1', $morewherefilter, 0, 0, $extrafields, 1, $search_array_options, 1, 1, $sortfield, $sortorder);
961
962 // We load also tasks limited to a particular user
963 $tmpuser = new User($db);
964 if ($search_user_id > 0) {
965 $tmpuser->fetch($search_user_id);
966 }
967
968 $tasksrole = ($tmpuser->id > 0 ? $taskstatic->getUserRolesForProjectsOrTasks(null, $tmpuser, (string) $object->id, 0) : '');
969 //var_dump($tasksarray);
970 //var_dump($tasksrole);
971
972 if (!empty($conf->use_javascript_ajax)) {
973 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
974 }
975
976 // Filter on assigned users
977 $moreforfilter = '';
978 $moreforfilter .= '<div class="divsearchfield">';
979 $moreforfilter .= img_picto('', 'user', 'class="pictofixedwidth"');
980 $moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', $langs->trans("TasksAssignedTo"), null, 0, '', '');
981 $moreforfilter .= '</div>';
982 if ($moreforfilter) {
983 print '<div class="liste_titre liste_titre_bydiv centpercent">';
984 print $moreforfilter;
985 print '</div>';
986 }
987
988 // Show the massaction checkboxes only when this page is not opened from the Extended POS
989 if (!empty($massactionbutton) && $contextpage != 'poslist') {
990 $selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
991 }
992
993 print '<div class="div-table-responsive">';
994 print '<table id="tablelines" class="tagtable nobottom liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
995
996 // Fields title search
997 print '<tr class="liste_titre_filter">';
998
999 // Action column
1000 if ($conf->main_checkbox_left_column) {
1001 print '<td class="liste_titre maxwidthsearch">';
1002 $searchpicto = $form->showFilterButtons();
1003 print $searchpicto;
1004 print '</td>';
1005 }
1006
1007 if (!empty($arrayfields['t.ref']['checked'])) {
1008 print '<td class="liste_titre">';
1009 print '<input class="flat searchstring maxwidth50" type="text" name="search_taskref" value="'.dol_escape_htmltag($search_taskref).'">';
1010 print '</td>';
1011 }
1012
1013 if (!empty($arrayfields['t.label']['checked'])) {
1014 print '<td class="liste_titre">';
1015 print '<input class="flat searchstring maxwidth100" type="text" name="search_tasklabel" value="'.dol_escape_htmltag($search_tasklabel).'">';
1016 print '</td>';
1017 }
1018
1019 if (!empty($arrayfields['t.description']['checked'])) {
1020 print '<td class="liste_titre">';
1021 print '<input class="flat searchstring maxwidth100" type="text" name="search_taskdescription" value="'.dol_escape_htmltag($search_taskdescription).'">';
1022 print '</td>';
1023 }
1024
1025 if (!empty($arrayfields['t.dateo']['checked'])) {
1026 print '<td class="liste_titre center">';
1027 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartday" value="'.$search_dtstartday.'">';
1028 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartmonth" value="'.$search_dtstartmonth.'"></span>';
1029 print $formother->selectyear($search_dtstartyear ? $search_dtstartyear : -1, 'search_dtstartyear', 1, 20, 5);*/
1030 print '<div class="nowrapfordate">';
1031 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'));
1032 print '</div>';
1033 print '<div class="nowrapfordate">';
1034 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'));
1035 print '</div>';
1036 print '</td>';
1037 }
1038
1039 if (!empty($arrayfields['t.datee']['checked'])) {
1040 print '<td class="liste_titre center">';
1041 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendday" value="'.$search_dtendday.'">';
1042 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendmonth" value="'.$search_dtendmonth.'"></span>';
1043 print $formother->selectyear($search_dtendyear ? $search_dtendyear : -1, 'search_dtendyear', 1, 20, 5);*/
1044 print '<div class="nowrapfordate">';
1045 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'));
1046 print '</div>';
1047 print '<div class="nowrapfordate">';
1048 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'));
1049 print '</div>';
1050 print '</td>';
1051 }
1052
1053 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1054 print '<td class="liste_titre right">';
1055 print '<input class="flat" type="text" size="4" name="search_planedworkload" value="'.$search_planedworkload.'">';
1056 print '</td>';
1057 }
1058
1059 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1060 print '<td class="liste_titre right">';
1061 print '<input class="flat" type="text" size="4" name="search_timespend" value="'.$search_timespend.'">';
1062 print '</td>';
1063 }
1064
1065 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1066 print '<td class="liste_titre right">';
1067 print '<input class="flat" type="text" size="4" name="search_progresscalc" value="'.$search_progresscalc.'">';
1068 print '</td>';
1069 }
1070
1071 if (!empty($arrayfields['t.progress']['checked'])) {
1072 print '<td class="liste_titre right">';
1073 print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
1074 print '</td>';
1075 }
1076
1077 // progress resume not searchable
1078 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1079 print '<td class="liste_titre right"></td>';
1080 }
1081
1082 if (!empty($arrayfields['t.fk_statut']['checked'])) {
1083 print '<td class="liste_titre center">';
1084 $arrayofstatus = array();
1085 foreach ($taskstatic->labelStatusShort as $key => $val) {
1086 $arrayofstatus[$key] = $langs->trans($val);
1087 }
1088 print $form->selectarray('search_status', $arrayofstatus, $search_status, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100');
1089 print '</td>';
1090 }
1091
1092 if ($object->usage_bill_time) {
1093 if (!empty($arrayfields['t.tobill']['checked'])) {
1094 print '<td class="liste_titre right">';
1095 print '</td>';
1096 }
1097
1098 if (!empty($arrayfields['t.billed']['checked'])) {
1099 print '<td class="liste_titre right">';
1100 print '</td>';
1101 }
1102 }
1103
1104 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1105 print '<td class="liste_titre center">';
1106 print '<input type="text" class="flat" name="search_task_budget_amount" value="'.$search_task_budget_amount.'" size="4">';
1107 print '</td>';
1108 }
1109
1110 if (!empty($arrayfields['c.assigned']['checked'])) {
1111 print '<td class="liste_titre right">';
1112 print '</td>';
1113 }
1114
1115 if (!empty($arrayfields['t.billable']['checked'])) {
1116 print '<td class="liste_titre center">';
1117 print $form->selectyesno('search_task_billable', $search_task_billable, 0, false, 1);
1118 print '</td>';
1119 }
1120
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 (!$conf->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 ($conf->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 (!$conf->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 to help generate other html components 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:386
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
$date_start
Variables from include:
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.
dolPrintHTML($s, $allowiframe=0, $moreallowedtags=array())
Return a string (that can be on several lines) ready to be output on a HTML page.
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.
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.