dolibarr 22.0.5
task.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
7 * Copyright (C) 2024 Vincent de Grandpré <vincent@de-grandpre.quebec>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
29require "../../main.inc.php";
30require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
31require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/project.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.'/core/lib/date.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
38require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
39
48// Load translation files required by the page
49$langs->loadlangs(array('projects', 'companies'));
50
51$action = GETPOST('action', 'aZ09');
52$confirm = GETPOST('confirm', 'alpha');
53//$cancel = GETPOST('cancel');
54//$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
55//$backtopage = GETPOST('backtopage', 'alpha'); // if not set, a default page will be used
56//$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); // if not set, $backtopage will be used
57
58$id = GETPOSTINT('id');
59$ref = GETPOST("ref", 'alpha', 1); // task ref
60$taskref = GETPOST("taskref", 'alpha'); // task ref
61$withproject = GETPOSTINT('withproject');
62$project_ref = GETPOST('project_ref', 'alpha');
63$planned_workload = ((GETPOST('planned_workloadhour') != '' || GETPOST('planned_workloadmin') != '') ? (GETPOSTINT('planned_workloadhour') > 0 ? GETPOSTINT('planned_workloadhour') * 3600 : 0) + (GETPOSTINT('planned_workloadmin') > 0 ? GETPOSTINT('planned_workloadmin') * 60 : 0) : '');
64$mode = GETPOST('mode', 'alpha');
65
66// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
67$hookmanager->initHooks(array('projecttaskcard', 'globalcard'));
68
69$object = new Task($db);
70$extrafields = new ExtraFields($db);
71$projectstatic = new Project($db);
72
73// fetch optionals attributes and labels
74$extrafields->fetch_name_optionals_label($object->table_element);
75
76$parameters = array('id' => $id);
77$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
78if ($reshook < 0) {
79 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
80}
81
82if ($id > 0 || $ref) {
83 $ret = $object->fetch($id, $ref);
84 if ($ret > 0) {
85 $projectstatic->fetch($object->fk_project);
86 }
87}
88
89// Security check
90$socid = 0;
91
92restrictedArea($user, 'projet', $object->fk_project, 'projet&project');
93
94
95
96/*
97 * Actions
98 */
99$error = 0;
100
101if ($action == 'update' && !GETPOST("cancel") && $user->hasRight('projet', 'creer')) {
102 if (empty($taskref)) {
103 $error++;
104 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Ref")), null, 'errors');
105 }
106 if (!GETPOST("label")) {
107 $error++;
108 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
109 }
110 if (!$error) {
111 $object->oldcopy = clone $object; // @phan-suppress-current-line PhanTypeMismatchProperty
112
113 $tmparray = explode('_', GETPOST('task_parent'));
114 $task_parent = $tmparray[1];
115 if (empty($task_parent)) {
116 $task_parent = 0; // If task_parent is ''
117 }
118
119 $object->ref = $taskref ? $taskref : GETPOST("ref", 'alpha', 2);
120 $object->label = GETPOST("label", "alphanohtml");
121 if (!getDolGlobalString('FCKEDITOR_ENABLE_SOCIETE')) {
122 $object->description = GETPOST('description', "alphanohtml");
123 } else {
124 $object->description = GETPOST('description', "restricthtml");
125 }
126 $object->fk_task_parent = $task_parent;
127 $object->planned_workload = $planned_workload;
128 $object->date_start = dol_mktime(GETPOSTINT('date_starthour'), GETPOSTINT('date_startmin'), 0, GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
129 $object->date_end = dol_mktime(GETPOSTINT('date_endhour'), GETPOSTINT('date_endmin'), 0, GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
130 $object->progress = price2num(GETPOST('progress', 'alphanohtml'));
131 $object->budget_amount = GETPOSTFLOAT('budget_amount');
132 $object->billable = (GETPOST('billable', 'aZ') == 'yes' ? 1 : 0);
133 if (GETPOST('progress') == '100') {
134 $object->status = $object::STATUS_CLOSED;
135 } elseif (GETPOST('progress') != '0') {
136 $object->status = $object::STATUS_ONGOING;
137 }
138
139 // Fill array 'array_options' with data from add form
140 $ret = $extrafields->setOptionalsFromPost(null, $object, '@GETPOSTISSET');
141 if ($ret < 0) {
142 $error++;
143 }
144
145 if (!$error) {
146 $result = $object->update($user);
147 if ($result < 0) {
148 setEventMessages($object->error, $object->errors, 'errors');
149 $action = 'edit';
150 }
151 } else {
152 $action = 'edit';
153 }
154 } else {
155 $action = 'edit';
156 }
157}
158
159if ($action == 'confirm_merge' && $confirm == 'yes' && $user->hasRight('projet', 'creer')) {
160 $task_origin_id = GETPOSTINT('task_origin');
161 $task_origin = new Task($db); // The Task that we will delete
162
163 if ($task_origin_id <= 0) {
164 $langs->load('errors');
165 setEventMessages($langs->trans('ErrorTaskIdIsMandatory', $langs->transnoentitiesnoconv('MergeOriginTask')), null, 'errors');
166 } else {
167 if (!$error && $task_origin->fetch($task_origin_id) < 1) {
168 setEventMessages($langs->trans('ErrorRecordNotFound'), null, 'errors');
169 $error++;
170 }
171 if (!$error) {
172 $result = $object->mergeTask($task_origin_id);
173 if ($result < 0) {
174 $error++;
175 setEventMessages($object->error, $object->errors, 'errors');
176 } else {
177 setEventMessages($langs->trans('TaskMergeSuccess'), null, 'mesgs');
178 }
179 }
180 }
181}
182
183if ($action == 'confirm_clone' && $confirm == 'yes' && $user->hasRight('projet', 'creer')) {
184 //$clone_contacts = GETPOST('clone_contacts') ? 1 : 0;
185 $clone_prog = GETPOST('clone_prog') ? 1 : 0;
186 $clone_time = GETPOST('clone_time') ? 1 : 0;
187 $clone_affectation = GETPOST('clone_affectation') ? 1 : 0;
188 $clone_change_dt = GETPOST('clone_change_dt') ? 1 : 0;
189 $clone_notes = GETPOST('clone_notes') ? 1 : 0;
190 $clone_file = GETPOST('clone_file') ? 1 : 0;
191 $result = $object->createFromClone($user, $object->id, $object->fk_project, $object->fk_task_parent, $clone_change_dt, $clone_affectation, $clone_time, $clone_file, $clone_notes, $clone_prog);
192 if ($result <= 0) {
193 setEventMessages($object->error, $object->errors, 'errors');
194 } else {
195 // Load new object
196 $newobject = new Task($db);
197 $newobject->fetch($result);
198 $newobject->fetch_optionals();
199 $newobject->fetch_thirdparty(); // Load new object
200 $object = $newobject;
201 $action = '';
202 }
203}
204
205if ($action == 'confirm_delete' && $confirm == "yes" && $user->hasRight('projet', 'supprimer')) {
206 $result = $projectstatic->fetch($object->fk_project);
207 $projectstatic->fetch_thirdparty();
208
209 if ($object->delete($user) > 0) {
210 header('Location: '.DOL_URL_ROOT.'/projet/tasks.php?restore_lastsearch_values=1&id='.$projectstatic->id.($withproject ? '&withproject=1' : ''));
211 exit;
212 } else {
213 setEventMessages($object->error, $object->errors, 'errors');
214 $action = '';
215 }
216}
217
218if ($action == 'confirm_close' && $confirm == "yes" && $user->hasRight('projet', 'creer')) {
219 $result = $projectstatic->fetch($object->fk_project);
220 $projectstatic->fetch_thirdparty();
221
222 if ($object->setStatusCommon($user, Task::STATUS_CLOSED) > 0) {
223 header('Location: '.DOL_URL_ROOT.'/projet/tasks.php?restore_lastsearch_values=1&id='.$projectstatic->id.($withproject ? '&withproject=1' : ''));
224 exit;
225 } else {
226 setEventMessages($object->error, $object->errors, 'errors');
227 $action = '';
228 }
229}
230
231// Retrieve First Task ID of Project if withprojet is on to allow project prev next to work
232if (!empty($project_ref) && !empty($withproject)) {
233 if ($projectstatic->fetch(0, $project_ref) > 0) {
234 $tasksarray = $object->getTasksArray(null, null, $projectstatic->id, $socid, 0);
235 if (count($tasksarray) > 0) {
236 $id = $tasksarray[0]->id;
237 } else {
238 header("Location: ".DOL_URL_ROOT.'/projet/tasks.php?id='.$projectstatic->id.(empty($mode) ? '' : '&mode='.$mode));
239 }
240 }
241}
242
243// Build doc
244if ($action == 'builddoc' && $user->hasRight('projet', 'creer')) {
245 // Save last template used to generate document
246 if (GETPOST('model')) {
247 $object->setDocModel($user, GETPOST('model', 'alpha'));
248 }
249
250 $outputlangs = $langs;
251 if (GETPOST('lang_id', 'aZ09')) {
252 $outputlangs = new Translate("", $conf);
253 $outputlangs->setDefaultLang(GETPOST('lang_id', 'aZ09'));
254 }
255 $result = $object->generateDocument($object->model_pdf, $outputlangs);
256 if ($result <= 0) {
257 setEventMessages($object->error, $object->errors, 'errors');
258 $action = '';
259 }
260}
261
262// Delete file in doc form
263if ($action == 'remove_file' && $user->hasRight('projet', 'creer')) {
264 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
265
266 $langs->load("other");
267 $upload_dir = $conf->project->dir_output."/".dol_sanitizeFileName($projectstatic->ref)."/".dol_sanitizeFileName($object->ref);
268 $file = $upload_dir.'/'.dol_sanitizeFileName(GETPOST('file'));
269
270 $ret = dol_delete_file($file, 1);
271 if ($ret) {
272 setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs');
273 } else {
274 setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('file')), null, 'errors');
275 }
276}
277
278// Reopen task
279if ($action == 'reopen' && $user->hasRight('projet', 'creer')) {
280 $result = $object->setStatusCommon($user, Task::STATUS_DRAFT);
281 if ($result >= 0) {
282 setEventMessages($langs->trans("TaskBackToDraft"), null, 'mesgs');
283 } else {
284 $error++;
285 setEventMessages($object->error, $object->errors, 'errors');
286 }
287}
288
289// Validate status of task
290if ($action == 'valid' && $user->hasRight('projet', 'creer')) {
291 $result = $object->setStatusCommon($user, Task::STATUS_VALIDATED);
292 if ($result >= 0) {
293 setEventMessages($langs->trans("TaskValidated"), null, 'mesgs');
294 } else {
295 $error++;
296 setEventMessages($object->error, $object->errors, 'errors');
297 }
298}
299
300
301/*
302 * View
303 */
304
305$form = new Form($db);
306$formother = new FormOther($db);
307$formfile = new FormFile($db);
308$formproject = new FormProjets($db);
309
310$title = $object->ref;
311if (!empty($withproject)) {
312 $title .= ' | ' . $langs->trans("Project") . (!empty($projectstatic->ref) ? ': '.$projectstatic->ref : '') ;
313}
314$help_url = '';
315
316llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-project project-tasks page-task');
317
318
319if ($id > 0 || !empty($ref)) {
320 $res = $object->fetch_optionals();
321 if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_TASK') && method_exists($object, 'fetchComments') && empty($object->comments)) {
322 $object->fetchComments();
323 }
324
325
326 if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($projectstatic, 'fetchComments') && empty($projectstatic->comments)) {
327 $projectstatic->fetchComments();
328 }
329 if (!empty($projectstatic->socid)) {
330 $projectstatic->fetch_thirdparty();
331 }
332
333 $object->project = clone $projectstatic;
334
335 //$userWrite = $projectstatic->restrictedProjectArea($user, 'write');
336
337 if (!empty($withproject)) {
338 // Tabs for project
339 $tab = 'tasks';
340 $head = project_prepare_head($projectstatic);
341 print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($projectstatic->public ? 'projectpub' : 'project'), 0, '', '');
342
343 $param = ($mode == 'mine' ? '&mode=mine' : '');
344
345 // Project card
346
347 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
348
349 $morehtmlref = '<div class="refidno">';
350 // Title
351 $morehtmlref .= $projectstatic->title;
352 // Thirdparty
353 if (!empty($projectstatic->thirdparty->id) && $projectstatic->thirdparty->id > 0) {
354 $morehtmlref .= '<br>'.$projectstatic->thirdparty->getNomUrl(1, 'project');
355 }
356 $morehtmlref .= '</div>';
357
358 // Define a complementary filter for search of next/prev ref.
359 if (!$user->hasRight('projet', 'all', 'lire')) {
360 $objectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 0);
361 $projectstatic->next_prev_filter = "rowid:IN:".$db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0');
362 }
363
364 dol_banner_tab($projectstatic, 'project_ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
365
366 print '<div class="fichecenter">';
367 print '<div class="fichehalfleft">';
368 print '<div class="underbanner clearboth"></div>';
369
370 print '<table class="border tableforfield centpercent">';
371
372 // Usage
373 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
374 print '<tr><td class="tdtop">';
375 print $langs->trans("Usage");
376 print '</td>';
377 print '<td>';
378 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
379 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_opportunity ? ' checked="checked"' : '')).'"> ';
380 $htmltext = $langs->trans("ProjectFollowOpportunity");
381 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
382 print '<br>';
383 }
384 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
385 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_task ? ' checked="checked"' : '')).'"> ';
386 $htmltext = $langs->trans("ProjectFollowTasks");
387 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
388 print '<br>';
389 }
390 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
391 print '<input type="checkbox" disabled name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_bill_time ? ' checked="checked"' : '')).'"> ';
392 $htmltext = $langs->trans("ProjectBillTimeDescription");
393 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
394 print '<br>';
395 }
396 if (isModEnabled('eventorganization')) {
397 print '<input type="checkbox" disabled name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($projectstatic->usage_organize_event ? ' checked="checked"' : '')).'"> ';
398 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
399 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
400 }
401 print '</td></tr>';
402 }
403
404 // Budget
405 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
406 if (isset($projectstatic->budget_amount) && strcmp($projectstatic->budget_amount, '')) {
407 print '<span class="amount">'.price($projectstatic->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
408 }
409 print '</td></tr>';
410
411 // Date start - end project
412 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
413 $start = dol_print_date($projectstatic->date_start, 'day');
414 print($start ? $start : '?');
415 $end = dol_print_date($projectstatic->date_end, 'day');
416 print ' - ';
417 print($end ? $end : '?');
418 if ($projectstatic->hasDelay()) {
419 print img_warning("Late");
420 }
421 print '</td></tr>';
422
423 // Visibility
424 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
425 if ($projectstatic->public) {
426 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
427 print $langs->trans('SharedProject');
428 } else {
429 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
430 print $langs->trans('PrivateProject');
431 }
432 print '</td></tr>';
433
434 // Other attributes
435 $cols = 2;
436 $savobject = $object;
437 $object = $projectstatic;
438 include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
439 $object = $savobject;
440
441 print '</table>';
442
443 print '</div>';
444
445 print '<div class="fichehalfright">';
446 print '<div class="underbanner clearboth"></div>';
447
448 print '<table class="border tableforfield centpercent">';
449
450 // Categories
451 if (isModEnabled('category')) {
452 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
453 print $form->showCategories($projectstatic->id, 'project', 1);
454 print "</td></tr>";
455 }
456
457 // Description
458 print '<tr><td class="titlefield'.($projectstatic->description ? ' noborderbottom' : '').'" colspan="2">'.$langs->trans("Description").'</td></tr>';
459 if ($projectstatic->description) {
460 print '<tr><td class="nottitleforfield" colspan="2">';
461 print '<div class="longmessagecut">';
462 print dolPrintHTML($projectstatic->description);
463 print '</div>';
464 print '</td></tr>';
465 }
466
467 print '</table>';
468
469 print '</div>';
470 print '</div>';
471
472 print '<div class="clearboth"></div>';
473
474 print dol_get_fiche_end();
475
476 print '<br>';
477 }
478
479 /*
480 * Actions
481 */
482 /*print '<div class="tabsAction">';
483
484 if ($user->rights->projet->all->creer || $user->rights->projet->creer)
485 {
486 if ($projectstatic->public || $userWrite > 0)
487 {
488 print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=create'.$param.'">'.$langs->trans('AddTask').'</a>';
489 }
490 else
491 {
492 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotOwnerOfProject").'">'.$langs->trans('AddTask').'</a>';
493 }
494 }
495 else
496 {
497 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans('AddTask').'</a>';
498 }
499
500 print '</div>';
501 */
502
503 // To verify role of users
504 //$userAccess = $projectstatic->restrictedProjectArea($user); // We allow task affected to user even if a not allowed project
505 //$arrayofuseridoftask=$object->getListContactId('internal');
506
507
508 $head = task_prepare_head($object);
509
510 if ($action == 'edit' && $user->hasRight('projet', 'creer')) {
511 print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
512 print '<input type="hidden" name="token" value="'.newToken().'">';
513 print '<input type="hidden" name="action" value="update">';
514 print '<input type="hidden" name="withproject" value="'.$withproject.'">';
515 print '<input type="hidden" name="id" value="'.$object->id.'">';
516
517 print dol_get_fiche_head($head, 'task_task', $langs->trans("Task"), 0, 'projecttask', 0, '', '');
518
519 print '<table class="border centpercent">';
520
521 // Ref
522 print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Ref").'</td>';
523 print '<td><input class="minwidth100" name="taskref" value="'.$object->ref.'"></td></tr>';
524
525 // Label
526 print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td>';
527 print '<td><input class="minwidth500" name="label" value="'.$object->label.'"></td></tr>';
528
529 // Project
530 if (empty($withproject)) {
531 print '<tr><td>'.$langs->trans("Project").'</td><td>';
532 print $projectstatic->getNomUrl(1);
533 print '</td></tr>';
534
535 // Third party
536 print '<td>'.$langs->trans("ThirdParty").'</td><td>';
537 if ($projectstatic->thirdparty->id) {
538 print $projectstatic->thirdparty->getNomUrl(1);
539 } else {
540 print '&nbsp;';
541 }
542 print '</td></tr>';
543 }
544
545 // Task parent
546 print '<tr><td>'.$langs->trans("ChildOfProjectTask").'</td><td>';
547 print img_picto('', 'projecttask');
548 $formother->selectProjectTasks($object->fk_task_parent, $projectstatic->id, 'task_parent', ($user->admin ? 0 : 1), 0, 0, 0, $object->id, '', 'minwidth100 widthcentpercentminusxx maxwidth500');
549 print '</td></tr>';
550
551 // Date start
552 print '<tr><td>'.$langs->trans("DateStart").'</td><td>';
553 print $form->selectDate($object->date_start, 'date_start', 1, 1, 0, '', 1, 0);
554 print '</td></tr>';
555
556 // Date end
557 print '<tr><td>'.$langs->trans("Deadline").'</td><td>';
558 print $form->selectDate($object->date_end ? $object->date_end : -1, 'date_end', 1, 1, 0, '', 1, 0);
559 print '</td></tr>';
560
561 // Planned workload
562 print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td>';
563 print $form->select_duration('planned_workload', $object->planned_workload, 0, 'text');
564 print '</td></tr>';
565
566 // Progress declared
567 print '<tr><td>'.$langs->trans("ProgressDeclared").'</td><td>';
568 print $formother->select_percent($object->progress, 'progress', 0, 5, 0, 100, 1);
569 print '</td></tr>';
570
571 // Billable
572 print '<tr><td>'.$langs->trans("Billable").'</td><td>';
573 print $form->selectyesno('billable', $object->billable);
574 print '</td></tr>';
575
576 // Description
577
578 print '<tr><td class="tdtop">'.$langs->trans("Description").'</td>';
579 print '<td>';
580
581 // WYSIWYG editor
582 include_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
583 $nbrows = getDolGlobalInt('MAIN_INPUT_DESC_HEIGHT', 0);
584 $doleditor = new DolEditor('description', $object->description, '', 80, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_SOCIETE'), $nbrows, '90%');
585 print $doleditor->Create();
586
587 print '</td></tr>';
588
589
590 print '<tr><td>'.$langs->trans("Budget").'</td>';
591 print '<td><input class="width75" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : price2num($object->budget_amount)).'"></td>';
592 print '</tr>';
593
594 // Other options
595 $parameters = array();
596 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
597 print $hookmanager->resPrint;
598 if (empty($reshook)) {
599 print $object->showOptionals($extrafields, 'edit');
600 }
601
602 print '</table>';
603
604 print dol_get_fiche_end();
605
606 print $form->buttonsSaveCancel("Modify");
607
608 print '</form>';
609 } else {
610 /*
611 * Fiche tache en mode visu
612 */
613 $param = ($withproject ? '&withproject=1' : '');
614 $linkback = $withproject ? '<a href="'.DOL_URL_ROOT.'/projet/tasks.php?id='.$projectstatic->id.'&restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>' : '';
615
616 print dol_get_fiche_head($head, 'task_task', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition');
617
618 if ($action == 'clone') {
619 $formquestion = array(
620 'text' => $langs->trans("ConfirmClone"),
621 //array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true),
622 0 => array('type' => 'checkbox', 'name' => 'clone_change_dt', 'label' => $langs->trans("CloneChanges"), 'value' => true),
623 1 => array('type' => 'checkbox', 'name' => 'clone_affectation', 'label' => $langs->trans("CloneAffectation"), 'value' => true),
624 2 => array('type' => 'checkbox', 'name' => 'clone_prog', 'label' => $langs->trans("CloneProgression"), 'value' => true),
625 3 => array('type' => 'checkbox', 'name' => 'clone_time', 'label' => $langs->trans("CloneTimes"), 'value' => true),
626 4 => array('type' => 'checkbox', 'name' => 'clone_file', 'label' => $langs->trans("CloneFile"), 'value' => true),
627 );
628
629 print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClone"), $langs->trans("ConfirmCloneTask"), "confirm_clone", $formquestion, '', 1, 300, 590);
630 }
631
632 if ($action == 'close') {
633 $formquestion = array(
634 'text' => $langs->trans("ConfirmClosed"),
635 );
636 print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id, $langs->trans("ToClose"), $langs->trans("ConfirmCloseTask"), "confirm_close", $formquestion, '', 1, 300, 590);
637 }
638
639
640 if ($action == 'merge') {
641 $formquestion = array(
642 array(
643 'name' => 'task_origin',
644 'label' => $langs->trans('MergeOriginTask'),
645 'type' => 'other',
646 'value' => $formproject->selectTasks(-1, 0, 'task_origin', 24, 0, $langs->trans('SelectTask'), 0, 0, 0, 'maxwidth500 minwidth200', '', '', null, 1)
647 )
648 );
649 print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".$object->id.(GETPOST('withproject') ? "&withproject=1" : ""), $langs->trans("MergeTasks"), $langs->trans("ConfirmMergeTasks"), "confirm_merge", $formquestion, 'yes', 1, 250);
650 }
651
652 if ($action == 'delete') {
653 print $form->formconfirm($_SERVER["PHP_SELF"]."?id=".GETPOSTINT("id").'&withproject='.$withproject, $langs->trans("DeleteATask"), $langs->trans("ConfirmDeleteATask"), "confirm_delete");
654 }
655
656 if (!GETPOST('withproject') || empty($projectstatic->id)) {
657 $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1);
658 $object->next_prev_filter = "fk_projet:IN:".$db->sanitize($projectsListId);
659 } else {
660 $object->next_prev_filter = "fk_projet:=:".((int) $projectstatic->id);
661 }
662
663 $morehtmlref = '';
664
665 // Project
666 if (empty($withproject)) {
667 $morehtmlref .= '<div class="refidno">';
668 $morehtmlref .= $langs->trans("Project").': ';
669 $morehtmlref .= $projectstatic->getNomUrl(1);
670 $morehtmlref .= '<br>';
671
672 // Third party
673 $morehtmlref .= $langs->trans("ThirdParty").': ';
674 if (!empty($projectstatic->thirdparty) && is_object($projectstatic->thirdparty)) {
675 $morehtmlref .= $projectstatic->thirdparty->getNomUrl(1);
676 }
677 $morehtmlref .= '</div>';
678 }
679
680 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, $param);
681
682 print '<div class="fichecenter">';
683 print '<div class="fichehalfleft">';
684
685 print '<div class="underbanner clearboth"></div>';
686 print '<table class="border centpercent tableforfield">';
687
688 // Task parent
689 print '<tr><td class="titlefieldmiddle">'.$langs->trans("ChildOfTask").'</td><td>';
690 if ($object->fk_task_parent > 0) {
691 $tasktmp = new Task($db);
692 $tasktmp->fetch($object->fk_task_parent);
693 print $tasktmp->getNomUrl(1);
694 }
695 print '</td></tr>';
696
697 // Date start - Date end task
698 print '<tr><td>'.$langs->trans("DateStart").' - '.$langs->trans("Deadline").'</td><td colspan="3">';
699 $start = dol_print_date($object->date_start, 'dayhour');
700 print($start ? $start : '?');
701 $end = dol_print_date($object->date_end, 'dayhour');
702 print ' - ';
703 print($end ? $end : '?');
704 if ($object->hasDelay()) {
705 print img_warning("Late");
706 }
707 print '</td></tr>';
708
709 // Planned workload
710 print '<tr><td>'.$langs->trans("PlannedWorkload").'</td><td colspan="3">';
711 if ($object->planned_workload != '') {
712 print convertSecondToTime($object->planned_workload, 'allhourmin');
713 }
714 print '</td></tr>';
715
716 // Description
717 print '<td class="tdtop">'.$langs->trans("Description").'</td><td colspan="3">';
718 print dol_htmlentitiesbr($object->description);
719 print '</td></tr>';
720
721 print '</table>';
722 print '</div>';
723
724 print '<div class="fichehalfright">';
725
726 print '<div class="underbanner clearboth"></div>';
727 print '<table class="border centpercent tableforfield">';
728
729 // Progress declared
730 print '<tr><td class="titlefieldmiddle">'.$langs->trans("ProgressDeclared").'</td><td colspan="3">';
731 if ($object->progress != '' && $object->progress != '-1') {
732 print $object->progress.' %';
733 }
734 print '</td></tr>';
735
736 // Progress calculated
737 print '<tr><td>'.$langs->trans("ProgressCalculated").'</td><td colspan="3">';
738 if ($object->planned_workload != '') {
739 $tmparray = $object->getSummaryOfTimeSpent();
740 if ($tmparray['total_duration'] > 0 && !empty($object->planned_workload)) {
741 print round($tmparray['total_duration'] / $object->planned_workload * 100, 2).' %';
742 } else {
743 print '0 %';
744 }
745 } else {
746 print '<span class="opacitymedium">'.$langs->trans("WorkloadNotDefined").'</span>';
747 }
748 print '</td></tr>';
749
750 // Budget
751 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
752 if (!is_null($object->budget_amount) && strcmp((string) $object->budget_amount, '')) {
753 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
754 }
755 print '</td></tr>';
756
757 // Billable
758 print '<tr><td>'.$langs->trans("Billable").'</td><td>';
759 print '<span>'.($object->billable ? $langs->trans('Yes') : $langs->trans('No')).'</span>';
760 print '</td></tr>';
761
762
763 // Other attributes
764 $cols = 3;
765 $parameters = array('socid' => $socid);
766 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
767
768 print '</table>';
769
770 print '</div>';
771
772 print '</div>';
773 print '<div class="clearboth"></div>';
774
775 print dol_get_fiche_end();
776 }
777
778
779 if ($action != 'edit') {
780 /*
781 * Actions
782 */
783
784 print '<div class="tabsAction">';
785
786 $parameters = array();
787 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
788 // modified by hook
789 if (empty($reshook)) {
790 // Modify
791 if ($user->hasRight('projet', 'creer')) {
792 if ($object->status == $object::STATUS_VALIDATED || $object->status == $object::STATUS_ONGOING) {
793 print '<a class="butAction classfortooltip reposition" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=reopen&token='.newToken().'&withproject='.((int) $withproject).'" title="'.$langs->trans("SetToDraft").'">'.$langs->trans('SetToDraft').'</a>';
794 } elseif ($object->status == $object::STATUS_DRAFT) {
795 print '<a class="butAction reposition" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=valid&token='.newToken().'&withproject='.((int) $withproject).'">'.$langs->trans('Validate').'</a>';
796 }
797 //if ($object->status != $object::STATUS_CLOSED) {
798 print '<a class="butAction reposition" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=edit&token='.newToken().'&withproject='.((int) $withproject).'">'.$langs->trans('Modify').'</a>';
799 //}
800
801 if ($object->status != $object::STATUS_CLOSED) {
802 print '<a class="butAction classfortooltip reposition" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=close&token='.newToken().'&withproject='.((int) $withproject).'" title="'.$langs->trans("Close").'">'.$langs->trans('Close').'</a>';
803 }
804
805 print '<a class="butAction reposition" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=clone&token='.newToken().'&withproject='.((int) $withproject).'">'.$langs->trans('Clone').'</a>';
806
807 print '<a class="butActionDelete classfortooltip reposition" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=merge&token='.newToken().'&withproject='.((int) $withproject).'" title="'.$langs->trans("MergeTasks").'">'.$langs->trans('Merge').'</a>';
808 } else {
809 print '<a class="butActionRefused classfortooltip reposition" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans('Modify').'</a>';
810 }
811
812 // Delete
813 $permissiontodelete = $user->hasRight('projet', 'supprimer');
814 if ($permissiontodelete) {
815 if (!$object->hasChildren() && !$object->hasTimeSpent()) {
816 print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'&withproject='.((int) $withproject), 'delete', $permissiontodelete);
817 } else {
818 print dolGetButtonAction($langs->trans("TaskHasChild"), $langs->trans("Delete"), 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'&withproject='.((int) $withproject), 'delete', -1);
819 }
820 } else {
821 print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'&withproject='.((int) $withproject), 'delete', $permissiontodelete);
822 }
823
824 print '</div>';
825 }
826
827 print '<div class="fichecenter"><div class="fichehalfleft">';
828 print '<a name="builddoc"></a>'; // ancre
829
830 /*
831 * Generated documents
832 */
833 $subdir = dol_sanitizeFileName($projectstatic->ref)."/".dol_sanitizeFileName($object->ref);
834 $filedir = $conf->project->multidir_output[$object->entity]."/".$subdir;
835 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
836 $genallowed = ($user->hasRight('projet', 'lire'));
837 $delallowed = ($user->hasRight('projet', 'creer'));
838
839 print $formfile->showdocuments('project_task', $subdir, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 0, 0, '', '', '', '', '', $object);
840
841 // Show links to link elements
842 $tmparray = $form->showLinkToObjectBlock($object, array(), array('project_task'), 1);
843 $linktoelem = $tmparray['linktoelem'];
844 $htmltoenteralink = $tmparray['htmltoenteralink'];
845 print $htmltoenteralink;
846
847 $compatibleImportElementsList = array();
848 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
849
850 print '</div><div class="fichehalfright">';
851
852 // List of actions on element
853 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
854 $formactions = new FormActions($db);
855 $formactions->showactions($object, 'project_task', 0, 1, '', 10, 'withproject='.$withproject);
856
857 print '</div></div>';
858 }
859}
860
861// End of page
862llxFooter();
863$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 building of HTML components.
Class to offer components to list and upload files.
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 building of HTML components.
Class to manage projects.
Class to manage tasks.
const STATUS_VALIDATED
Validated status (To do).
const STATUS_DRAFT
Draft status.
const STATUS_CLOSED
Finished status.
Class to manage translations.
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:244
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
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.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
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).
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
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...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
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
task_prepare_head($object)
Prepare array with list of tabs.
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.