dolibarr  19.0.0-dev
list.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2006-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2006-2010 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
6  * Copyright (C) 2021 Alexandre Spangaro <aspangaro@open-dsi.fr>
7  * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
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 
29 require "../../main.inc.php";
30 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
35 
36 // Load translation files required by the page
37 $langs->loadLangs(array('projects', 'users', 'companies'));
38 
39 $action = GETPOST('action', 'aZ09');
40 $massaction = GETPOST('massaction', 'alpha');
41 $show_files = GETPOST('show_files', 'int');
42 $confirm = GETPOST('confirm', 'alpha');
43 $toselect = GETPOST('toselect', 'array');
44 $optioncss = GETPOST('optioncss', 'aZ09');
45 $mode = GETPOST('mode', 'aZ');
46 
47 $id = GETPOST('id', 'int');
48 
49 $search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
50 $search_categ = GETPOST("search_categ", 'int');
51 
52 $search_projectstatus = GETPOST('search_projectstatus');
53 if (!isset($search_projectstatus) || $search_projectstatus === '') {
54  if ($search_all != '') {
55  $search_projectstatus = -1;
56  } else {
57  $search_projectstatus = 1;
58  }
59 }
60 
61 $search_project_ref = GETPOST('search_project_ref');
62 $search_project_title = GETPOST('search_project_title');
63 $search_task_ref = GETPOST('search_task_ref');
64 $search_task_label = GETPOST('search_task_label');
65 $search_task_description = GETPOST('search_task_description');
66 $search_task_ref_parent = GETPOST('search_task_ref_parent');
67 $search_project_user = GETPOST('search_project_user', 'int');
68 $search_task_user = GETPOST('search_task_user', 'int');
69 $search_task_progress = GETPOST('search_task_progress');
70 $search_task_budget_amount = GETPOST('search_task_budget_amount');
71 $search_societe = GETPOST('search_societe');
72 $search_societe_alias = GETPOST('search_societe_alias');
73 $search_opp_status = GETPOST("search_opp_status", 'alpha');
74 $searchCategoryCustomerOperator = 0;
75 if (GETPOSTISSET('formfilteraction')) {
76  $searchCategoryCustomerOperator = GETPOST('search_category_customer_operator', 'int');
77 } elseif (!empty($conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT)) {
78  $searchCategoryCustomerOperator = $conf->global->MAIN_SEARCH_CAT_OR_BY_DEFAULT;
79 }
80 $searchCategoryCustomerList = GETPOST('search_category_customer_list', 'array');
81 
82 $mine = GETPOST('mode', 'alpha') == 'mine' ? 1 : 0;
83 if ($mine) {
84  $search_task_user = $user->id;
85  $mine = 0;
86 }
87 $type = GETPOST('type');
88 
89 $search_date_startday = GETPOST('search_date_startday', 'int');
90 $search_date_startmonth = GETPOST('search_date_startmonth', 'int');
91 $search_date_startyear = GETPOST('search_date_startyear', 'int');
92 $search_date_endday = GETPOST('search_date_endday', 'int');
93 $search_date_endmonth = GETPOST('search_date_endmonth', 'int');
94 $search_date_endyear = GETPOST('search_date_endyear', 'int');
95 $search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver
96 $search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
97 $search_datelimit_startday = GETPOST('search_datelimit_startday', 'int');
98 $search_datelimit_startmonth = GETPOST('search_datelimit_startmonth', 'int');
99 $search_datelimit_startyear = GETPOST('search_datelimit_startyear', 'int');
100 $search_datelimit_endday = GETPOST('search_datelimit_endday', 'int');
101 $search_datelimit_endmonth = GETPOST('search_datelimit_endmonth', 'int');
102 $search_datelimit_endyear = GETPOST('search_datelimit_endyear', 'int');
103 $search_datelimit_start = dol_mktime(0, 0, 0, $search_datelimit_startmonth, $search_datelimit_startday, $search_datelimit_startyear);
104 $search_datelimit_end = dol_mktime(23, 59, 59, $search_datelimit_endmonth, $search_datelimit_endday, $search_datelimit_endyear);
105 
106 // Initialize context for list
107 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'tasklist';
108 
109 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
110 $object = new Task($db);
111 $hookmanager->initHooks(array('tasklist'));
112 $extrafields = new ExtraFields($db);
113 
114 // fetch optionals attributes and labels
115 $extrafields->fetch_name_optionals_label($object->table_element);
116 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
117 
118 // Security check
119 $socid = 0;
120 //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 assignement.
121 if (!$user->rights->projet->lire) {
122  accessforbidden();
123 }
124 
125 $diroutputmassaction = $conf->project->dir_output.'/tasks/temp/massgeneration/'.$user->id;
126 
127 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
128 $sortfield = GETPOST('sortfield', 'aZ09comma');
129 $sortorder = GETPOST('sortorder', 'aZ09comma');
130 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
131 if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
132  // If $page is not defined, or '' or -1 or if we click on clear filters
133  $page = 0;
134 }
135 $offset = $limit * $page;
136 $pageprev = $page - 1;
137 $pagenext = $page + 1;
138 if (!$sortfield) {
139  $sortfield = 'p.ref';
140 }
141 if (!$sortorder) {
142  $sortorder = 'DESC';
143 }
144 
145 // List of fields to search into when doing a "search in all"
146 $fieldstosearchall = array(
147  't.ref'=>"Ref",
148  't.label'=>"Label",
149  't.description'=>"Description",
150  't.note_public'=>"NotePublic",
151 );
152 if (empty($user->socid)) {
153  $fieldstosearchall['t.note_private'] = "NotePrivate";
154 }
155 
156 $arrayfields = array(
157  't.fk_task_parent'=>array('label'=>"RefTaskParent", 'checked'=>0, 'position'=>70),
158  't.ref'=>array('label'=>"RefTask", 'checked'=>1, 'position'=>80),
159  't.label'=>array('label'=>"LabelTask", 'checked'=>1, 'position'=>80),
160  't.description'=>array('label'=>"Description", 'checked'=>0, 'position'=>80),
161  't.dateo'=>array('label'=>"DateStart", 'checked'=>1, 'position'=>100),
162  't.datee'=>array('label'=>"Deadline", 'checked'=>1, 'position'=>101),
163  'p.ref'=>array('label'=>"ProjectRef", 'checked'=>1),
164  'p.title'=>array('label'=>"ProjectLabel", 'checked'=>0),
165  's.nom'=>array('label'=>"ThirdParty", 'checked'=>0, 'csslist'=>'tdoverflowmax125'),
166  's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>1, 'csslist'=>'tdoverflowmax125'),
167  'p.fk_statut'=>array('label'=>"ProjectStatus", 'checked'=>1),
168  't.planned_workload'=>array('label'=>"PlannedWorkload", 'checked'=>1, 'position'=>102),
169  't.duration_effective'=>array('label'=>"TimeSpent", 'checked'=>1, 'position'=>103),
170  't.progress_calculated'=>array('label'=>"ProgressCalculated", 'checked'=>1, 'position'=>104),
171  't.progress'=>array('label'=>"ProgressDeclared", 'checked'=>1, 'position'=>105),
172  't.progress_summary'=>array('label'=>"TaskProgressSummary", 'checked'=>1, 'position'=>106),
173  't.budget_amount'=>array('label'=>"Budget", 'checked'=>0, 'position'=>107),
174  't.tobill'=>array('label'=>"TimeToBill", 'checked'=>0, 'position'=>110),
175  't.billed'=>array('label'=>"TimeBilled", 'checked'=>0, 'position'=>111),
176  't.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500),
177  't.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500),
178  //'t.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000),
179 );
180 // Extra fields
181 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
182 
183 $object->fields = dol_sort_array($object->fields, 'position');
184 $arrayfields = dol_sort_array($arrayfields, 'position');
185 
186 $permissiontoread = $user->hasRight('projet', 'lire');
187 $permissiontocreate = $user->hasRight('projet', 'creer');
188 $permissiontodelete = $user->hasRight('projet', 'supprimer');
189 
190 if (!$permissiontoread) accessforbidden();
191 
192 
193 /*
194  * Actions
195  */
196 
197 if (GETPOST('cancel', 'alpha')) {
198  $action = 'list';
199  $massaction = '';
200 }
201 if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
202  $massaction = '';
203 }
204 
205 $parameters = array('socid'=>$socid);
206 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
207 if ($reshook < 0) {
208  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
209 }
210 
211 if (empty($reshook)) {
212  // Selection of new fields
213  include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
214 
215  // Purge search criteria
216  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
217  $search_all = "";
218  $search_categ = "";
219  $search_projectstatus = -1;
220  $search_project_ref = "";
221  $search_societe = "";
222  $search_societe_alias = "";
223  $search_project_title = "";
224  $search_task_ref = "";
225  $search_task_label = "";
226  $search_task_description = "";
227  $search_task_ref_parent = "";
228  $search_task_progress = "";
229  $search_task_budget_amount = "";
230  $search_task_user = -1;
231  $search_project_user = -1;
232  $search_date_startday = '';
233  $search_date_startmonth = '';
234  $search_date_startyear = '';
235  $search_date_endday = '';
236  $search_date_endmonth = '';
237  $search_date_endyear = '';
238  $search_date_start = '';
239  $search_date_end = '';
240  $search_datelimit_startday = '';
241  $search_datelimit_startmonth = '';
242  $search_datelimit_startyear = '';
243  $search_datelimit_endday = '';
244  $search_datelimit_endmonth = '';
245  $search_datelimit_endyear = '';
246  $search_datelimit_start = '';
247  $search_datelimit_end = '';
248  $toselect = array();
249  $searchCategoryCustomerList = array();
250  $search_array_options = array();
251  }
252 
253  // Mass actions
254  $objectclass = 'Task';
255  $objectlabel = 'Tasks';
256  $uploaddir = $conf->project->dir_output.'/tasks';
257  include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
258 }
259 
260 if (empty($search_projectstatus) && $search_projectstatus == '') {
261  $search_projectstatus = 1;
262 }
263 
264 
265 
266 
267 /*
268  * View
269  */
270 
271 $form = new Form($db);
272 $formother = new FormOther($db);
273 $socstatic = new Societe($db);
274 $projectstatic = new Project($db);
275 $puser = new User($db);
276 $tuser = new User($db);
277 
278 $now = dol_now();
279 
280 $title = $langs->trans("Activities");
281 $help_url = "EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos";
282 $morejs = array();
283 $morecss = array();
284 
285 if ($search_project_user > 0) {
286  $puser->fetch($search_project_user);
287 }
288 if ($search_task_user > 0) {
289  $tuser->fetch($search_task_user);
290 }
291 
292 
293 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
294 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')); // This also change content of $arrayfields
295 
296 
297 if ($id) {
298  $projectstatic->fetch($id);
299  $projectstatic->fetch_thirdparty();
300 }
301 
302 // Get list of project id allowed to user (in a string list separated by coma)
303 if (empty($user->rights->projet->all->lire)) {
304  $projectsListId = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, $socid);
305 }
306 //var_dump($projectsListId);
307 
308 // Get id of types of contacts for projects (This list never contains a lot of elements)
309 $listofprojectcontacttype = array();
310 $sql = "SELECT ctc.rowid, ctc.code FROM ".MAIN_DB_PREFIX."c_type_contact as ctc";
311 $sql .= " WHERE ctc.element = '".$db->escape($projectstatic->element)."'";
312 $sql .= " AND ctc.source = 'internal'";
313 $resql = $db->query($sql);
314 if ($resql) {
315  while ($obj = $db->fetch_object($resql)) {
316  $listofprojectcontacttype[$obj->rowid] = $obj->code;
317  }
318 } else {
319  dol_print_error($db);
320 }
321 if (count($listofprojectcontacttype) == 0) {
322  $listofprojectcontacttype[0] = '0'; // To avoid sql syntax error if not found
323 }
324 // Get id of types of contacts for tasks (This list never contains a lot of elements)
325 $listoftaskcontacttype = array();
326 $sql = "SELECT ctc.rowid, ctc.code FROM ".MAIN_DB_PREFIX."c_type_contact as ctc";
327 $sql .= " WHERE ctc.element = '".$db->escape($object->element)."'";
328 $sql .= " AND ctc.source = 'internal'";
329 $resql = $db->query($sql);
330 if ($resql) {
331  while ($obj = $db->fetch_object($resql)) {
332  $listoftaskcontacttype[$obj->rowid] = $obj->code;
333  }
334 } else {
335  dol_print_error($db);
336 }
337 if (count($listoftaskcontacttype) == 0) {
338  $listoftaskcontacttype[0] = '0'; // To avoid sql syntax error if not found
339 }
340 
341 // Build and execute select
342 // --------------------------------------------------------------------
343 $distinct = 'DISTINCT'; // We add distinct until we are added a protection to be sure a contact of a project and task is assigned only once.
344 $sql = "SELECT ".$distinct." p.rowid as projectid, p.ref as projectref, p.title as projecttitle, p.fk_statut as projectstatus, p.datee as projectdatee, p.fk_opp_status, p.public, p.fk_user_creat as projectusercreate, p.usage_bill_time,";
345 $sql .= " s.nom as name, s.name_alias as alias, s.rowid as socid,";
346 $sql .= " t.datec as date_creation, t.dateo as date_start, t.datee as date_end, t.tms as date_update,";
347 $sql .= " t.rowid as id, t.ref, t.label, t.planned_workload, t.duration_effective, t.progress, t.fk_statut,";
348 $sql .= " t.description, t.fk_task_parent";
349 $sql .= " ,t.budget_amount";
350 // Add sum fields
351 if (!empty($arrayfields['t.tobill']['checked']) || !empty($arrayfields['t.billed']['checked'])) {
352  $sql .= " , SUM(tt.element_duration * ".$db->ifsql("invoice_id IS NULL", "1", "0").") as tobill, SUM(tt.element_duration * ".$db->ifsql("invoice_id IS NULL", "0", "1").") as billed";
353 }
354 // Add fields from extrafields
355 if (!empty($extrafields->attributes[$object->table_element]['label'])) {
356  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
357  $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
358  }
359 }
360 // Add fields from hooks
361 $parameters = array();
362 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
363 $sql .= $hookmanager->resPrint;
364 $sql = preg_replace('/,\s*$/', '', $sql);
365 
366 $sqlfields = $sql; // $sql fields to remove for count total
367 
368 $sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
369 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
370 $sql .= ", ".MAIN_DB_PREFIX."projet_task as t";
371 if (!empty($arrayfields['t.tobill']['checked']) || !empty($arrayfields['t.billed']['checked'])) {
372  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."element_time as tt ON (tt.fk_element = t.rowid AND tt.elementtype = 'task')";
373 }
374 if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
375  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)";
376 }
377 if ($search_project_user > 0) {
378  $sql .= ", ".MAIN_DB_PREFIX."element_contact as ecp";
379 }
380 if ($search_task_user > 0) {
381  $sql .= ", ".MAIN_DB_PREFIX."element_contact as ect";
382 }
383 $sql .= " WHERE t.fk_projet = p.rowid";
384 $sql .= " AND p.entity IN (".getEntity('project').')';
385 if (empty($user->rights->projet->all->lire)) {
386  $sql .= " AND p.rowid IN (".$db->sanitize($projectsListId ? $projectsListId : '0').")"; // public and assigned to projects, or restricted to company for external users
387 }
388 if (is_object($projectstatic) && $projectstatic->id > 0) {
389  $sql .= " AND p.rowid = ".((int) $projectstatic->id);
390 }
391 // No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
392 if ($socid) {
393  $sql .= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".((int) $socid).")";
394 }
395 if ($search_project_ref) {
396  $sql .= natural_search('p.ref', $search_project_ref);
397 }
398 if ($search_project_title) {
399  $sql .= natural_search('p.title', $search_project_title);
400 }
401 if ($search_task_ref) {
402  $sql .= natural_search('t.ref', $search_task_ref);
403 }
404 if ($search_task_label) {
405  $sql .= natural_search('t.label', $search_task_label);
406 }
407 if ($search_task_description) {
408  $sql .= natural_search('t.description', $search_task_description);
409 }
410 if ($search_task_ref_parent) {
411  $sql .= ' AND t.fk_task_parent IN (SELECT ipt.rowid FROM '.MAIN_DB_PREFIX.'projet_task as ipt WHERE '.natural_search('ipt.ref', $search_task_ref_parent, 0, 1).')';
412 }
413 if ($search_task_progress) {
414  $sql .= natural_search('t.progress', $search_task_progress, 1);
415 }
416 if ($search_task_budget_amount) {
417  $sql .= natural_search('t.budget_amount', $search_task_budget_amount, 1);
418 }
419 if (empty($arrayfields['s.name_alias']['checked']) && $search_societe) {
420  $sql .= natural_search(array("s.nom", "s.name_alias"), $search_societe);
421 } else {
422  if ($search_societe) {
423  $sql .= natural_search('s.nom', $search_societe);
424  }
425  if ($search_societe_alias) {
426  $sql .= natural_search('s.name_alias', $search_societe_alias);
427  }
428 }
429 if ($search_date_start) {
430  $sql .= " AND t.dateo >= '".$db->idate($search_date_start)."'";
431 }
432 if ($search_date_end) {
433  $sql .= " AND t.dateo <= '".$db->idate($search_date_end)."'";
434 }
435 if ($search_datelimit_start) {
436  $sql .= " AND t.datee >= '".$db->idate($search_datelimit_start)."'";
437 }
438 if ($search_datelimit_end) {
439  $sql .= " AND t.datee <= '".$db->idate($search_datelimit_end)."'";
440 }
441 if ($search_all) {
442  $sql .= natural_search(array_keys($fieldstosearchall), $search_all);
443 }
444 if ($search_projectstatus >= 0) {
445  if ($search_projectstatus == 99) {
446  $sql .= " AND p.fk_statut <> 2";
447  } else {
448  $sql .= " AND p.fk_statut = ".((int) $search_projectstatus);
449  }
450 }
451 if ($search_project_user > 0) {
452  $sql .= " AND ecp.fk_c_type_contact IN (".$db->sanitize(join(',', array_keys($listofprojectcontacttype))).") AND ecp.element_id = p.rowid AND ecp.fk_socpeople = ".((int) $search_project_user);
453 }
454 if ($search_task_user > 0) {
455  $sql .= " AND ect.fk_c_type_contact IN (".$db->sanitize(join(',', array_keys($listoftaskcontacttype))).") AND ect.element_id = t.rowid AND ect.fk_socpeople = ".((int) $search_task_user);
456 }
457 // Search for tag/category ($searchCategoryProjectList is an array of ID)
458 $searchCategoryProjectList = array($search_categ);
459 $searchCategoryProjectOperator = 0;
460 if (!empty($searchCategoryProjectList)) {
461  $searchCategoryProjectSqlList = array();
462  $listofcategoryid = '';
463  foreach ($searchCategoryProjectList as $searchCategoryProject) {
464  if (intval($searchCategoryProject) == -2) {
465  $searchCategoryProjectSqlList[] = "NOT EXISTS (SELECT ck.fk_project FROM ".MAIN_DB_PREFIX."categorie_project as ck WHERE p.rowid = ck.fk_project)";
466  } elseif (intval($searchCategoryProject) > 0) {
467  if ($searchCategoryProjectOperator == 0) {
468  $searchCategoryProjectSqlList[] = " EXISTS (SELECT ck.fk_project FROM ".MAIN_DB_PREFIX."categorie_project as ck WHERE p.rowid = ck.fk_project AND ck.fk_categorie = ".((int) $searchCategoryProject).")";
469  } else {
470  $listofcategoryid .= ($listofcategoryid ? ', ' : '') .((int) $searchCategoryProject);
471  }
472  }
473  }
474  if ($listofcategoryid) {
475  $searchCategoryProjectSqlList[] = " EXISTS (SELECT ck.fk_project FROM ".MAIN_DB_PREFIX."categorie_project as ck WHERE p.rowid = ck.fk_project AND ck.fk_categorie IN (".$db->sanitize($listofcategoryid)."))";
476  }
477  if ($searchCategoryProjectOperator == 1) {
478  if (!empty($searchCategoryProjectSqlList)) {
479  $sql .= " AND (".implode(' OR ', $searchCategoryProjectSqlList).")";
480  }
481  } else {
482  if (!empty($searchCategoryProjectSqlList)) {
483  $sql .= " AND (".implode(' AND ', $searchCategoryProjectSqlList).")";
484  }
485  }
486 }
487 $searchCategoryCustomerSqlList = array();
488 if ($searchCategoryCustomerOperator == 1) {
489  $existsCategoryCustomerList = array();
490  foreach ($searchCategoryCustomerList as $searchCategoryCustomer) {
491  if (intval($searchCategoryCustomer) == -2) {
492  $sqlCategoryCustomerNotExists = " NOT EXISTS (";
493  $sqlCategoryCustomerNotExists .= " SELECT cat_cus.fk_soc";
494  $sqlCategoryCustomerNotExists .= " FROM ".$db->prefix()."categorie_societe AS cat_cus";
495  $sqlCategoryCustomerNotExists .= " WHERE cat_cus.fk_soc = p.fk_soc";
496  $sqlCategoryCustomerNotExists .= " )";
497  $searchCategoryCustomerSqlList[] = $sqlCategoryCustomerNotExists;
498  } elseif (intval($searchCategoryCustomer) > 0) {
499  $existsCategoryCustomerList[] = $db->escape($searchCategoryCustomer);
500  }
501  }
502  if (!empty($existsCategoryCustomerList)) {
503  $sqlCategoryCustomerExists = " EXISTS (";
504  $sqlCategoryCustomerExists .= " SELECT cat_cus.fk_soc";
505  $sqlCategoryCustomerExists .= " FROM ".$db->prefix()."categorie_societe AS cat_cus";
506  $sqlCategoryCustomerExists .= " WHERE cat_cus.fk_soc = p.fk_soc";
507  $sqlCategoryCustomerExists .= " AND cat_cus.fk_categorie IN (".$db->sanitize(implode(',', $existsCategoryCustomerList)).")";
508  $sqlCategoryCustomerExists .= " )";
509  $searchCategoryCustomerSqlList[] = $sqlCategoryCustomerExists;
510  }
511  if (!empty($searchCategoryCustomerSqlList)) {
512  $sql .= " AND (".implode(' OR ', $searchCategoryCustomerSqlList).")";
513  }
514 } else {
515  foreach ($searchCategoryCustomerList as $searchCategoryCustomer) {
516  if (intval($searchCategoryCustomer) == -2) {
517  $sqlCategoryCustomerNotExists = " NOT EXISTS (";
518  $sqlCategoryCustomerNotExists .= " SELECT cat_cus.fk_soc";
519  $sqlCategoryCustomerNotExists .= " FROM ".$db->prefix()."categorie_societe AS cat_cus";
520  $sqlCategoryCustomerNotExists .= " WHERE cat_cus.fk_soc = p.fk_soc";
521  $sqlCategoryCustomerNotExists .= " )";
522  $searchCategoryCustomerSqlList[] = $sqlCategoryCustomerNotExists;
523  } elseif (intval($searchCategoryCustomer) > 0) {
524  $searchCategoryCustomerSqlList[] = "p.fk_soc IN (SELECT fk_soc FROM ".$db->prefix()."categorie_societe WHERE fk_categorie = ".((int) $searchCategoryCustomer).")";
525  }
526  }
527  if (!empty($searchCategoryCustomerSqlList)) {
528  $sql .= " AND (".implode(' AND ', $searchCategoryCustomerSqlList).")";
529  }
530 }
531 // Add where from extra fields
532 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
533 // Add where from hooks
534 $parameters = array();
535 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
536 $sql .= $hookmanager->resPrint;
537 if (!empty($arrayfields['t.tobill']['checked']) || !empty($arrayfields['t.billed']['checked'])) {
538  $sql .= " GROUP BY p.rowid, p.ref, p.title, p.fk_statut, p.datee, p.fk_opp_status, p.public, p.fk_user_creat,";
539  $sql .= " s.nom, s.rowid,";
540  $sql .= " t.datec, t.dateo, t.datee, t.tms,";
541  $sql .= " t.rowid, t.ref, t.label, t.planned_workload, t.duration_effective, t.progress,t.budget_amount, t.fk_statut";
542  // Add fields from extrafields
543  if (!empty($extrafields->attributes[$object->table_element]['label'])) {
544  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
545  $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key : '');
546  }
547  }
548 }
549 
550 // Count total nb of records
551 $nbtotalofrecords = '';
552 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
553  /* The fast and low memory method to get and count full list converts the sql into a sql count */
554  $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
555  $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
556  $resql = $db->query($sqlforcount);
557  if ($resql) {
558  $objforcount = $db->fetch_object($resql);
559  $nbtotalofrecords = $objforcount->nbtotalofrecords;
560  } else {
561  dol_print_error($db);
562  }
563 
564  if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
565  $page = 0;
566  $offset = 0;
567  }
568  $db->free($resql);
569 }
570 
571 // Complete request and execute it with limit
572 $sql .= $db->order($sortfield, $sortorder);
573 if ($limit) {
574  $sql .= $db->plimit($limit + 1, $offset);
575 }
576 
577 $resql = $db->query($sql);
578 if (!$resql) {
579  dol_print_error($db);
580  exit;
581 }
582 
583 $num = $db->num_rows($resql);
584 
585 
586 // Direct jump if only one record found
587 if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all) {
588  $obj = $db->fetch_object($resql);
589  $id = $obj->id; // in select, task id has been aliases into 'id'
590  header("Location: ".DOL_URL_ROOT.'/projet/tasks/task.php?id='.$id.'&withproject=1');
591  exit;
592 }
593 
594 
595 // Output page
596 // --------------------------------------------------------------------
597 
598 llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist'); // Can use also classforhorizontalscrolloftabs instead of bodyforlist for no horizontal scroll
599 
600 $arrayofselected = is_array($toselect) ? $toselect : array();
601 
602 $param = '';
603 if (!empty($mode)) {
604  $param .= '&mode='.urlencode($mode);
605 }
606 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
607  $param .= '&contextpage='.urlencode($contextpage);
608 }
609 if ($limit > 0 && $limit != $conf->liste_limit) {
610  $param .= '&limit='.((int) $limit);
611 }
612 if ($search_date_startday) {
613  $param .= '&search_date_startday='.urlencode($search_date_startday);
614 }
615 if ($search_date_startmonth) {
616  $param .= '&search_date_startmonth='.urlencode($search_date_startmonth);
617 }
618 if ($search_date_startyear) {
619  $param .= '&search_date_startyear='.urlencode($search_date_startyear);
620 }
621 if ($search_date_endday) {
622  $param .= '&search_date_endday='.urlencode($search_date_endday);
623 }
624 if ($search_date_endmonth) {
625  $param .= '&search_date_endmonth='.urlencode($search_date_endmonth);
626 }
627 if ($search_date_endyear) {
628  $param .= '&search_date_endyear='.urlencode($search_date_endyear);
629 }
630 if ($search_datelimit_startday) {
631  $param .= '&search_datelimit_startday='.urlencode($search_datelimit_startday);
632 }
633 if ($search_datelimit_startmonth) {
634  $param .= '&search_datelimit_startmonth='.urlencode($search_datelimit_startmonth);
635 }
636 if ($search_datelimit_startyear) {
637  $param .= '&search_datelimit_startyear='.urlencode($search_datelimit_startyear);
638 }
639 if ($search_datelimit_endday) {
640  $param .= '&search_datelimit_endday='.urlencode($search_datelimit_endday);
641 }
642 if ($search_datelimit_endmonth) {
643  $param .= '&search_datelimit_endmonth='.urlencode($search_datelimit_endmonth);
644 }
645 if ($search_datelimit_endyear) {
646  $param .= '&search_datelimit_endyear='.urlencode($search_datelimit_endyear);
647 }
648 if ($search_task_budget_amount) {
649  $param .= '&search_task_budget_amount='.urlencode($search_task_budget_amount);
650 }
651 if ($socid) {
652  $param .= '&socid='.urlencode($socid);
653 }
654 if ($search_all != '') {
655  $param .= '&search_all='.urlencode($search_all);
656 }
657 if ($search_project_ref != '') {
658  $param .= '&search_project_ref='.urlencode($search_project_ref);
659 }
660 if ($search_project_title != '') {
661  $param .= '&search_project_title='.urlencode($search_project_title);
662 }
663 if ($search_task_ref != '') {
664  $param .= '&search_task_ref='.urlencode($search_task_ref);
665 }
666 if ($search_task_label != '') {
667  $param .= '&search_task_label='.urlencode($search_task_label);
668 }
669 if ($search_task_description != '') {
670  $param .= '&search_task_description='.urlencode($search_task_description);
671 }
672 if ($search_task_ref_parent != '') {
673  $param .= '&search_task_ref_parent='.urlencode($search_task_ref_parent);
674 }
675 if ($search_task_progress != '') {
676  $param .= '&search_task_progress='.urlencode($search_task_progress);
677 }
678 if ($search_societe != '') {
679  $param .= '&search_societe='.urlencode($search_societe);
680 }
681 if ($search_societe != '') {
682  $param .= '&search_societe_alias='.urlencode($search_societe_alias);
683 }
684 if ($search_projectstatus != '') {
685  $param .= '&search_projectstatus='.urlencode($search_projectstatus);
686 }
687 if ((is_numeric($search_opp_status) && $search_opp_status >= 0) || in_array($search_opp_status, array('all', 'none'))) {
688  $param .= '&search_opp_status='.urlencode($search_opp_status);
689 }
690 if ($search_project_user != '') {
691  $param .= '&search_project_user='.urlencode($search_project_user);
692 }
693 if ($search_task_user > 0) {
694  $param .= '&search_task_user='.urlencode($search_task_user);
695 }
696 if ($optioncss != '') {
697  $param .= '&optioncss='.urlencode($optioncss);
698 }
699 foreach ($searchCategoryCustomerList as $searchCategoryCustomer) {
700  $param .= "&search_category_customer_list[]=".urlencode($searchCategoryCustomer);
701 }
702 // Add $param from extra fields
703 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
704 // Add $param from hooks
705 $parameters = array();
706 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook
707 $param .= $hookmanager->resPrint;
708 
709 // List of mass actions available
710 $arrayofmassactions = array(
711 // 'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
712 // 'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
713 );
714 //if($user->rights->societe->creer) $arrayofmassactions['createbills']=$langs->trans("CreateInvoiceForThisCustomer");
715 if (!empty($permissiontodelete)) {
716  $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
717 }
718 if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) {
719  $arrayofmassactions = array();
720 }
721 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
722 
723 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
724 if ($optioncss != '') {
725  print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
726 }
727 print '<input type="hidden" name="token" value="'.newToken().'">';
728 print '<input type="hidden" name="action" value="list">';
729 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
730 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
731 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
732 print '<input type="hidden" name="page" value="'.$page.'">';
733 if (!empty($type)) {
734  print '<input type="hidden" name="type" value="'.$type.'">';
735 }
736 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
737 print '<input type="hidden" name="page_y" value="">';
738 print '<input type="hidden" name="mode" value="'.$mode.'">';
739 
740 
741 $newcardbutton = '';
742 
743 $newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss'=>'reposition'));
744 $newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition'));
745 $newcardbutton .= dolGetButtonTitle($langs->trans('NewTask'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/tasks.php?action=create', '', $permissiontocreate);
746 
747 
748 // Show description of content
749 $texthelp = '';
750 if ($search_task_user == $user->id) {
751  $texthelp .= $langs->trans("MyTasksDesc");
752 } else {
753  if ($user->hasRight('projet', 'all', 'lire') && !$socid) {
754  $texthelp .= $langs->trans("TasksOnProjectsDesc");
755  } else {
756  $texthelp .= $langs->trans("TasksOnProjectsPublicDesc");
757  }
758 }
759 
760 print_barre_liste($form->textwithpicto($title, $texthelp), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'projecttask', 0, $newcardbutton, '', $limit, 0, 0, 1);
761 
762 $topicmail = "Information";
763 $modelmail = "task";
764 $objecttmp = new Task($db);
765 $trackid = 'tas'.$object->id;
766 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
767 
768 if ($search_all) {
769  $setupstring = '';
770  foreach ($fieldstosearchall as $key => $val) {
771  $fieldstosearchall[$key] = $langs->trans($val);
772  $setupstring .= $key."=".$val.";";
773  }
774  print '<!-- Search done like if TASK_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
775  print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'</div>'."\n";
776 }
777 
778 $moreforfilter = '';
779 
780 // Filter on categories
781 if (isModEnabled('categorie') && $user->hasRight('categorie', 'lire')) {
782  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
783  $moreforfilter .= '<div class="divsearchfield">';
784  $tmptitle = $langs->trans('ProjectCategories');
785  $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"').$formother->select_categories('project', $search_categ, 'search_categ', 1, $tmptitle, 'maxwidth300');
786  $moreforfilter .= '</div>';
787 }
788 
789 // If the user can view users
790 $moreforfilter .= '<div class="divsearchfield">';
791 $tmptitle = $langs->trans('ProjectsWithThisUserAsContact');
792 $includeonly = '';
793 if (empty($user->rights->user->user->lire)) {
794  $includeonly = array($user->id);
795 }
796 $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_project_user ? $search_project_user : '', 'search_project_user', $tmptitle, '', 0, $includeonly, '', 0, 0, 0, '', 0, '', 'maxwidth250');
797 $moreforfilter .= '</div>';
798 
799 // If the user can view users
800 $moreforfilter .= '<div class="divsearchfield">';
801 $tmptitle = $langs->trans('TasksWithThisUserAsContact');
802 $includeonly = '';
803 if (empty($user->rights->user->user->lire)) {
804  $includeonly = array($user->id);
805 }
806 $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_task_user, 'search_task_user', $tmptitle, '', 0, $includeonly, '', 0, 0, 0, '', 0, '', 'maxwidth250');
807 $moreforfilter .= '</div>';
808 
809 // Filter on customer categories
810 if (!empty($conf->global->MAIN_SEARCH_CATEGORY_CUSTOMER_ON_TASK_LIST) && isModEnabled("categorie") && $user->hasRight('categorie', 'lire')) {
811  $moreforfilter .= '<div class="divsearchfield">';
812  $tmptitle = $langs->transnoentities('CustomersProspectsCategoriesShort');
813  $moreforfilter .= img_picto($tmptitle, 'category', 'class="pictofixedwidth"');
814  $categoriesArr = $form->select_all_categories(Categorie::TYPE_CUSTOMER, '', '', 64, 0, 1);
815  $categoriesArr[-2] = '- '.$langs->trans('NotCategorized').' -';
816  $moreforfilter .= Form::multiselectarray('search_category_customer_list', $categoriesArr, $searchCategoryCustomerList, 0, 0, 'minwidth300', 0, 0, '', 'category', $tmptitle);
817  $moreforfilter .= ' <input type="checkbox" class="valignmiddle" id="search_category_customer_operator" name="search_category_customer_operator" value="1"'.($searchCategoryCustomerOperator == 1 ? ' checked="checked"' : '').'/>';
818  $moreforfilter .= $form->textwithpicto('', $langs->trans('UseOrOperatorForCategories') . ' : ' . $tmptitle, 1, 'help', '', 0, 2, 'tooltip_cat_cus'); // Tooltip on click
819  $moreforfilter .= '</div>';
820 }
821 
822 if (!empty($moreforfilter)) {
823  print '<div class="liste_titre liste_titre_bydiv centpercent">';
824  print $moreforfilter;
825  $parameters = array();
826  $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
827  print $hookmanager->resPrint;
828  print '</div>';
829 }
830 
831 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
832 $selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields
833 $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
834 
835 print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
836 print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'" id="tablelines3">'."\n";
837 
838 // Fields title search
839 // --------------------------------------------------------------------
840 print '<tr class="liste_titre_filter">';
841 // Action column
842 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
843  print '<td class="liste_titre center maxwidthsearch">';
844  $searchpicto = $form->showFilterButtons('left');
845  print $searchpicto;
846  print '</td>';
847 }
848 if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
849  print '<td class="liste_titre">';
850  print '<input type="text" class="flat" name="search_task_ref_parent" value="'.dol_escape_htmltag($search_task_ref_parent).'" size="4">';
851  print '</td>';
852 }
853 if (!empty($arrayfields['t.ref']['checked'])) {
854  print '<td class="liste_titre">';
855  print '<input type="text" class="flat" name="search_task_ref" value="'.dol_escape_htmltag($search_task_ref).'" size="4">';
856  print '</td>';
857 }
858 if (!empty($arrayfields['t.label']['checked'])) {
859  print '<td class="liste_titre">';
860  print '<input type="text" class="flat" name="search_task_label" value="'.dol_escape_htmltag($search_task_label).'" size="8">';
861  print '</td>';
862 }
863 // Task Description
864 if (!empty($arrayfields['t.description']['checked'])) {
865  print '<td class="liste_titre">';
866  print '<input type="text" class="flat" name="search_task_description" value="'.dol_escape_htmltag($search_task_description).'" size="8">';
867  print '</td>';
868 }
869 // Start date
870 if (!empty($arrayfields['t.dateo']['checked'])) {
871  print '<td class="liste_titre center">';
872  print '<div class="nowrap">';
873  print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
874  print '</div>';
875  print '<div class="nowrap">';
876  print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
877  print '</div>';
878  print '</td>';
879 }
880 // End date
881 if (!empty($arrayfields['t.datee']['checked'])) {
882  print '<td class="liste_titre center">';
883  print '<div class="nowrap">';
884  print $form->selectDate($search_datelimit_start ? $search_datelimit_start : -1, 'search_datelimit_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
885  print '</div>';
886  print '<div class="nowrap">';
887  print $form->selectDate($search_datelimit_end ? $search_datelimit_end : -1, 'search_datelimit_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
888  // TODO Add option late
889  //print '<br><input type="checkbox" name="search_option" value="late"'.($option == 'late' ? ' checked' : '').'> '.$langs->trans("Alert");
890  print '</div>';
891  print '</td>';
892 }
893 if (!empty($arrayfields['p.ref']['checked'])) {
894  print '<td class="liste_titre">';
895  print '<input type="text" class="flat" name="search_project_ref" value="'.$search_project_ref.'" size="4">';
896  print '</td>';
897 }
898 if (!empty($arrayfields['p.title']['checked'])) {
899  print '<td class="liste_titre">';
900  print '<input type="text" class="flat" name="search_project_title" value="'.$search_project_title.'" size="6">';
901  print '</td>';
902 }
903 if (!empty($arrayfields['s.nom']['checked'])) {
904  print '<td class="liste_titre">';
905  print '<input type="text" class="flat" name="search_societe" value="'.dol_escape_htmltag($search_societe).'" size="4">';
906  print '</td>';
907 }
908 if (!empty($arrayfields['s.name_alias']['checked'])) {
909  print '<td class="liste_titre">';
910  print '<input type="text" class="flat" name="search_societe_alias" value="'.dol_escape_htmltag($search_societe_alias).'" size="4">';
911  print '</td>';
912 }
913 if (!empty($arrayfields['p.fk_statut']['checked'])) {
914  print '<td class="liste_titre center">';
915  $arrayofstatus = array();
916  foreach ($projectstatic->statuts_short as $key => $val) {
917  $arrayofstatus[$key] = $langs->trans($val);
918  }
919  $arrayofstatus['99'] = $langs->trans("NotClosed").' ('.$langs->trans('Draft').'+'.$langs->trans('Opened').')';
920  print $form->selectarray('search_projectstatus', $arrayofstatus, $search_projectstatus, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth100');
921  print '</td>';
922 }
923 if (!empty($arrayfields['t.planned_workload']['checked'])) {
924  print '<td class="liste_titre"></td>';
925 }
926 if (!empty($arrayfields['t.duration_effective']['checked'])) {
927  print '<td class="liste_titre"></td>';
928 }
929 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
930  print '<td class="liste_titre"></td>';
931 }
932 if (!empty($arrayfields['t.progress']['checked'])) {
933  print '<td class="liste_titre center">';
934  print '<input type="text" class="flat" name="search_task_progress" value="'.$search_task_progress.'" size="4">';
935  print '</td>';
936 }
937 
938 if (!empty($arrayfields['t.progress_summary']['checked'])) {
939  print '<td class="liste_titre"></td>';
940 }
941 
942 if (!empty($arrayfields['t.budget_amount']['checked'])) {
943  print '<td class="liste_titre center">';
944  print '<input type="text" class="flat" name="search_task_budget_amount" value="'.$search_task_budget_amount.'" size="4">';
945  print '</td>';
946 }
947 
948 if (!empty($arrayfields['t.tobill']['checked'])) {
949  print '<td class="liste_titre"></td>';
950 }
951 if (!empty($arrayfields['t.billed']['checked'])) {
952  print '<td class="liste_titre"></td>';
953 }
954 // Extra fields
955 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
956 // Fields from hook
957 $parameters = array('arrayfields'=>$arrayfields);
958 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
959 print $hookmanager->resPrint;
960 if (!empty($arrayfields['t.datec']['checked'])) {
961  // Date creation
962  print '<td class="liste_titre">';
963  print '</td>';
964 }
965 if (!empty($arrayfields['t.tms']['checked'])) {
966  // Date modification
967  print '<td class="liste_titre">';
968  print '</td>';
969 }
970 // Action column
971 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
972  print '<td class="liste_titre center maxwidthsearch">';
973  $searchpicto = $form->showFilterButtons();
974  print $searchpicto;
975  print '</td>';
976 }
977 print '</tr>'."\n";
978 
979 $totalarray = array(
980  'nbfield' => 0,
981  'val' => array(
982  't.planned_workload' => 0,
983  't.duration_effective' => 0,
984  't.progress' => 0,
985  't.budget_amount' => 0,
986  ),
987  'totalplannedworkload' => 0,
988  'totaldurationeffective' => 0,
989  'totaldurationdeclared' => 0,
990  'totaltobillfield' => 0,
991  'totalbilledfield' => 0,
992  'totalbudget_amountfield' => 0,
993  'totalbudgetamount' => 0,
994  'totaltobill' => 0,
995  'totalbilled' => 0,
996 );
997 
998 // Fields title label
999 // --------------------------------------------------------------------
1000 print '<tr class="liste_titre">';
1001 // Action column
1002 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1003  print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1004  $totalarray['nbfield']++;
1005 }
1006 if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
1007  print_liste_field_titre($arrayfields['t.fk_task_parent']['label'], $_SERVER["PHP_SELF"], "t.fk_task_parent", "", $param, "", $sortfield, $sortorder);
1008  $totalarray['nbfield']++;
1009 }
1010 if (!empty($arrayfields['t.ref']['checked'])) {
1011  print_liste_field_titre($arrayfields['t.ref']['label'], $_SERVER["PHP_SELF"], "t.ref", "", $param, "", $sortfield, $sortorder);
1012  $totalarray['nbfield']++;
1013 }
1014 if (!empty($arrayfields['t.label']['checked'])) {
1015  print_liste_field_titre($arrayfields['t.label']['label'], $_SERVER["PHP_SELF"], "t.label", "", $param, "", $sortfield, $sortorder);
1016  $totalarray['nbfield']++;
1017 }
1018 if (!empty($arrayfields['t.description']['checked'])) {
1019  print_liste_field_titre($arrayfields['t.description']['label'], $_SERVER["PHP_SELF"], "t.description", "", $param, "", $sortfield, $sortorder);
1020  $totalarray['nbfield']++;
1021 }
1022 if (!empty($arrayfields['t.dateo']['checked'])) {
1023  print_liste_field_titre($arrayfields['t.dateo']['label'], $_SERVER["PHP_SELF"], "t.dateo", "", $param, '', $sortfield, $sortorder, 'center ');
1024  $totalarray['nbfield']++;
1025 }
1026 if (!empty($arrayfields['t.datee']['checked'])) {
1027  print_liste_field_titre($arrayfields['t.datee']['label'], $_SERVER["PHP_SELF"], "t.datee", "", $param, '', $sortfield, $sortorder, 'center ');
1028  $totalarray['nbfield']++;
1029 }
1030 if (!empty($arrayfields['p.ref']['checked'])) {
1031  print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder);
1032  $totalarray['nbfield']++;
1033 }
1034 if (!empty($arrayfields['p.title']['checked'])) {
1035  print_liste_field_titre($arrayfields['p.title']['label'], $_SERVER["PHP_SELF"], "p.title", "", $param, "", $sortfield, $sortorder);
1036  $totalarray['nbfield']++;
1037 }
1038 if (!empty($arrayfields['s.nom']['checked'])) {
1039  print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder);
1040  $totalarray['nbfield']++;
1041 }
1042 if (!empty($arrayfields['s.name_alias']['checked'])) {
1043  print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], "s.name_alias", "", $param, "", $sortfield, $sortorder);
1044  $totalarray['nbfield']++;
1045 }
1046 if (!empty($arrayfields['p.fk_statut']['checked'])) {
1047  print_liste_field_titre($arrayfields['p.fk_statut']['label'], $_SERVER["PHP_SELF"], "p.fk_statut", "", $param, '', $sortfield, $sortorder, 'center ');
1048  $totalarray['nbfield']++;
1049 }
1050 if (!empty($arrayfields['t.planned_workload']['checked'])) {
1051  print_liste_field_titre($arrayfields['t.planned_workload']['label'], $_SERVER["PHP_SELF"], "t.planned_workload", "", $param, '', $sortfield, $sortorder, 'center ');
1052  $totalarray['nbfield']++;
1053 }
1054 if (!empty($arrayfields['t.duration_effective']['checked'])) {
1055  print_liste_field_titre($arrayfields['t.duration_effective']['label'], $_SERVER["PHP_SELF"], "t.duration_effective", "", $param, '', $sortfield, $sortorder, 'center ');
1056  $totalarray['nbfield']++;
1057 }
1058 if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1059  print_liste_field_titre($arrayfields['t.progress_calculated']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', '', '', 'center ');
1060  $totalarray['nbfield']++;
1061 }
1062 if (!empty($arrayfields['t.progress']['checked'])) {
1063  print_liste_field_titre($arrayfields['t.progress']['label'], $_SERVER["PHP_SELF"], "t.progress", "", $param, '', $sortfield, $sortorder, 'center ');
1064  $totalarray['nbfield']++;
1065 }
1066 if (!empty($arrayfields['t.progress_summary']['checked'])) {
1067  print_liste_field_titre($arrayfields['t.progress_summary']['label'], $_SERVER["PHP_SELF"], "t.progress", "", $param, '', $sortfield, $sortorder, 'center ');
1068  $totalarray['nbfield']++;
1069 }
1070 if (!empty($arrayfields['t.budget_amount']['checked'])) {
1071  print_liste_field_titre($arrayfields['t.budget_amount']['label'], $_SERVER["PHP_SELF"], "t.budget_amount", "", $param, '', $sortfield, $sortorder, 'center ');
1072  $totalarray['nbfield']++;
1073 }
1074 if (!empty($arrayfields['t.tobill']['checked'])) {
1075  print_liste_field_titre($arrayfields['t.tobill']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1076  $totalarray['nbfield']++;
1077 }
1078 if (!empty($arrayfields['t.billed']['checked'])) {
1079  print_liste_field_titre($arrayfields['t.billed']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'center ');
1080  $totalarray['nbfield']++;
1081 }
1082 // Extra fields
1083 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1084 // Hook fields
1085 $parameters = array(
1086  'arrayfields' => $arrayfields,
1087  'param' => $param,
1088  'sortfield' => $sortfield,
1089  'sortorder' => $sortorder,
1090  'totalarray' => &$totalarray,
1091 );
1092 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
1093 print $hookmanager->resPrint;
1094 if (!empty($arrayfields['t.datec']['checked'])) {
1095  print_liste_field_titre($arrayfields['t.datec']['label'], $_SERVER["PHP_SELF"], "t.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1096  $totalarray['nbfield']++;
1097 }
1098 if (!empty($arrayfields['t.tms']['checked'])) {
1099  print_liste_field_titre($arrayfields['t.tms']['label'], $_SERVER["PHP_SELF"], "t.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1100  $totalarray['nbfield']++;
1101 }
1102 // Action column
1103 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1104  print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1105  $totalarray['nbfield']++;
1106 }
1107 print '</tr>'."\n";
1108 
1109 $plannedworkloadoutputformat = 'allhourmin';
1110 $timespentoutputformat = 'allhourmin';
1111 if (!empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) {
1112  $plannedworkloadoutputformat = $conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
1113 }
1114 if (!empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) {
1115  $timespentoutputformat = $conf->global->PROJECT_TIME_SPENT_FORMAT;
1116 }
1117 
1118 // Loop on record
1119 // --------------------------------------------------------------------
1120 $i = 0;
1121 $savnbfield = $totalarray['nbfield'];
1122 $totalarray = array();
1123 $totalarray['nbfield'] = 0;
1124 $imaxinloop = ($limit ? min($num, $limit) : $num);
1125 while ($i < $imaxinloop) {
1126  $obj = $db->fetch_object($resql);
1127  if (empty($obj)) {
1128  break; // Should not happen
1129  }
1130 
1131  // Store properties in $object
1132  $object->id = $obj->id;
1133  $object->ref = $obj->ref;
1134  $object->label = $obj->label;
1135  $object->description = $obj->description;
1136  $object->fk_statut = $obj->fk_statut;
1137  $object->progress = $obj->progress;
1138  $object->budget_amount = $obj->budget_amount;
1139  $object->date_start = $db->jdate($obj->date_start);
1140  $object->date_end = $db->jdate($obj->date_end);
1141  $object->planned_workload = $obj->planned_workload;
1142  $object->duration_effective = $obj->duration_effective;
1143  $object->fk_task_parent = $obj->fk_task_parent;
1144 
1145  $projectstatic->id = $obj->projectid;
1146  $projectstatic->ref = $obj->projectref;
1147  $projectstatic->title = $obj->projecttitle;
1148  $projectstatic->public = $obj->public;
1149  $projectstatic->statut = $obj->projectstatus;
1150  $projectstatic->datee = $db->jdate($obj->projectdatee);
1151 
1152  if ($obj->socid) {
1153  $socstatic->id = $obj->socid;
1154  $socstatic->name = $obj->name;
1155  $socstatic->name_alias = $obj->alias;
1156  }
1157  if ($mode == 'kanban') {
1158  if ($i == 0) {
1159  print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
1160  print '<div class="box-flex-container kanban">';
1161  }
1162  // Output Kanban
1163  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1164  $selected = 0;
1165  if (in_array($object->id, $arrayofselected)) {
1166  $selected = 1;
1167  }
1168  }
1169 
1170  $arraydata = array();
1171  $arraydata['projectlink'] = $projectstatic->getNomUrl(1);
1172  $arraydata['selected'] = in_array($object->id, $arrayofselected);
1173 
1174  print $object->getKanbanView('', $arraydata);
1175  if ($i == ($imaxinloop - 1)) {
1176  print '</div>';
1177  print '</td></tr>';
1178  }
1179  } else {
1180  $userAccess = $projectstatic->restrictedProjectArea($user); // why this ?
1181  if ($userAccess >= 0) {
1182  // Show here line of result
1183  $j = 0;
1184  print '<tr data-rowid="'.$object->id.'" class="oddeven">';
1185 
1186  // Action column
1187  if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1188  print '<td class="nowrap center">';
1189  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1190  $selected = 0;
1191  if (in_array($object->id, $arrayofselected)) {
1192  $selected = 1;
1193  }
1194  print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1195  }
1196  print '</td>';
1197  if (!$i) {
1198  $totalarray['nbfield']++;
1199  }
1200  }
1201  // Ref Parent
1202  if (!empty($arrayfields['t.fk_task_parent']['checked'])) {
1203  print '<td class="nowraponall">';
1204  if (!empty($object->fk_task_parent)) {
1205  $object_parent = new Task($db);
1206  $result = $object_parent->fetch($object->fk_task_parent);
1207  if ($result < 0) {
1208  setEventMessage($object_parent->error, 'errors');
1209  } else {
1210  print $object_parent->getNomUrl(1, 'withproject');
1211  if ($object_parent->hasDelay()) {
1212  print img_warning("Late");
1213  }
1214  }
1215  }
1216  print '</td>';
1217  if (!$i) {
1218  $totalarray['nbfield']++;
1219  }
1220  }
1221  // Ref
1222  if (!empty($arrayfields['t.ref']['checked'])) {
1223  print '<td class="nowraponall">';
1224  print $object->getNomUrl(1, 'withproject');
1225  if ($object->hasDelay()) {
1226  print img_warning("Late");
1227  }
1228  print '</td>';
1229  if (!$i) {
1230  $totalarray['nbfield']++;
1231  }
1232  }
1233  // Label
1234  if (!empty($arrayfields['t.label']['checked'])) {
1235  print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($object->label).'">';
1236  print dol_escape_htmltag($object->label);
1237  print '</td>';
1238  if (!$i) {
1239  $totalarray['nbfield']++;
1240  }
1241  }
1242  // Description
1243  if (!empty($arrayfields['t.description']['checked'])) {
1244  print '<td>';
1245  print dolGetFirstLineOfText($object->description, 5);
1246  print '</td>';
1247  if (!$i) {
1248  $totalarray['nbfield']++;
1249  }
1250  }
1251 
1252  // Date start project
1253  if (!empty($arrayfields['t.dateo']['checked'])) {
1254  print '<td class="center">';
1255  print dol_print_date($db->jdate($obj->date_start), 'day');
1256  print '</td>';
1257  if (!$i) {
1258  $totalarray['nbfield']++;
1259  }
1260  }
1261  // Date end project
1262  if (!empty($arrayfields['t.datee']['checked'])) {
1263  print '<td class="center">';
1264  print dol_print_date($db->jdate($obj->date_end), 'day');
1265  print '</td>';
1266  if (!$i) {
1267  $totalarray['nbfield']++;
1268  }
1269  }
1270  // Project ref
1271  if (!empty($arrayfields['p.ref']['checked'])) {
1272  print '<td class="nowraponall tdoverflowmax150">';
1273  print $projectstatic->getNomUrl(1, 'task');
1274  if ($projectstatic->hasDelay()) {
1275  print img_warning("Late");
1276  }
1277  print '</td>';
1278  if (!$i) {
1279  $totalarray['nbfield']++;
1280  }
1281  }
1282  // Project title
1283  if (!empty($arrayfields['p.title']['checked'])) {
1284  print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($obj->projecttitle).'">';
1285  print dol_escape_htmltag($obj->projecttitle);
1286  print '</td>';
1287  if (!$i) {
1288  $totalarray['nbfield']++;
1289  }
1290  }
1291  // Third party
1292  if (!empty($arrayfields['s.nom']['checked'])) {
1293  print '<td class="tdoverflowmax125">';
1294  if ($obj->socid) {
1295  print $socstatic->getNomUrl(1, '', 0, 0, -1, empty($arrayfields['s.name_alias']['checked']) ? 0 : 1);
1296  } else {
1297  print '&nbsp;';
1298  }
1299  print '</td>';
1300  if (!$i) {
1301  $totalarray['nbfield']++;
1302  }
1303  }
1304  // Alias
1305  if (!empty($arrayfields['s.name_alias']['checked'])) {
1306  print '<td class="tdoverflowmax125">';
1307  if ($obj->socid) {
1308  print $socstatic->name_alias;
1309  } else {
1310  print '&nbsp;';
1311  }
1312  print '</td>';
1313  if (!$i) {
1314  $totalarray['nbfield']++;
1315  }
1316  }
1317  // Project status
1318  if (!empty($arrayfields['p.fk_statut']['checked'])) {
1319  print '<td class="center">';
1320  print $projectstatic->getLibStatut(1);
1321  print '</td>';
1322  if (!$i) {
1323  $totalarray['nbfield']++;
1324  }
1325  }
1326 
1327  // Planned workload
1328  if (!empty($arrayfields['t.planned_workload']['checked'])) {
1329  print '<td class="center">';
1330  $fullhour = convertSecondToTime($obj->planned_workload, $plannedworkloadoutputformat);
1331  $workingdelay = convertSecondToTime($obj->planned_workload, 'all', 86400, 7); // TODO Replace 86400 and 7 to take account working hours per day and working day per weeks
1332  if ($obj->planned_workload != '') {
1333  print $fullhour;
1334  // TODO Add delay taking account of working hours per day and working day per week
1335  //if ($workingdelay != $fullhour) print '<br>('.$workingdelay.')';
1336  }
1337  //else print '--:--';
1338  print '</td>';
1339  if (!$i) {
1340  $totalarray['nbfield']++;
1341  }
1342  if (!$i) {
1343  $totalarray['pos'][$totalarray['nbfield']] = 't.planned_workload';
1344  }
1345  if (!isset($totalarray['val']['planned_workload'])) {
1346  $totalarray['val']['t.planned_workload'] = 0;
1347  }
1348  $totalarray['val']['t.planned_workload'] += $obj->planned_workload;
1349  if (!$i) {
1350  $totalarray['totalplannedworkloadfield'] = $totalarray['nbfield'];
1351  }
1352  if (!isset($totalarray['totalplannedworkload'])) {
1353  $totalarray['totalplannedworkload'] = 0;
1354  }
1355  $totalarray['totalplannedworkload'] += $obj->planned_workload;
1356  }
1357  // Time spent
1358  if (!empty($arrayfields['t.duration_effective']['checked'])) {
1359  $showlineingray = 0; $showproject = 1;
1360  print '<td class="center">';
1361  if ($showlineingray) {
1362  print '<i>';
1363  } else {
1364  print '<a href="'.DOL_URL_ROOT.'/projet/tasks/time.php?id='.$object->id.($showproject ? '' : '&withproject=1').'">';
1365  }
1366  if ($obj->duration_effective) {
1367  print convertSecondToTime($obj->duration_effective, $timespentoutputformat);
1368  } else {
1369  print '--:--';
1370  }
1371  if ($showlineingray) {
1372  print '</i>';
1373  } else {
1374  print '</a>';
1375  }
1376  print '</td>';
1377  if (!$i) {
1378  $totalarray['nbfield']++;
1379  }
1380  if (!$i) {
1381  $totalarray['pos'][$totalarray['nbfield']] = 't.duration_effective';
1382  }
1383  if (!isset($totalarray['val']['t.duration_effective'])) {
1384  $totalarray['val']['t.duration_effective'] = 0;
1385  }
1386  $totalarray['val']['t.duration_effective'] += $obj->duration_effective;
1387  if (!$i) {
1388  $totalarray['totaldurationeffectivefield'] = $totalarray['nbfield'];
1389  }
1390  if (!isset($totalarray['totaldurationeffective'])) {
1391  $totalarray['totaldurationeffective'] = 0;
1392  }
1393  $totalarray['totaldurationeffective'] += $obj->duration_effective;
1394  }
1395  // Calculated progress
1396  if (!empty($arrayfields['t.progress_calculated']['checked'])) {
1397  print '<td class="center">';
1398  if ($obj->planned_workload || $obj->duration_effective) {
1399  if ($obj->planned_workload) {
1400  print round(100 * $obj->duration_effective / $obj->planned_workload, 2).' %';
1401  } else {
1402  print $form->textwithpicto('', $langs->trans('WorkloadNotDefined'), 1, 'help');
1403  }
1404  }
1405  print '</td>';
1406  if (!$i) {
1407  $totalarray['nbfield']++;
1408  }
1409  if (!$i) {
1410  $totalarray['totalprogress_calculatedfield'] = $totalarray['nbfield'];
1411  }
1412  }
1413  // Declared progress
1414  if (!empty($arrayfields['t.progress']['checked'])) {
1415  print '<td class="center">';
1416  if ($obj->progress != '') {
1417  print getTaskProgressBadge($object);
1418  }
1419  print '</td>';
1420  if (!$i) {
1421  $totalarray['nbfield']++;
1422  }
1423  if (!$i) {
1424  $totalarray['pos'][$totalarray['nbfield']] = 't.progress';
1425  }
1426  if (!isset($totalarray['val']['t.progress'])) {
1427  $totalarray['val']['t.progress'] = 0;
1428  }
1429  $totalarray['val']['t.progress'] += ($obj->planned_workload * $obj->progress / 100);
1430  if (!$i) {
1431  $totalarray['totalprogress_declaredfield'] = $totalarray['nbfield'];
1432  }
1433  if (!isset($totalarray['totaldurationdeclared'])) {
1434  $totalarray['totaldurationdeclared'] = 0;
1435  }
1436  $totalarray['totaldurationdeclared'] += $obj->planned_workload * $obj->progress / 100;
1437  }
1438  // Progress summary
1439  if (!empty($arrayfields['t.progress_summary']['checked'])) {
1440  print '<td class="center">';
1441  if ($obj->progress != '' && $obj->duration_effective) {
1442  print getTaskProgressView($object, false, false);
1443  }
1444  print '</td>';
1445  if (!$i) {
1446  $totalarray['nbfield']++;
1447  }
1448  if (!$i) {
1449  $totalarray['totalprogress_summary'] = $totalarray['nbfield'];
1450  }
1451  }
1452  // Budget for task
1453  if (!empty($arrayfields['t.budget_amount']['checked'])) {
1454  print '<td class="center">';
1455  if ($object->budget_amount) {
1456  print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
1457  }
1458  print '</td>';
1459  if (!$i) {
1460  $totalarray['nbfield']++;
1461  }
1462  if (!$i) {
1463  $totalarray['pos'][$totalarray['nbfield']] = 't.budget_amount';
1464  }
1465  $totalarray['val']['t.budget_amount'] += $obj->budget_amount;
1466  if (!$i) {
1467  $totalarray['totalbudget_amountfield'] = $totalarray['nbfield'];
1468  }
1469  $totalarray['totalbudgetamount'] += $obj->budget_amount;
1470  }
1471  // Time not billed
1472  if (!empty($arrayfields['t.tobill']['checked'])) {
1473  print '<td class="center">';
1474  if ($obj->usage_bill_time) {
1475  print convertSecondToTime($obj->tobill, 'allhourmin');
1476  $totalarray['val']['t.tobill'] += $obj->tobill;
1477  $totalarray['totaltobill'] += $obj->tobill;
1478  } else {
1479  print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1480  }
1481  print '</td>';
1482  if (!$i) {
1483  $totalarray['nbfield']++;
1484  }
1485  if (!$i) {
1486  $totalarray['pos'][$totalarray['nbfield']] = 't.tobill';
1487  }
1488  if (!$i) {
1489  $totalarray['totaltobillfield'] = $totalarray['nbfield'];
1490  }
1491  }
1492  // Time billed
1493  if (!empty($arrayfields['t.billed']['checked'])) {
1494  print '<td class="center">';
1495  if ($obj->usage_bill_time) {
1496  print convertSecondToTime($obj->billed, 'allhourmin');
1497  $totalarray['val']['t.billed'] += $obj->billed;
1498  $totalarray['totalbilled'] += $obj->billed;
1499  } else {
1500  print '<span class="opacitymedium">'.$langs->trans("NA").'</span>';
1501  }
1502  print '</td>';
1503  if (!$i) {
1504  $totalarray['nbfield']++;
1505  }
1506  if (!$i) {
1507  $totalarray['pos'][$totalarray['nbfield']] = 't.billed';
1508  }
1509  if (!$i) {
1510  $totalarray['totalbilledfield'] = $totalarray['nbfield'];
1511  }
1512  }
1513  // Extra fields
1514  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1515  // Fields from hook
1516  $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
1517  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1518  print $hookmanager->resPrint;
1519  // Date creation
1520  if (!empty($arrayfields['t.datec']['checked'])) {
1521  print '<td class="center">';
1522  print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
1523  print '</td>';
1524  if (!$i) {
1525  $totalarray['nbfield']++;
1526  }
1527  }
1528  // Date modification
1529  if (!empty($arrayfields['t.tms']['checked'])) {
1530  print '<td class="center">';
1531  print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser');
1532  print '</td>';
1533  if (!$i) {
1534  $totalarray['nbfield']++;
1535  }
1536  }
1537  // Status
1538  /*if (!empty($arrayfields['p.fk_statut']['checked']))
1539  {
1540  $projectstatic->statut = $obj->fk_statut;
1541  print '<td class="right">'.$projectstatic->getLibStatut(5).'</td>';
1542  }*/
1543  // Action column
1544  if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1545  print '<td class="nowrap center">';
1546  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1547  $selected = 0;
1548  if (in_array($object->id, $arrayofselected)) {
1549  $selected = 1;
1550  }
1551  print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
1552  }
1553  print '</td>';
1554  if (!$i) {
1555  $totalarray['nbfield']++;
1556  }
1557  }
1558 
1559  print '</tr>'."\n";
1560  }
1561  }
1562 
1563  $i++;
1564 }
1565 
1566 // Show total line
1567 if (!empty($totalarray['totalizable']) && is_array($totalarray['totalizable'])) {
1568  foreach ($totalarray['totalizable'] as $keytotalizable => $valtotalizable) {
1569  $totalarray['pos'][$valtotalizable['pos']] = $keytotalizable;
1570  $totalarray['val'][$keytotalizable] = $valtotalizable['total'];
1571  }
1572 }
1573 
1574 if (isset($totalarray['totaldurationeffectivefield']) || isset($totalarray['totalplannedworkloadfield']) || isset($totalarray['totalprogress_calculatedfield'])
1575  || isset($totalarray['totaltobill']) || isset($totalarray['totalbilled']) || isset($totalarray['totalbudget'])) {
1576  print '<tr class="liste_total">';
1577  $i = 0;
1578  while ($i < $totalarray['nbfield']) {
1579  $i++;
1580  if ($i == 1) {
1581  if ($num < $limit && empty($offset)) {
1582  print '<td class="left">'.$langs->trans("Total").'</td>';
1583  } else {
1584  print '<td class="left">'.$langs->trans("Totalforthispage").'</td>';
1585  }
1586  } elseif (isset($totalarray['totalplannedworkloadfield']) && $totalarray['totalplannedworkloadfield'] == $i) {
1587  print '<td class="center">'.convertSecondToTime($totalarray['totalplannedworkload'], $plannedworkloadoutputformat).'</td>';
1588  } elseif (isset($totalarray['totaldurationeffectivefield']) && $totalarray['totaldurationeffectivefield'] == $i) {
1589  print '<td class="center">'.convertSecondToTime($totalarray['totaldurationeffective'], $timespentoutputformat).'</td>';
1590  } elseif (isset($totalarray['totalprogress_calculatedfield']) && $totalarray['totalprogress_calculatedfield'] == $i) {
1591  print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationeffective'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1592  } elseif (isset($totalarray['totalprogress_declaredfield']) && $totalarray['totalprogress_declaredfield'] == $i) {
1593  print '<td class="center">'.($totalarray['totalplannedworkload'] > 0 ? round(100 * $totalarray['totaldurationdeclared'] / $totalarray['totalplannedworkload'], 2).' %' : '').'</td>';
1594  } elseif (isset($totalarray['totaltobillfield']) && $totalarray['totaltobillfield'] == $i) {
1595  print '<td class="center">'.convertSecondToTime($totalarray['totaltobill'], $plannedworkloadoutputformat).'</td>';
1596  } elseif (isset($totalarray['totalbilledfield']) && $totalarray['totalbilledfield'] == $i) {
1597  print '<td class="center">'.convertSecondToTime($totalarray['totalbilled'], $plannedworkloadoutputformat).'</td>';
1598  } elseif (isset($totalarray['totalbudget_amountfield']) && $totalarray['totalbudget_amountfield'] == $i) {
1599  print '<td class="center">'.price($totalarray['totalbudgetamount'], 0, $langs, 1, 0, 0, $conf->currency).'</td>';
1600  } elseif (!empty($totalarray['pos'][$i])) {
1601  print '<td class="right">';
1602  if (isset($totalarray['type']) && $totalarray['type'][$i] == 'duration') {
1603  print (!empty($totalarray['val'][$totalarray['pos'][$i]])?convertSecondToTime($totalarray['val'][$totalarray['pos'][$i]], 'allhourmin'):0);
1604  } else {
1605  print price(!empty($totalarray['val'][$totalarray['pos'][$i]])?$totalarray['val'][$totalarray['pos'][$i]]:0);
1606  }
1607  print '</td>';
1608  } else {
1609  print '<td></td>';
1610  }
1611  }
1612  print '</tr>';
1613 }
1614 
1615 $db->free($resql);
1616 
1617 $parameters = array('arrayfields'=>$arrayfields, 'sql' => $sql);
1618 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1619 print $hookmanager->resPrint;
1620 
1621 print '</table>'."\n";
1622 print '</div>'."\n";
1623 
1624 print '</form>'."\n";
1625 
1626 // End of page
1627 llxFooter();
1628 $db->close();
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to manage standard extra fields.
Class to manage generation of HTML components Only common components must be here.
static multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $morecss='', $translate=0, $width=0, $moreattrib='', $elemtype='', $placeholder='', $addjscombo=-1)
Show a multiselect form from an array.
Classe permettant la generation de composants html autre Only common components are here.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Definition: task.class.php:40
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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:239
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dolGetFirstLineOfText($text, $nboflines=1, $charset='UTF-8')
Return first line of text.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
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...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
getTaskProgressView($task, $label=true, $progressNumber=true, $hideOnProgressNull=false, $spaced=false)
getTaskProgressBadge($task, $label='', $tooltip='')
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.