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