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