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