1 | <?php |
||
2 | |||
3 | /* Copyright (C) 2005 Rodolphe Quiedeville <[email protected]> |
||
4 | * Copyright (C) 2004-2017 Laurent Destailleur <[email protected]> |
||
5 | * Copyright (C) 2005-2012 Regis Houssin <[email protected]> |
||
6 | * Copyright (C) 2024 MDW <[email protected]> |
||
7 | * Copyright (C) 2024 Rafael San José <[email protected]> |
||
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 | |||
23 | use Dolibarr\Code\Categories\Classes\Categorie; |
||
24 | use Dolibarr\Code\Contact\Classes\Contact; |
||
25 | use Dolibarr\Code\Core\Classes\Form; |
||
26 | use Dolibarr\Code\Core\Classes\FormOther; |
||
27 | use Dolibarr\Code\Projet\Classes\Project; |
||
28 | use Dolibarr\Code\Projet\Classes\Task; |
||
29 | use Dolibarr\Code\Societe\Classes\Societe; |
||
30 | use Dolibarr\Code\User\Classes\User; |
||
31 | use Dolibarr\Lib\ViewMain; |
||
32 | |||
33 | /** |
||
34 | * \file htdocs/projet/ganttview.php |
||
35 | * \ingroup projet |
||
36 | * \brief Gantt diagram of a project |
||
37 | */ |
||
38 | |||
39 | require constant('DOL_DOCUMENT_ROOT') . '/main.inc.php'; |
||
40 | require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/project.lib.php'; |
||
41 | require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/date.lib.php'; |
||
42 | |||
43 | $id = GETPOST('id', 'intcomma'); |
||
44 | $ref = GETPOST('ref', 'alpha'); |
||
45 | |||
46 | $mode = GETPOST('mode', 'alpha'); |
||
47 | $mine = ($mode == 'mine' ? 1 : 0); |
||
48 | //if (! $user->rights->projet->all->lire) $mine=1; // Special for projects |
||
49 | |||
50 | $object = new Project($db); |
||
51 | |||
52 | include DOL_DOCUMENT_ROOT . '/core/actions_fetchobject.inc.php'; // Must be include, not include_once |
||
53 | if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($object, 'fetchComments') && empty($object->comments)) { |
||
54 | $object->fetchComments(); |
||
55 | } |
||
56 | |||
57 | // Security check |
||
58 | $socid = 0; |
||
59 | //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. |
||
60 | $result = restrictedArea($user, 'projet', $id, 'projet&project'); |
||
61 | |||
62 | // Load translation files required by the page |
||
63 | $langs->loadlangs(array('users', 'projects')); |
||
64 | |||
65 | |||
66 | /* |
||
67 | * Actions |
||
68 | */ |
||
69 | |||
70 | // None |
||
71 | |||
72 | /* |
||
73 | * View |
||
74 | */ |
||
75 | |||
76 | $form = new Form($db); |
||
77 | $formother = new FormOther($db); |
||
78 | $userstatic = new User($db); |
||
79 | $companystatic = new Societe($db); |
||
80 | $contactstatic = new Contact($db); |
||
81 | $task = new Task($db); |
||
82 | |||
83 | $arrayofcss = array('/includes/jsgantt/jsgantt.css'); |
||
84 | |||
85 | if (!empty($conf->use_javascript_ajax)) { |
||
86 | $arrayofjs = array( |
||
87 | '/includes/jsgantt/jsgantt.js', |
||
88 | '/projet/jsgantt_language.js.php?lang=' . $langs->defaultlang |
||
89 | ); |
||
90 | } |
||
91 | |||
92 | //$title=$langs->trans("Gantt").($object->ref?' - '.$object->ref.' '.$object->name:''); |
||
93 | $title = $langs->trans("Gantt"); |
||
94 | if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/projectnameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->name) { |
||
95 | $title = ($object->ref ? $object->ref . ' ' . $object->name . ' - ' : '') . $langs->trans("Gantt"); |
||
96 | } |
||
97 | $help_url = "EN:Module_Projects|FR:Module_Projets|ES:Módulo_Proyectos"; |
||
98 | |||
99 | ViewMain::llxHeader("", $title, $help_url, '', 0, 0, $arrayofjs, $arrayofcss); |
||
100 | |||
101 | if (($id > 0 && is_numeric($id)) || !empty($ref)) { |
||
102 | // To verify role of users |
||
103 | //$userAccess = $object->restrictedProjectArea($user,'read'); |
||
104 | $userWrite = $object->restrictedProjectArea($user, 'write'); |
||
105 | //$userDelete = $object->restrictedProjectArea($user,'delete'); |
||
106 | //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete; |
||
107 | |||
108 | $tab = 'tasks'; |
||
109 | |||
110 | $head = project_prepare_head($object); |
||
111 | print dol_get_fiche_head($head, $tab, $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project')); |
||
112 | |||
113 | $param = ($mode == 'mine' ? '&mode=mine' : ''); |
||
114 | |||
115 | |||
116 | // Project card |
||
117 | |||
118 | if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) { |
||
119 | $tmpurl = $_SESSION['pageforbacktolist']['project']; |
||
120 | $tmpurl = preg_replace('/__SOCID__/', (string)$object->socid, $tmpurl); |
||
121 | $linkback = '<a href="' . $tmpurl . (preg_match('/\?/', $tmpurl) ? '&' : '?') . 'restore_lastsearch_values=1">' . $langs->trans("BackToList") . '</a>'; |
||
122 | } else { |
||
123 | $linkback = '<a href="' . constant('BASE_URL') . '/projet/list.php?restore_lastsearch_values=1">' . $langs->trans("BackToList") . '</a>'; |
||
124 | } |
||
125 | |||
126 | $morehtmlref = '<div class="refidno">'; |
||
127 | // Title |
||
128 | $morehtmlref .= $object->title; |
||
129 | // Thirdparty |
||
130 | if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) { |
||
131 | $morehtmlref .= '<br>' . $object->thirdparty->getNomUrl(1, 'project'); |
||
0 ignored issues
–
show
|
|||
132 | } |
||
133 | $morehtmlref .= '</div>'; |
||
134 | |||
135 | // Define a complementary filter for search of next/prev ref. |
||
136 | if (!$user->hasRight('projet', 'all', 'lire')) { |
||
137 | $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0); |
||
138 | $object->next_prev_filter = "rowid IN (" . $db->sanitize(count($objectsListId) ? implode(',', array_keys($objectsListId)) : '0') . ")"; |
||
139 | } |
||
140 | |||
141 | dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); |
||
142 | |||
143 | |||
144 | print '<div class="fichecenter">'; |
||
145 | print '<div class="fichehalfleft">'; |
||
146 | print '<div class="underbanner clearboth"></div>'; |
||
147 | |||
148 | print '<table class="border tableforfield centpercent">'; |
||
149 | |||
150 | // Usage |
||
151 | if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) { |
||
152 | print '<tr><td class="tdtop">'; |
||
153 | print $langs->trans("Usage"); |
||
154 | print '</td>'; |
||
155 | print '<td>'; |
||
156 | if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) { |
||
157 | print '<input type="checkbox" disabled name="usage_opportunity"' . (GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')) . '"> '; |
||
158 | $htmltext = $langs->trans("ProjectFollowOpportunity"); |
||
159 | print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext); |
||
160 | print '<br>'; |
||
161 | } |
||
162 | if (!getDolGlobalString('PROJECT_HIDE_TASKS')) { |
||
163 | print '<input type="checkbox" disabled name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')) . '"> '; |
||
164 | $htmltext = $langs->trans("ProjectFollowTasks"); |
||
165 | print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext); |
||
166 | print '<br>'; |
||
167 | } |
||
168 | if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) { |
||
169 | 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"' : '')) . '"> '; |
||
170 | $htmltext = $langs->trans("ProjectBillTimeDescription"); |
||
171 | print $form->textwithpicto($langs->trans("BillTime"), $htmltext); |
||
172 | print '<br>'; |
||
173 | } |
||
174 | if (isModEnabled('eventorganization')) { |
||
175 | 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"' : '')) . '"> '; |
||
176 | $htmltext = $langs->trans("EventOrganizationDescriptionLong"); |
||
177 | print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext); |
||
178 | } |
||
179 | print '</td></tr>'; |
||
180 | } |
||
181 | |||
182 | // Visibility |
||
183 | print '<tr><td class="titlefield">' . $langs->trans("Visibility") . '</td><td>'; |
||
184 | if ($object->public) { |
||
185 | print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"'); |
||
186 | print $langs->trans('SharedProject'); |
||
187 | } else { |
||
188 | print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"'); |
||
189 | print $langs->trans('PrivateProject'); |
||
190 | } |
||
191 | print '</td></tr>'; |
||
192 | |||
193 | // Budget |
||
194 | print '<tr><td>' . $langs->trans("Budget") . '</td><td>'; |
||
195 | if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) { |
||
196 | print price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency); |
||
197 | } |
||
198 | print '</td></tr>'; |
||
199 | |||
200 | // Date start - end project |
||
201 | print '<tr><td>' . $langs->trans("Dates") . '</td><td>'; |
||
202 | $start = dol_print_date($object->date_start, 'day'); |
||
203 | print($start ? $start : '?'); |
||
204 | $end = dol_print_date($object->date_end, 'day'); |
||
205 | print ' - '; |
||
206 | print($end ? $end : '?'); |
||
207 | if ($object->hasDelay()) { |
||
208 | print img_warning("Late"); |
||
209 | } |
||
210 | print '</td></tr>'; |
||
211 | |||
212 | // Other attributes |
||
213 | $cols = 2; |
||
214 | include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; |
||
215 | |||
216 | print '</table>'; |
||
217 | |||
218 | print '</div>'; |
||
219 | print '<div class="fichehalfright">'; |
||
220 | print '<div class="underbanner clearboth"></div>'; |
||
221 | |||
222 | print '<table class="border tableforfield centpercent">'; |
||
223 | |||
224 | // Description |
||
225 | print '<td class="titlefield tdtop">' . $langs->trans("Description") . '</td><td>'; |
||
226 | print nl2br($object->description); |
||
227 | print '</td></tr>'; |
||
228 | |||
229 | // Categories |
||
230 | if (isModEnabled('category')) { |
||
231 | print '<tr><td class="valignmiddle">' . $langs->trans("Categories") . '</td><td>'; |
||
232 | print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1); |
||
233 | print "</td></tr>"; |
||
234 | } |
||
235 | |||
236 | print '</table>'; |
||
237 | |||
238 | print '</div>'; |
||
239 | print '</div>'; |
||
240 | |||
241 | print '<div class="clearboth"></div>'; |
||
242 | |||
243 | print dol_get_fiche_end(); |
||
244 | |||
245 | print '<br>'; |
||
246 | } |
||
247 | |||
248 | // Link to create task |
||
249 | $linktocreatetaskParam = array(); |
||
250 | $linktocreatetaskUserRight = false; |
||
251 | if ($user->hasRight('projet', 'all', 'creer') || $user->hasRight('projet', 'creer')) { |
||
252 | if ($object->public || $userWrite > 0) { |
||
253 | $linktocreatetaskUserRight = true; |
||
254 | } else { |
||
255 | $linktocreatetaskParam['attr']['title'] = $langs->trans("NotOwnerOfProject"); |
||
256 | } |
||
257 | } |
||
258 | |||
259 | $linktocreatetask = dolGetButtonTitle($langs->trans('AddTask'), '', 'fa fa-plus-circle', constant('BASE_URL') . '/projet/tasks.php?id=' . $object->id . '&action=create' . $param . '&backtopage=' . urlencode($_SERVER['PHP_SELF'] . '?id=' . $object->id), '', $linktocreatetaskUserRight, $linktocreatetaskParam); |
||
260 | |||
261 | $linktotasks = dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars paddingleft imgforviewmode', constant('BASE_URL') . '/projet/tasks.php?id=' . $object->id, '', 1, array('morecss' => 'reposition')); |
||
262 | $linktotasks .= dolGetButtonTitle($langs->trans('ViewGantt'), '', 'fa fa-stream paddingleft imgforviewmode', constant('BASE_URL') . '/projet/ganttview.php?id=' . $object->id . '&withproject=1', '', 1, array('morecss' => 'reposition marginleftonly btnTitleSelected')); |
||
263 | |||
264 | //print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $linktotasks, $num, $totalnboflines, 'generic', 0, '', '', 0, 1); |
||
265 | print load_fiche_titre($title, $linktotasks . ' ' . $linktocreatetask, 'projecttask'); |
||
266 | |||
267 | |||
268 | // Get list of tasks in tasksarray and taskarrayfiltered |
||
269 | // We need all tasks (even not limited to a user because a task to user |
||
270 | // can have a parent that is not affected to him). |
||
271 | $tasksarray = $task->getTasksArray(0, 0, ($object->id ? $object->id : $id), $socid, 0); |
||
272 | // We load also tasks limited to a particular user |
||
273 | //$tasksrole=($_REQUEST["mode"]=='mine' ? $task->getUserRolesForProjectsOrTasks(null, $user, $object->id, 0) : ''); |
||
274 | //var_dump($tasksarray); |
||
275 | //var_dump($tasksrole); |
||
276 | |||
277 | |||
278 | if (count($tasksarray) > 0) { |
||
279 | // Show Gant diagram from $taskarray using JSGantt |
||
280 | |||
281 | $dateformat = $langs->trans("FormatDateShortJQuery"); // Used by include ganttchart.inc.php later |
||
282 | $datehourformat = $langs->trans("FormatDateShortJQuery") . ' ' . $langs->trans("FormatHourShortJQuery"); // Used by include ganttchart.inc.php later |
||
283 | $array_contacts = array(); |
||
284 | $tasks = array(); |
||
285 | $task_dependencies = array(); |
||
286 | $taskcursor = 0; |
||
287 | foreach ($tasksarray as $key => $val) { // Task array are sorted by "project, position, date" |
||
288 | $task->fetch($val->id, ''); |
||
289 | |||
290 | $idparent = ($val->fk_task_parent ? $val->fk_task_parent : '-' . $val->fk_project); // If start with -, id is a project id |
||
291 | |||
292 | $tasks[$taskcursor]['task_id'] = $val->id; |
||
293 | $tasks[$taskcursor]['task_alternate_id'] = ($taskcursor + 1); // An id that has same order than position (required by ganttchart) |
||
294 | $tasks[$taskcursor]['task_project_id'] = $val->fk_project; |
||
295 | $tasks[$taskcursor]['task_parent'] = $idparent; |
||
296 | |||
297 | $tasks[$taskcursor]['task_is_group'] = 0; |
||
298 | $tasks[$taskcursor]['task_css'] = 'gtaskblue'; |
||
299 | $tasks[$taskcursor]['task_position'] = $val->rang; |
||
300 | $tasks[$taskcursor]['task_planned_workload'] = $val->planned_workload; |
||
301 | |||
302 | if ($val->fk_task_parent != 0 && $task->hasChildren() > 0) { |
||
303 | $tasks[$taskcursor]['task_is_group'] = 1; |
||
304 | $tasks[$taskcursor]['task_css'] = 'ggroupblack'; |
||
305 | //$tasks[$taskcursor]['task_css'] = 'gtaskblue'; |
||
306 | } elseif ($task->hasChildren() > 0) { |
||
307 | $tasks[$taskcursor]['task_is_group'] = 1; |
||
308 | //$tasks[$taskcursor]['task_is_group'] = 0; |
||
309 | $tasks[$taskcursor]['task_css'] = 'ggroupblack'; |
||
310 | //$tasks[$taskcursor]['task_css'] = 'gtaskblue'; |
||
311 | } |
||
312 | $tasks[$taskcursor]['task_milestone'] = '0'; |
||
313 | $tasks[$taskcursor]['task_percent_complete'] = $val->progress; |
||
314 | //$tasks[$taskcursor]['task_name']=$task->getNomUrl(1); |
||
315 | //print dol_print_date($val->date_start).dol_print_date($val->date_end).'<br>'."\n"; |
||
316 | $tasks[$taskcursor]['task_name'] = $val->ref . ' - ' . $val->label; |
||
317 | $tasks[$taskcursor]['task_start_date'] = $val->date_start; |
||
318 | $tasks[$taskcursor]['task_end_date'] = $val->date_end; |
||
319 | $tasks[$taskcursor]['task_color'] = 'b4d1ea'; |
||
320 | |||
321 | $idofusers = $task->getListContactId('internal'); |
||
322 | $idofcontacts = $task->getListContactId('external'); |
||
323 | $s = ''; |
||
324 | if (count($idofusers) > 0) { |
||
325 | $s .= $langs->trans("Internals") . ': '; |
||
326 | $i = 0; |
||
327 | foreach ($idofusers as $valid) { |
||
328 | $userstatic->fetch($valid); |
||
329 | if ($i) { |
||
330 | $s .= ', '; |
||
331 | } |
||
332 | $s .= $userstatic->login; |
||
333 | $i++; |
||
334 | } |
||
335 | } |
||
336 | //if (count($idofusers)>0 && (count($idofcontacts)>0)) $s.=' - '; |
||
337 | if (count($idofcontacts) > 0) { |
||
338 | if ($s) { |
||
339 | $s .= ' - '; |
||
340 | } |
||
341 | $s .= $langs->trans("Externals") . ': '; |
||
342 | $i = 0; |
||
343 | $contactidfound = array(); |
||
344 | foreach ($idofcontacts as $valid) { |
||
345 | if (empty($contactidfound[$valid])) { |
||
346 | $res = $contactstatic->fetch($valid); |
||
347 | if ($res > 0) { |
||
348 | if ($i) { |
||
349 | $s .= ', '; |
||
350 | } |
||
351 | $s .= $contactstatic->getFullName($langs); |
||
352 | $contactidfound[$valid] = 1; |
||
353 | $i++; |
||
354 | } |
||
355 | } |
||
356 | } |
||
357 | } |
||
358 | |||
359 | /* For JSGanttImproved */ |
||
360 | //if ($s) $tasks[$taskcursor]['task_resources']=implode(',',$idofusers); |
||
361 | $tasks[$taskcursor]['task_resources'] = $s; |
||
362 | if ($s) { |
||
363 | $tasks[$taskcursor]['task_resources'] = '<a href="' . constant('BASE_URL') . '/projet/tasks/contact.php?id=' . $val->id . '&withproject=1" title="' . dol_escape_htmltag($s) . '">' . $langs->trans("Contacts") . '</a>'; |
||
364 | } |
||
365 | //print "xxx".$val->id.$tasks[$taskcursor]['task_resources']; |
||
366 | $tasks[$taskcursor]['note'] = $task->note_public; |
||
367 | $taskcursor++; |
||
368 | } |
||
369 | |||
370 | // Search parent to set task_parent_alternate_id (required by ganttchart) |
||
371 | foreach ($tasks as $tmpkey => $tmptask) { |
||
372 | foreach ($tasks as $tmptask2) { |
||
373 | if ($tmptask2['task_id'] == $tmptask['task_parent']) { |
||
374 | $tasks[$tmpkey]['task_parent_alternate_id'] = $tmptask2['task_alternate_id']; |
||
375 | break; |
||
376 | } |
||
377 | } |
||
378 | if (empty($tasks[$tmpkey]['task_parent_alternate_id'])) { |
||
379 | $tasks[$tmpkey]['task_parent_alternate_id'] = $tasks[$tmpkey]['task_parent']; |
||
380 | } |
||
381 | } |
||
382 | |||
383 | print "\n"; |
||
384 | |||
385 | if (!empty($conf->use_javascript_ajax)) { |
||
386 | //var_dump($_SESSION); |
||
387 | |||
388 | // How the date for data are formatted (format used bu jsgantt) |
||
389 | $dateformatinput = 'yyyy-mm-dd'; |
||
390 | // How the date for data are formatted (format used by dol_print_date) |
||
391 | $dateformatinput2 = 'standard'; |
||
392 | //var_dump($dateformatinput); |
||
393 | //var_dump($dateformatinput2); |
||
394 | |||
395 | $moreforfilter = '<div class="liste_titre liste_titre_bydiv centpercent">'; |
||
396 | |||
397 | $moreforfilter .= '<div class="divsearchfield">'; |
||
398 | //$moreforfilter .= $langs->trans("TasksAssignedTo").': '; |
||
399 | //$moreforfilter .= $form->select_dolusers($tmpuser->id > 0 ? $tmpuser->id : '', 'search_user_id', 1); |
||
400 | $moreforfilter .= ' '; |
||
401 | $moreforfilter .= '</div>'; |
||
402 | |||
403 | $moreforfilter .= '</div>'; |
||
404 | |||
405 | print $moreforfilter; |
||
406 | |||
407 | print '<div class="div-table-responsive">'; |
||
408 | |||
409 | print '<div id="tabs" class="gantt" style="width: 80vw;">' . "\n"; |
||
410 | include_once DOL_DOCUMENT_ROOT . '/projet/ganttchart.inc.php'; |
||
411 | print '</div>' . "\n"; |
||
412 | |||
413 | print '</div>'; |
||
414 | } else { |
||
415 | $langs->load("admin"); |
||
416 | print $langs->trans("AvailableOnlyIfJavascriptAndAjaxNotDisabled"); |
||
417 | } |
||
418 | } else { |
||
419 | print '<div class="opacitymedium">' . $langs->trans("NoTasks") . '</div>'; |
||
420 | } |
||
421 | |||
422 | // End of page |
||
423 | ViewMain::llxFooter(); |
||
424 | $db->close(); |
||
425 |
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.