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