dolibarr 21.0.0-beta
tasks.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2024 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) {
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
452if ($id > 0 || !empty($ref)) {
453 $result = $object->fetch($id, $ref);
454 if ($result < 0) {
455 setEventMessages(null, $object->errors, 'errors');
456 }
457 $result = $object->fetch_thirdparty();
458 if ($result < 0) {
459 setEventMessages(null, $object->errors, 'errors');
460 }
461 $result = $object->fetch_optionals();
462 if ($result < 0) {
463 setEventMessages(null, $object->errors, 'errors');
464 }
465
466
467 // To verify role of users
468 //$userAccess = $object->restrictedProjectArea($user,'read');
469 $userWrite = $object->restrictedProjectArea($user, 'write');
470 //$userDelete = $object->restrictedProjectArea($user,'delete');
471 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
472
473
474 $tab = (GETPOSTISSET('tab') ? GETPOST('tab') : 'tasks');
475
476 $head = project_prepare_head($object);
477 print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
478
479 $param = '&id='.$object->id;
480 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
481 $param .= '&contextpage='.urlencode($contextpage);
482 }
483 if ($search_user_id) {
484 $param .= '&search_user_id='.urlencode((string) ($search_user_id));
485 }
486 if ($search_taskref) {
487 $param .= '&search_taskref='.urlencode($search_taskref);
488 }
489 if ($search_tasklabel) {
490 $param .= '&search_tasklabel='.urlencode($search_tasklabel);
491 }
492 if ($search_taskdescription) {
493 $param .= '&search_taskdescription='.urlencode($search_taskdescription);
494 }
495 if ($search_dtstartday) {
496 $param .= '&search_dtstartday='.urlencode($search_dtstartday);
497 }
498 if ($search_dtstartmonth) {
499 $param .= '&search_dtstartmonth='.urlencode($search_dtstartmonth);
500 }
501 if ($search_dtstartyear) {
502 $param .= '&search_dtstartyear='.urlencode($search_dtstartyear);
503 }
504 if ($search_dtendday) {
505 $param .= '&search_dtendday='.urlencode($search_dtendday);
506 }
507 if ($search_dtendmonth) {
508 $param .= '&search_dtendmonth='.urlencode($search_dtendmonth);
509 }
510 if ($search_dtendyear) {
511 $param .= '&search_dtendyear='.urlencode($search_dtendyear);
512 }
513 if ($search_date_start_startmonth) {
514 $param .= '&search_date_start_startmonth='.urlencode((string) ($search_date_start_startmonth));
515 }
516 if ($search_date_start_startyear) {
517 $param .= '&search_date_start_startyear='.urlencode((string) ($search_date_start_startyear));
518 }
519 if ($search_date_start_startday) {
520 $param .= '&search_date_start_startday='.urlencode((string) ($search_date_start_startday));
521 }
522 if ($search_date_start_start) {
523 $param .= '&search_date_start_start='.urlencode($search_date_start_start);
524 }
525 if ($search_date_start_endmonth) {
526 $param .= '&search_date_start_endmonth='.urlencode((string) ($search_date_start_endmonth));
527 }
528 if ($search_date_start_endyear) {
529 $param .= '&search_date_start_endyear='.urlencode((string) ($search_date_start_endyear));
530 }
531 if ($search_date_start_endday) {
532 $param .= '&search_date_start_endday='.urlencode((string) ($search_date_start_endday));
533 }
534 if ($search_date_start_end) {
535 $param .= '&search_date_start_end='.urlencode($search_date_start_end);
536 }
537 if ($search_date_end_startmonth) {
538 $param .= '&search_date_end_startmonth='.urlencode((string) ($search_date_end_startmonth));
539 }
540 if ($search_date_end_startyear) {
541 $param .= '&search_date_end_startyear='.urlencode((string) ($search_date_end_startyear));
542 }
543 if ($search_date_end_startday) {
544 $param .= '&search_date_end_startday='.urlencode((string) ($search_date_end_startday));
545 }
546 if ($search_date_end_start) {
547 $param .= '&search_date_end_start='.urlencode($search_date_end_start);
548 }
549 if ($search_date_end_endmonth) {
550 $param .= '&search_date_end_endmonth='.urlencode((string) ($search_date_end_endmonth));
551 }
552 if ($search_date_end_endyear) {
553 $param .= '&search_date_end_endyear='.urlencode((string) ($search_date_end_endyear));
554 }
555 if ($search_date_end_endday) {
556 $param .= '&search_date_end_endday='.urlencode((string) ($search_date_end_endday));
557 }
558 if ($search_date_end_end) {
559 $param .= '&search_date_end_end=' . urlencode($search_date_end_end);
560 }
561 if ($search_planedworkload) {
562 $param .= '&search_planedworkload='.urlencode($search_planedworkload);
563 }
564 if ($search_timespend) {
565 $param .= '&search_timespend='.urlencode($search_timespend);
566 }
567 if ($search_progresscalc) {
568 $param .= '&search_progresscalc='.urlencode($search_progresscalc);
569 }
570 if ($search_progressdeclare) {
571 $param .= '&search_progressdeclare='.urlencode($search_progressdeclare);
572 }
573 if ($search_task_budget_amount) {
574 $param .= '&search_task_budget_amount='.urlencode($search_task_budget_amount);
575 }
576 if ($search_task_billable) {
577 $param .= '&search_task_billable='.urlencode($search_task_billable);
578 }
579 if ($optioncss != '') {
580 $param .= '&optioncss='.urlencode($optioncss);
581 }
582 // Add $param from extra fields
583 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
584
585 $arrayofmassactions = array();
586 if ($user->hasRight('projet', 'creer')) {
587 $arrayofmassactions['preclonetasks'] = img_picto('', 'clone', 'class="pictofixedwidth"').$langs->trans("Clone");
588 }
589 if ($permissiontodelete) {
590 $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
591 }
592 if (in_array($massaction, array('presend', 'predelete'))) {
593 $arrayofmassactions = array();
594 }
595 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
596
597 // Project card
598
599 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
600 $tmpurl = $_SESSION['pageforbacktolist']['project'];
601 $tmpurl = preg_replace('/__SOCID__/', (string) $object->socid, $tmpurl);
602 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
603 } else {
604 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
605 }
606
607 $morehtmlref = '<div class="refidno">';
608 // Title
609 $morehtmlref .= $object->title;
610 // Thirdparty
611 if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
612 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1, 'project');
613 }
614 $morehtmlref .= '</div>';
615
616 // Define a complementary filter for search of next/prev ref.
617 if (!$user->hasRight('projet', 'all', 'lire')) {
618 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
619 $object->next_prev_filter = "rowid:IN:(".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0').")";
620 }
621
622 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
623
624 print '<div class="fichecenter">';
625 print '<div class="fichehalfleft">';
626 print '<div class="underbanner clearboth"></div>';
627
628 print '<table class="border tableforfield centpercent">';
629
630 // Usage
631 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
632 print '<tr><td class="tdtop">';
633 print $langs->trans("Usage");
634 print '</td>';
635 print '<td>';
636 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
637 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
638 $htmltext = $langs->trans("ProjectFollowOpportunity");
639 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
640 print '<br>';
641 }
642 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
643 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
644 $htmltext = $langs->trans("ProjectFollowTasks");
645 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
646 print '<br>';
647 }
648 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
649 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"' : '')).'"> ';
650 $htmltext = $langs->trans("ProjectBillTimeDescription");
651 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
652 print '<br>';
653 }
654 if (isModEnabled('eventorganization')) {
655 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"' : '')).'"> ';
656 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
657 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
658 }
659 print '</td></tr>';
660 }
661
662 // Visibility
663 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
664 if ($object->public) {
665 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
666 print $langs->trans('SharedProject');
667 } else {
668 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
669 print $langs->trans('PrivateProject');
670 }
671 print '</td></tr>';
672
673 // Budget
674 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
675 if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
676 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
677 }
678 print '</td></tr>';
679
680 // Date start - end project
681 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
682 $start = dol_print_date($object->date_start, 'day');
683 print($start ? $start : '?');
684 $end = dol_print_date($object->date_end, 'day');
685 print ' - ';
686 print($end ? $end : '?');
687 if ($object->hasDelay()) {
688 print img_warning("Late");
689 }
690 print '</td></tr>';
691
692 // Other attributes
693 $cols = 2;
694 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
695
696 print '</table>';
697
698 print '</div>';
699 print '<div class="fichehalfright">';
700 print '<div class="underbanner clearboth"></div>';
701
702 print '<table class="border tableforfield centpercent">';
703
704 // Description
705 print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
706 print dol_htmlentitiesbr($object->description);
707 print '</td></tr>';
708
709 // Categories
710 if (isModEnabled('category')) {
711 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
712 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
713 print "</td></tr>";
714 }
715
716 print '</table>';
717
718 print '</div>';
719 print '</div>';
720
721 print '<div class="clearboth"></div>';
722
723
724 print dol_get_fiche_end();
725}
726
727
728if ($action == 'create' && $user->hasRight('projet', 'creer') && (empty($object->thirdparty->id) || $userWrite > 0)) {
729 if ($id > 0 || !empty($ref)) {
730 print '<br>';
731 }
732
733 print load_fiche_titre($langs->trans("NewTask"), '', 'projecttask');
734
735 $projectoktoentertime = 1;
736 if ($object->id > 0 && $object->status == Project::STATUS_CLOSED) {
737 $projectoktoentertime = 0;
738 print '<div class="warning">';
739 $langs->load("errors");
740 print $langs->trans("WarningProjectClosed");
741 print '</div>';
742 }
743
744 if ($object->id > 0 && $object->status == Project::STATUS_DRAFT) {
745 $projectoktoentertime = 0;
746 print '<div class="warning">';
747 $langs->load("errors");
748 print $langs->trans("WarningProjectDraft");
749 print '</div>';
750 }
751
752 print '<form action="'.$_SERVER['PHP_SELF'].'" method="POST">';
753 print '<input type="hidden" name="token" value="'.newToken().'">';
754 print '<input type="hidden" name="action" value="createtask">';
755 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
756 if (!empty($object->id)) {
757 print '<input type="hidden" name="id" value="'.$object->id.'">';
758 }
759
760 print dol_get_fiche_head();
761
762 print '<div class="div-table-responsive-no-min">';
763 print '<table class="border centpercent">';
764
765 $defaultref = '';
766 $classnamemodtask = getDolGlobalString('PROJECT_TASK_ADDON', 'mod_task_simple');
767 if (getDolGlobalString('PROJECT_TASK_ADDON') && is_readable(DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').".php")) {
768 require_once DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').'.php';
769 $modTask = new $classnamemodtask();
770 '@phan-var-force ModeleNumRefTask $modTask';
771 $defaultref = $modTask->getNextValue($object->thirdparty, $object);
772 }
773
774 if (is_numeric($defaultref) && $defaultref <= 0) {
775 $defaultref = '';
776 }
777
778 // Ref
779 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
780 if (empty($duplicate_code_error)) {
781 print(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref);
782 } else {
783 print $defaultref;
784 }
785 print '<input type="hidden" name="taskref" value="'.(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref).'">';
786 print '</td></tr>';
787
788 // Label
789 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td>';
790 print '<input type="text" name="label" autofocus class="minwidth500" value="'.$label.'">';
791 print '</td></tr>';
792
793 // Project
794 print '<tr><td class="fieldrequired">'.$langs->trans("ChildOfProjectTask").'</td><td>';
795 print img_picto('', 'project', 'class="pictofixedwidth"');
796 if ($projectoktoentertime) {
797 $formother->selectProjectTasks(GETPOST('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '0,1', 'maxwidth500 widthcentpercentminusxx');
798 } else {
799 $formother->selectProjectTasks(GETPOST('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '', 'maxwidth500 widthcentpercentminusxx');
800 }
801 print '</td></tr>';
802
803 $contactsofproject = (empty($object->id) ? '' : $object->getListContactId('internal'));
804
805 // Assigned to
806 print '<tr><td>'.$langs->trans("AffectedTo").'</td><td>';
807 print img_picto('', 'user', 'class="pictofixedwidth"');
808 if (is_array($contactsofproject) && count($contactsofproject)) {
809 print $form->select_dolusers($user->id, 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
810 } else {
811 if ((isset($projectid) && $projectid > 0) || $object->id > 0) {
812 print '<span class="opacitymedium">'.$langs->trans("NoUserAssignedToTheProject").'</span>';
813 } else {
814 print $form->select_dolusers($user->id, 'userid', 0, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
815 }
816 }
817 print '</td></tr>';
818
819 // Billable
820 print '<tr><td>'.$langs->trans("Billable").'</td><td>';
821 print $form->selectyesno('billable');
822 print '</td></tr>';
823
824 // Date start task
825 print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
826 print img_picto('', 'action', 'class="pictofixedwidth"');
827 print $form->selectDate((!empty($date_start) ? $date_start : ''), 'date_start', 1, 1, 0, '', 1, 1);
828 print '</td></tr>';
829
830 // Date end task
831 print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
832 print img_picto('', 'action', 'class="pictofixedwidth"');
833 print $form->selectDate((!empty($date_end) ? $date_end : -1), 'date_end', -1, 1, 0, '', 1, 1);
834 print '</td></tr>';
835
836 // Planned workload
837 print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td>';
838 print img_picto('', 'clock', 'class="pictofixedwidth"');
839 print $form->select_duration('planned_workload', $planned_workload, 0, 'text');
840 print '</td></tr>';
841
842 // Progress
843 print '<tr><td>'.$langs->trans("ProgressDeclared").'</td><td colspan="3">';
844 print img_picto('', 'fa-percent', 'class="pictofixedwidth"');
845 print $formother->select_percent($progress, 'progress', 0, 5, 0, 100, 1);
846 print '</td></tr>';
847
848 // Description
849 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
850 print '<td>';
851
852 // WYSIWYG editor
853 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
854 $nbrows = 0;
855 if (getDolGlobalString('MAIN_INPUT_DESC_HEIGHT')) {
856 $nbrows = getDolGlobalString('MAIN_INPUT_DESC_HEIGHT');
857 }
858 $doleditor = new DolEditor('description', $object->description, '', 80, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), $nbrows, '90%');
859 print $doleditor->Create();
860
861 print '</td></tr>';
862
863 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
864 print img_picto('', 'currency', 'class="pictofixedwidth"');
865 print '<input size="8" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'"></td>';
866 print '</tr>';
867
868 // Other options
869 $parameters = array('arrayfields' => &$arrayfields);
870 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $taskstatic, $action); // Note that $action and $object may have been modified by hook
871 print $hookmanager->resPrint;
872
873 if (empty($reshook) && !empty($extrafields->attributes[$taskstatic->table_element]['label'])) {
874 print $taskstatic->showOptionals($extrafields, 'edit'); // Do not use $object here that is object of project but use $taskstatic
875 }
876
877 print '</table>';
878 print '</div>';
879
880 print dol_get_fiche_end();
881
882 print $form->buttonsSaveCancel("Add");
883
884 print '</form>';
885} elseif ($id > 0 || !empty($ref)) {
886 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
887
888 // Projet card in view mode
889
890 print '<br>';
891
892 // Link to create task
893 $linktocreatetaskParam = array();
894 $linktocreatetaskUserRight = false;
895 if ($user->hasRight('projet', 'all', 'creer') || $user->hasRight('projet', 'creer')) {
896 if ($object->public || $userWrite > 0) {
897 $linktocreatetaskUserRight = true;
898 } else {
899 $linktocreatetaskParam['attr']['title'] = $langs->trans("NotOwnerOfProject");
900 }
901 }
902
903 $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);
904
905 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
906 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
907 print '<input type="hidden" name="token" value="'.newToken().'">';
908 print '<input type="hidden" name="action" value="list">';
909 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
910 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
911 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
912 print '<input type="hidden" name="page" value="'.$page.'">';
913 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
914
915 $title = $langs->trans("ListOfTasks");
916 $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss' => 'reposition btnTitleSelected'));
917 $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'));
918
919 //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1);
920 print load_fiche_titre($title, $linktotasks.' &nbsp; '.$linktocreatetask, 'projecttask', 0, '', '', $massactionbutton);
921
922 $objecttmp = new Task($db);
923 $trackid = 'task'.$taskstatic->id;
924 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
925
926 // Get list of tasks in tasksarray and taskarrayfiltered
927 // 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).
928 $filteronthirdpartyid = $socid;
929 $tasksarray = $taskstatic->getTasksArray(0, 0, $object->id, $filteronthirdpartyid, 0, '', -1, $morewherefilter, 0, 0, $extrafields, 1, $search_array_options, 1, 1, $sortfield, $sortorder);
930
931 // We load also tasks limited to a particular user
932 $tmpuser = new User($db);
933 if ($search_user_id > 0) {
934 $tmpuser->fetch($search_user_id);
935 }
936
937 $tasksrole = ($tmpuser->id > 0 ? $taskstatic->getUserRolesForProjectsOrTasks(null, $tmpuser, $object->id, 0) : '');
938 //var_dump($tasksarray);
939 //var_dump($tasksrole);
940
941 if (!empty($conf->use_javascript_ajax)) {
942 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
943 }
944
945 // Filter on assigned users
946 $moreforfilter = '';
947 $moreforfilter .= '<div class="divsearchfield">';
948 $moreforfilter .= img_picto('', 'user', 'class="pictofixedwidth"');
949 $moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', $langs->trans("TasksAssignedTo"), null, 0, '', '');
950 $moreforfilter .= '</div>';
951 if ($moreforfilter) {
952 print '<div class="liste_titre liste_titre_bydiv centpercent">';
953 print $moreforfilter;
954 print '</div>';
955 }
956
957 // Show the massaction checkboxes only when this page is not opend from the Extended POS
958 if ($massactionbutton && $contextpage != 'poslist') {
959 $selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
960 }
961
962 print '<div class="div-table-responsive">';
963 print '<table id="tablelines" class="tagtable nobottom liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
964
965 // Fields title search
966 print '<tr class="liste_titre_filter">';
967
968 // Action column
969 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
970 print '<td class="liste_titre maxwidthsearch">';
971 $searchpicto = $form->showFilterButtons();
972 print $searchpicto;
973 print '</td>';
974 }
975
976 if (!empty($arrayfields['t.ref']['checked'])) {
977 print '<td class="liste_titre">';
978 print '<input class="flat searchstring maxwidth50" type="text" name="search_taskref" value="'.dol_escape_htmltag($search_taskref).'">';
979 print '</td>';
980 }
981
982 if (!empty($arrayfields['t.label']['checked'])) {
983 print '<td class="liste_titre">';
984 print '<input class="flat searchstring maxwidth100" type="text" name="search_tasklabel" value="'.dol_escape_htmltag($search_tasklabel).'">';
985 print '</td>';
986 }
987
988 if (!empty($arrayfields['t.description']['checked'])) {
989 print '<td class="liste_titre">';
990 print '<input class="flat searchstring maxwidth100" type="text" name="search_taskdescription" value="'.dol_escape_htmltag($search_taskdescription).'">';
991 print '</td>';
992 }
993
994 if (!empty($arrayfields['t.dateo']['checked'])) {
995 print '<td class="liste_titre center">';
996 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartday" value="'.$search_dtstartday.'">';
997 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartmonth" value="'.$search_dtstartmonth.'"></span>';
998 print $formother->selectyear($search_dtstartyear ? $search_dtstartyear : -1, 'search_dtstartyear', 1, 20, 5);*/
999 print '<div class="nowrapfordate">';
1000 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'));
1001 print '</div>';
1002 print '<div class="nowrapfordate">';
1003 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'));
1004 print '</div>';
1005 print '</td>';
1006 }
1007
1008 if (!empty($arrayfields['t.datee']['checked'])) {
1009 print '<td class="liste_titre center">';
1010 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendday" value="'.$search_dtendday.'">';
1011 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendmonth" value="'.$search_dtendmonth.'"></span>';
1012 print $formother->selectyear($search_dtendyear ? $search_dtendyear : -1, 'search_dtendyear', 1, 20, 5);*/
1013 print '<div class="nowrapfordate">';
1014 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'));
1015 print '</div>';
1016 print '<div class="nowrapfordate">';
1017 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'));
1018 print '</div>';
1019 print '</td>';
1020 }
1021
1022 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1023 print '<td class="liste_titre right">';
1024 print '<input class="flat" type="text" size="4" name="search_planedworkload" value="'.$search_planedworkload.'">';
1025 print '</td>';
1026 }
1027
1028 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1029 print '<td class="liste_titre right">';
1030 print '<input class="flat" type="text" size="4" name="search_timespend" value="'.$search_timespend.'">';
1031 print '</td>';
1032 }
1033
1034 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1035 print '<td class="liste_titre right">';
1036 print '<input class="flat" type="text" size="4" name="search_progresscalc" value="'.$search_progresscalc.'">';
1037 print '</td>';
1038 }
1039
1040 if (!empty($arrayfields['t.progress']['checked'])) {
1041 print '<td class="liste_titre right">';
1042 print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
1043 print '</td>';
1044 }
1045
1046 // progress resume not searchable
1047 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1048 print '<td class="liste_titre right"></td>';
1049 }
1050
1051 if ($object->usage_bill_time) {
1052 if (!empty($arrayfields['t.tobill']['checked'])) {
1053 print '<td class="liste_titre right">';
1054 print '</td>';
1055 }
1056
1057 if (!empty($arrayfields['t.billed']['checked'])) {
1058 print '<td class="liste_titre right">';
1059 print '</td>';
1060 }
1061 }
1062 // Contacts of task, disabled because available by default just after
1063 /*
1064 if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) {
1065 print '<td class="liste_titre"></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 // Contacts of task, disabled because available by default just after
1151 /*
1152 if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) {
1153 print_liste_field_titre("TaskRessourceLinks", $_SERVER["PHP_SELF"], '', '', $param, $sortfield, $sortorder);
1154 }
1155 */
1156
1157 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1158 print_liste_field_titre($arrayfields['t.budget_amount']['label'], $_SERVER["PHP_SELF"], "t.budget_amount", "", $param, '', $sortfield, $sortorder, 'center ');
1159 }
1160
1161 if (!empty($arrayfields['c.assigned']['checked'])) {
1162 print_liste_field_titre($arrayfields['c.assigned']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1163 }
1164
1165 if (!empty($arrayfields['t.billable']['checked'])) {
1166 print_liste_field_titre($arrayfields['t.billable']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1167 }
1168 // Extra fields
1169 $disablesortlink = 1;
1170 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1171 // Hook fields
1172 $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
1173 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1174 print $hookmanager->resPrint;
1175 print '<td></td>';
1176 // Action column
1177 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1178 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1179 }
1180 print "</tr>\n";
1181
1182 $nboftaskshown = 0;
1183 if (count($tasksarray) > 0) {
1184 // Show all lines in taskarray (recursive function to go down on tree)
1185 $j = 0;
1186 $level = 0;
1187 $nboftaskshown = projectLinesa($j, 0, $tasksarray, $level, '', 0, $tasksrole, (string) $object->id, 1, $object->id, '', ($object->usage_bill_time ? 1 : 0), $arrayfields, $arrayofselected);
1188 } else {
1189 $colspan = count($arrayfields);
1190 if ($object->usage_bill_time) {
1191 $colspan += 2;
1192 }
1193 print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoTasks").'</span></td></tr>';
1194 }
1195
1196 print "</table>";
1197 print '</div>';
1198
1199 print '</form>';
1200
1201
1202 // Test if database is clean. If not we clean it.
1203 //print 'mode='.$_REQUEST["mode"].' $nboftaskshown='.$nboftaskshown.' count($tasksarray)='.count($tasksarray).' count($tasksrole)='.count($tasksrole).'<br>';
1204 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)
1205 if ($search_user_id == $user->id) {
1206 if ($nboftaskshown < count($tasksrole)) {
1207 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1208 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1209 }
1210 } else {
1211 if ($nboftaskshown < count($tasksarray) && !GETPOSTINT('search_user_id')) {
1212 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1213 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1214 }
1215 }
1216 }
1217}
1218
1219// End of page
1220llxFooter();
1221$db->close();
$id
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
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
llxFooter()
Footer empty.
Definition document.php:107
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_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
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.
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.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
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
projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$taskrole, $projectsListId='', $addordertick=0, $projectidfortotallink=0, $dummy='', $showbilltime=0, $arrayfields=array(), $arrayofselected=array())
Show task lines with a particular parent.
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.