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$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 // Visibility
664 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
665 if ($object->public) {
666 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
667 print $langs->trans('SharedProject');
668 } else {
669 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
670 print $langs->trans('PrivateProject');
671 }
672 print '</td></tr>';
673
674 // Budget
675 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
676 if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
677 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
678 }
679 print '</td></tr>';
680
681 // Date start - end project
682 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
683 $start = dol_print_date($object->date_start, 'day');
684 print($start ? $start : '?');
685 $end = dol_print_date($object->date_end, 'day');
686 print ' - ';
687 print($end ? $end : '?');
688 if ($object->hasDelay()) {
689 print img_warning("Late");
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 // Description
706 print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
707 print dol_htmlentitiesbr($object->description);
708 print '</td></tr>';
709
710 // Categories
711 if (isModEnabled('category')) {
712 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
713 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
714 print "</td></tr>";
715 }
716
717 print '</table>';
718
719 print '</div>';
720 print '</div>';
721
722 print '<div class="clearboth"></div>';
723
724
725 print dol_get_fiche_end();
726}
727
728
729if ($action == 'create' && $user->hasRight('projet', 'creer') && (empty($object->thirdparty->id) || $userWrite > 0)) {
730 if ($id > 0 || !empty($ref)) {
731 print '<br>';
732 }
733
734 print load_fiche_titre($langs->trans("NewTask"), '', 'projecttask');
735
736 $projectoktoentertime = 1;
737 if ($object->id > 0 && $object->status == Project::STATUS_CLOSED) {
738 $projectoktoentertime = 0;
739 print '<div class="warning">';
740 $langs->load("errors");
741 print $langs->trans("WarningProjectClosed");
742 print '</div>';
743 }
744
745 if ($object->id > 0 && $object->status == Project::STATUS_DRAFT) {
746 $projectoktoentertime = 0;
747 print '<div class="warning">';
748 $langs->load("errors");
749 print $langs->trans("WarningProjectDraft");
750 print '</div>';
751 }
752
753 print '<form action="'.$_SERVER['PHP_SELF'].'" method="POST">';
754 print '<input type="hidden" name="token" value="'.newToken().'">';
755 print '<input type="hidden" name="action" value="createtask">';
756 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
757 if (!empty($object->id)) {
758 print '<input type="hidden" name="id" value="'.$object->id.'">';
759 }
760
761 print dol_get_fiche_head();
762
763 print '<div class="div-table-responsive-no-min">';
764 print '<table class="border centpercent">';
765
766 $defaultref = '';
767 $classnamemodtask = getDolGlobalString('PROJECT_TASK_ADDON', 'mod_task_simple');
768 if (getDolGlobalString('PROJECT_TASK_ADDON') && is_readable(DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').".php")) {
769 require_once DOL_DOCUMENT_ROOT."/core/modules/project/task/" . getDolGlobalString('PROJECT_TASK_ADDON').'.php';
770 $modTask = new $classnamemodtask();
771 '@phan-var-force ModeleNumRefTask $modTask';
772 $defaultref = $modTask->getNextValue($object->thirdparty, $object);
773 }
774
775 if (is_numeric($defaultref) && $defaultref <= 0) {
776 $defaultref = '';
777 }
778
779 // Ref
780 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Ref").'</span></td><td>';
781 if (empty($duplicate_code_error)) {
782 print(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref);
783 } else {
784 print $defaultref;
785 }
786 print '<input type="hidden" name="taskref" value="'.(GETPOSTISSET("ref") ? GETPOST("ref", 'alpha') : $defaultref).'">';
787 print '</td></tr>';
788
789 // Label
790 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td><td>';
791 print '<input type="text" name="label" autofocus class="minwidth500" value="'.$label.'">';
792 print '</td></tr>';
793
794 // Project
795 print '<tr><td class="fieldrequired">'.$langs->trans("ChildOfProjectTask").'</td><td>';
796 print img_picto('', 'project', 'class="pictofixedwidth"');
797 if ($projectoktoentertime) {
798 $formother->selectProjectTasks(GETPOST('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '0,1', 'maxwidth500 widthcentpercentminusxx');
799 } else {
800 $formother->selectProjectTasks(GETPOST('task_parent'), empty($projectid) ? $object->id : $projectid, 'task_parent', 0, 0, 1, 1, 0, '', 'maxwidth500 widthcentpercentminusxx');
801 }
802 print '</td></tr>';
803
804 $contactsofproject = (empty($object->id) ? '' : $object->getListContactId('internal'));
805
806 // Assigned to
807 print '<tr><td>'.$langs->trans("AffectedTo").'</td><td>';
808 print img_picto('', 'user', 'class="pictofixedwidth"');
809 if (is_array($contactsofproject) && count($contactsofproject)) {
810 print $form->select_dolusers($user->id, 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
811 } else {
812 if ((isset($projectid) && $projectid > 0) || $object->id > 0) {
813 print '<span class="opacitymedium">'.$langs->trans("NoUserAssignedToTheProject").'</span>';
814 } else {
815 print $form->select_dolusers($user->id, 'userid', 0, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth500 widthcentpercentminusx');
816 }
817 }
818 print '</td></tr>';
819
820 // Billable
821 print '<tr><td>'.$langs->trans("Billable").'</td><td>';
822 print $form->selectyesno('billable');
823 print '</td></tr>';
824
825 // Date start task
826 print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
827 print img_picto('', 'action', 'class="pictofixedwidth"');
828 print $form->selectDate((!empty($date_start) ? $date_start : ''), 'date_start', 1, 1, 0, '', 1, 1);
829 print '</td></tr>';
830
831 // Date end task
832 print '<tr><td>'.$langs->trans("DateEnd").'</td><td>';
833 print img_picto('', 'action', 'class="pictofixedwidth"');
834 print $form->selectDate((!empty($date_end) ? $date_end : -1), 'date_end', -1, 1, 0, '', 1, 1);
835 print '</td></tr>';
836
837 // Planned workload
838 print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td>';
839 print img_picto('', 'clock', 'class="pictofixedwidth"');
840 print $form->select_duration('planned_workload', $planned_workload, 0, 'text');
841 print '</td></tr>';
842
843 // Progress
844 print '<tr><td>'.$langs->trans("ProgressDeclared").'</td><td colspan="3">';
845 print img_picto('', 'fa-percent', 'class="pictofixedwidth"');
846 print $formother->select_percent($progress, 'progress', 0, 5, 0, 100, 1);
847 print '</td></tr>';
848
849 // Description
850 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
851 print '<td>';
852
853 // WYSIWYG editor
854 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
855 $nbrows = 0;
856 if (getDolGlobalString('MAIN_INPUT_DESC_HEIGHT')) {
857 $nbrows = getDolGlobalString('MAIN_INPUT_DESC_HEIGHT');
858 }
859 $doleditor = new DolEditor('description', $object->description, '', 80, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), $nbrows, '90%');
860 print $doleditor->Create();
861
862 print '</td></tr>';
863
864 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
865 print img_picto('', 'currency', 'class="pictofixedwidth"');
866 print '<input size="8" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'"></td>';
867 print '</tr>';
868
869 // Other options
870 $parameters = array('arrayfields' => &$arrayfields);
871 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $taskstatic, $action); // Note that $action and $object may have been modified by hook
872 print $hookmanager->resPrint;
873
874 if (empty($reshook) && !empty($extrafields->attributes[$taskstatic->table_element]['label'])) {
875 print $taskstatic->showOptionals($extrafields, 'edit'); // Do not use $object here that is object of project but use $taskstatic
876 }
877
878 print '</table>';
879 print '</div>';
880
881 print dol_get_fiche_end();
882
883 print $form->buttonsSaveCancel("Add");
884
885 print '</form>';
886} elseif ($id > 0 || !empty($ref)) {
887 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields
888
889 // Projet card in view mode
890
891 print '<br>';
892
893 // Link to create task
894 $linktocreatetaskParam = array();
895 $linktocreatetaskUserRight = false;
896 if ($user->hasRight('projet', 'all', 'creer') || $user->hasRight('projet', 'creer')) {
897 if ($object->public || $userWrite > 0) {
898 $linktocreatetaskUserRight = true;
899 } else {
900 $linktocreatetaskParam['attr']['title'] = $langs->trans("NotOwnerOfProject");
901 }
902 }
903
904 $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);
905
906 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
907 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
908 print '<input type="hidden" name="token" value="'.newToken().'">';
909 print '<input type="hidden" name="action" value="list">';
910 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
911 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
912 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
913 print '<input type="hidden" name="page" value="'.$page.'">';
914 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
915
916 $title = $langs->trans("ListOfTasks");
917 $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/projet/tasks.php?id='.$object->id, '', 1, array('morecss' => 'reposition btnTitleSelected'));
918 $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'));
919
920 //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1);
921 print load_fiche_titre($title, $linktotasks.' &nbsp; '.$linktocreatetask, 'projecttask', 0, '', '', $massactionbutton);
922
923 $objecttmp = new Task($db);
924 $trackid = 'task'.$taskstatic->id;
925 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
926
927 // Get list of tasks in tasksarray and taskarrayfiltered
928 // 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).
929 $filteronthirdpartyid = $socid;
930 $tasksarray = $taskstatic->getTasksArray(0, 0, $object->id, $filteronthirdpartyid, 0, '', -1, $morewherefilter, 0, 0, $extrafields, 1, $search_array_options, 1, 1, $sortfield, $sortorder);
931
932 // We load also tasks limited to a particular user
933 $tmpuser = new User($db);
934 if ($search_user_id > 0) {
935 $tmpuser->fetch($search_user_id);
936 }
937
938 $tasksrole = ($tmpuser->id > 0 ? $taskstatic->getUserRolesForProjectsOrTasks(null, $tmpuser, $object->id, 0) : '');
939 //var_dump($tasksarray);
940 //var_dump($tasksrole);
941
942 if (!empty($conf->use_javascript_ajax)) {
943 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
944 }
945
946 // Filter on assigned users
947 $moreforfilter = '';
948 $moreforfilter .= '<div class="divsearchfield">';
949 $moreforfilter .= img_picto('', 'user', 'class="pictofixedwidth"');
950 $moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', $langs->trans("TasksAssignedTo"), null, 0, '', '');
951 $moreforfilter .= '</div>';
952 if ($moreforfilter) {
953 print '<div class="liste_titre liste_titre_bydiv centpercent">';
954 print $moreforfilter;
955 print '</div>';
956 }
957
958 // Show the massaction checkboxes only when this page is not opend from the Extended POS
959 if ($massactionbutton && $contextpage != 'poslist') {
960 $selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
961 }
962
963 print '<div class="div-table-responsive">';
964 print '<table id="tablelines" class="tagtable nobottom liste'.($moreforfilter ? " listwithfilterbefore" : "").'">';
965
966 // Fields title search
967 print '<tr class="liste_titre_filter">';
968
969 // Action column
970 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
971 print '<td class="liste_titre maxwidthsearch">';
972 $searchpicto = $form->showFilterButtons();
973 print $searchpicto;
974 print '</td>';
975 }
976
977 if (!empty($arrayfields['t.ref']['checked'])) {
978 print '<td class="liste_titre">';
979 print '<input class="flat searchstring maxwidth50" type="text" name="search_taskref" value="'.dol_escape_htmltag($search_taskref).'">';
980 print '</td>';
981 }
982
983 if (!empty($arrayfields['t.label']['checked'])) {
984 print '<td class="liste_titre">';
985 print '<input class="flat searchstring maxwidth100" type="text" name="search_tasklabel" value="'.dol_escape_htmltag($search_tasklabel).'">';
986 print '</td>';
987 }
988
989 if (!empty($arrayfields['t.description']['checked'])) {
990 print '<td class="liste_titre">';
991 print '<input class="flat searchstring maxwidth100" type="text" name="search_taskdescription" value="'.dol_escape_htmltag($search_taskdescription).'">';
992 print '</td>';
993 }
994
995 if (!empty($arrayfields['t.dateo']['checked'])) {
996 print '<td class="liste_titre center">';
997 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartday" value="'.$search_dtstartday.'">';
998 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtstartmonth" value="'.$search_dtstartmonth.'"></span>';
999 print $formother->selectyear($search_dtstartyear ? $search_dtstartyear : -1, 'search_dtstartyear', 1, 20, 5);*/
1000 print '<div class="nowrapfordate">';
1001 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'));
1002 print '</div>';
1003 print '<div class="nowrapfordate">';
1004 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'));
1005 print '</div>';
1006 print '</td>';
1007 }
1008
1009 if (!empty($arrayfields['t.datee']['checked'])) {
1010 print '<td class="liste_titre center">';
1011 /*print '<span class="nowraponall"><input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendday" value="'.$search_dtendday.'">';
1012 print '<input class="flat valignmiddle width20" type="text" maxlength="2" name="search_dtendmonth" value="'.$search_dtendmonth.'"></span>';
1013 print $formother->selectyear($search_dtendyear ? $search_dtendyear : -1, 'search_dtendyear', 1, 20, 5);*/
1014 print '<div class="nowrapfordate">';
1015 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'));
1016 print '</div>';
1017 print '<div class="nowrapfordate">';
1018 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'));
1019 print '</div>';
1020 print '</td>';
1021 }
1022
1023 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1024 print '<td class="liste_titre right">';
1025 print '<input class="flat" type="text" size="4" name="search_planedworkload" value="'.$search_planedworkload.'">';
1026 print '</td>';
1027 }
1028
1029 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1030 print '<td class="liste_titre right">';
1031 print '<input class="flat" type="text" size="4" name="search_timespend" value="'.$search_timespend.'">';
1032 print '</td>';
1033 }
1034
1035 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1036 print '<td class="liste_titre right">';
1037 print '<input class="flat" type="text" size="4" name="search_progresscalc" value="'.$search_progresscalc.'">';
1038 print '</td>';
1039 }
1040
1041 if (!empty($arrayfields['t.progress']['checked'])) {
1042 print '<td class="liste_titre right">';
1043 print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
1044 print '</td>';
1045 }
1046
1047 // progress resume not searchable
1048 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1049 print '<td class="liste_titre right"></td>';
1050 }
1051
1052 if ($object->usage_bill_time) {
1053 if (!empty($arrayfields['t.tobill']['checked'])) {
1054 print '<td class="liste_titre right">';
1055 print '</td>';
1056 }
1057
1058 if (!empty($arrayfields['t.billed']['checked'])) {
1059 print '<td class="liste_titre right">';
1060 print '</td>';
1061 }
1062 }
1063 // Contacts of task, disabled because available by default just after
1064 /*
1065 if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) {
1066 print '<td class="liste_titre"></td>';
1067 }
1068 */
1069
1070 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1071 print '<td class="liste_titre center">';
1072 print '<input type="text" class="flat" name="search_task_budget_amount" value="'.$search_task_budget_amount.'" size="4">';
1073 print '</td>';
1074 }
1075
1076 if (!empty($arrayfields['c.assigned']['checked'])) {
1077 print '<td class="liste_titre right">';
1078 print '</td>';
1079 }
1080
1081 if (!empty($arrayfields['t.billable']['checked'])) {
1082 print '<td class="liste_titre center">';
1083 print $form->selectyesno('search_task_billable', $search_task_billable, 0, false, 1);
1084 print '</td>';
1085 }
1086
1087 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1088
1089 // Fields from hook
1090 $parameters = array('arrayfields' => $arrayfields);
1091 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1092 print $hookmanager->resPrint;
1093
1094 print '<td class="liste_titre maxwidthsearch">&nbsp;</td>';
1095
1096 // Action column
1097 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1098 print '<td class="liste_titre maxwidthsearch">';
1099 $searchpicto = $form->showFilterButtons();
1100 print $searchpicto;
1101 print '</td>';
1102 }
1103
1104 print "</tr>\n";
1105
1106 print '<tr class="liste_titre nodrag nodrop">';
1107 // Action column
1108 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1109 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1110 }
1111 // print '<td>'.$langs->trans("Project").'</td>';
1112 if (!empty($arrayfields['t.ref']['checked'])) {
1113 // @phan-suppress-next-line PhanTypeInvalidDimOffset
1114 print_liste_field_titre($arrayfields['t.ref']['label'], $_SERVER["PHP_SELF"], 't.ref', '', $param, '', $sortfield, $sortorder, '');
1115 }
1116 if (!empty($arrayfields['t.label']['checked'])) {
1117 print_liste_field_titre($arrayfields['t.label']['label'], $_SERVER["PHP_SELF"], "t.label", '', $param, '', $sortfield, $sortorder, '');
1118 }
1119 if (!empty($arrayfields['t.description']['checked'])) {
1120 print_liste_field_titre($arrayfields['t.description']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, '');
1121 }
1122 if (!empty($arrayfields['t.dateo']['checked'])) {
1123 print_liste_field_titre($arrayfields['t.dateo']['label'], $_SERVER["PHP_SELF"], "t.dateo", '', $param, '', $sortfield, $sortorder, 'center ');
1124 }
1125 if (!empty($arrayfields['t.datee']['checked'])) {
1126 print_liste_field_titre($arrayfields['t.datee']['label'], $_SERVER["PHP_SELF"], "t.datee", '', $param, '', $sortfield, $sortorder, 'center ');
1127 }
1128 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1129 print_liste_field_titre($arrayfields['t.planned_workload']['label'], $_SERVER["PHP_SELF"], "t.planned_workload", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1130 }
1131 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1132 print_liste_field_titre($arrayfields['t.duration_effective']['label'], $_SERVER["PHP_SELF"], "t.duration_effective", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1133 }
1134 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1135 print_liste_field_titre($arrayfields['t.progress_calculated']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1136 }
1137 if (!empty($arrayfields['t.progress']['checked'])) {
1138 print_liste_field_titre($arrayfields['t.progress']['label'], $_SERVER["PHP_SELF"], "t.progress", '', $param, '', $sortfield, $sortorder, 'right ', '', 1);
1139 }
1140 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1141 print_liste_field_titre($arrayfields['t.progress_summary']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '', 1);
1142 }
1143 if ($object->usage_bill_time) {
1144 if (!empty($arrayfields['t.tobill']['checked'])) {
1145 print_liste_field_titre($arrayfields['t.tobill']['label'], $_SERVER["PHP_SELF"], "t.tobill", '', $param, '', $sortfield, $sortorder, 'right ');
1146 }
1147 if (!empty($arrayfields['t.billed']['checked'])) {
1148 print_liste_field_titre($arrayfields['t.billed']['label'], $_SERVER["PHP_SELF"], "t.billed", '', $param, '', $sortfield, $sortorder, 'right ');
1149 }
1150 }
1151 // Contacts of task, disabled because available by default just after
1152 /*
1153 if (!empty($conf->global->PROJECT_SHOW_CONTACTS_IN_LIST)) {
1154 print_liste_field_titre("TaskRessourceLinks", $_SERVER["PHP_SELF"], '', '', $param, $sortfield, $sortorder);
1155 }
1156 */
1157
1158 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1159 print_liste_field_titre($arrayfields['t.budget_amount']['label'], $_SERVER["PHP_SELF"], "t.budget_amount", "", $param, '', $sortfield, $sortorder, 'center ');
1160 }
1161
1162 if (!empty($arrayfields['c.assigned']['checked'])) {
1163 print_liste_field_titre($arrayfields['c.assigned']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1164 }
1165
1166 if (!empty($arrayfields['t.billable']['checked'])) {
1167 print_liste_field_titre($arrayfields['t.billable']['label'], $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'center ', '');
1168 }
1169 // Extra fields
1170 $disablesortlink = 1;
1171 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1172 // Hook fields
1173 $parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
1174 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1175 print $hookmanager->resPrint;
1176 print '<td></td>';
1177 // Action column
1178 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1179 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1180 }
1181 print "</tr>\n";
1182
1183 $nboftaskshown = 0;
1184 if (count($tasksarray) > 0) {
1185 // Show all lines in taskarray (recursive function to go down on tree)
1186 $j = 0;
1187 $level = 0;
1188 $nboftaskshown = projectLinesa($j, 0, $tasksarray, $level, '', 0, $tasksrole, (string) $object->id, 1, $object->id, '', ($object->usage_bill_time ? 1 : 0), $arrayfields, $arrayofselected);
1189 } else {
1190 $colspan = count($arrayfields);
1191 if ($object->usage_bill_time) {
1192 $colspan += 2;
1193 }
1194 print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoTasks").'</span></td></tr>';
1195 }
1196
1197 print "</table>";
1198 print '</div>';
1199
1200 print '</form>';
1201
1202
1203 // Test if database is clean. If not we clean it.
1204 //print 'mode='.$_REQUEST["mode"].' $nboftaskshown='.$nboftaskshown.' count($tasksarray)='.count($tasksarray).' count($tasksrole)='.count($tasksrole).'<br>';
1205 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)
1206 if ($search_user_id == $user->id) {
1207 if ($nboftaskshown < count($tasksrole)) {
1208 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1209 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1210 }
1211 } else {
1212 if ($nboftaskshown < count($tasksarray) && !GETPOSTINT('search_user_id')) {
1213 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1214 cleanCorruptedTree($db, 'projet_task', 'fk_task_parent');
1215 }
1216 }
1217 }
1218}
1219
1220// End of page
1221llxFooter();
1222$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_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.