1<?php
2/* Copyright (C) 2002-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2017 Laurent Destailleur  <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2017 Regis Houssin        <regis.houssin@inodbox.com>
5 * Copyright (C) 2015      Alexandre Spangaro   <aspangaro@open-dsi.fr>
6 * Copyright (C) 2016      Marcos García        <marcosgdf@gmail.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22/**
23 *      \file       htdocs/user/list.php
24 * 		\ingroup	core
25 *      \brief      Page of users
26 */
27
28require '../main.inc.php';
29require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
30if (!empty($conf->categorie->enabled)) {
31	require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
32}
33
34if (!$user->rights->user->user->lire && !$user->admin) {
35	accessforbidden();
36}
37
38// Load translation files required by page
39$langs->loadLangs(array('users', 'companies', 'hrm', 'salaries'));
40
41$action     = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
42$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
43$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ?
44$confirm    = GETPOST('confirm', 'alpha'); // Result of a confirmation
45$cancel     = GETPOST('cancel', 'alpha'); // We click on a Cancel button
46$toselect   = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
47$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'userlist'; // To manage different context of search
48$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
49$optioncss  = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
50
51// Security check (for external users)
52$socid = 0;
53if ($user->socid > 0) {
54	$socid = $user->socid;
55}
56
57// Load mode employee
58$mode = GETPOST("mode", 'alpha');
59
60// Load variable for pagination
61$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
62$sortfield = GETPOST('sortfield', 'aZ09comma');
63$sortorder = GETPOST('sortorder', 'aZ09comma');
64$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
65if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { $page = 0; }     // If $page is not defined, or '' or -1 or if we click on clear filters
66$offset = $limit * $page;
67$pageprev = $page - 1;
68$pagenext = $page + 1;
69
70// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
71$object = new User($db);
72$extrafields = new ExtraFields($db);
73$diroutputmassaction = $conf->mymodule->dir_output.'/temp/massgeneration/'.$user->id;
74$hookmanager->initHooks(array('userlist'));
75
76// Fetch optionals attributes and labels
77$extrafields->fetch_name_optionals_label($object->table_element);
78
79$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
80
81if (!$sortfield) $sortfield = "u.login";
82if (!$sortorder) $sortorder = "ASC";
83
84// Initialize array of search criterias
85$search_all = GETPOST('search_all', 'alphanohtml') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml');
86$search = array();
87foreach ($object->fields as $key => $val)
88{
89	if (GETPOST('search_'.$key, 'alpha') !== '') $search[$key] = GETPOST('search_'.$key, 'alpha');
90}
91
92$userstatic = new User($db);
93$companystatic = new Societe($db);
94$form = new Form($db);
95
96// List of fields to search into when doing a "search in all"
97$fieldstosearchall = array(
98	'u.login'=>"Login",
99	'u.lastname'=>"Lastname",
100	'u.firstname'=>"Firstname",
101	'u.accountancy_code'=>"AccountancyCode",
102	'u.email'=>"EMail",
103	'u.note'=>"Note",
104);
105if (!empty($conf->api->enabled))
106{
107	$fieldstosearchall['u.api_key'] = "ApiKey";
108}
109
110// Definition of fields for list
111$arrayfields = array(
112	'u.login'=>array('label'=>"Login", 'checked'=>1, 'position'=>10),
113    'u.lastname'=>array('label'=>"Lastname", 'checked'=>1, 'position'=>15),
114    'u.firstname'=>array('label'=>"Firstname", 'checked'=>1, 'position'=>20),
115    'u.entity'=>array('label'=>"Entity", 'checked'=>1, 'position'=>50, 'enabled'=>(!empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))),
116    'u.gender'=>array('label'=>"Gender", 'checked'=>0, 'position'=>22),
117    'u.employee'=>array('label'=>"Employee", 'checked'=>($mode == 'employee' ? 1 : 0), 'position'=>25),
118    'u.fk_user'=>array('label'=>"HierarchicalResponsible", 'checked'=>1, 'position'=>27),
119    'u.accountancy_code'=>array('label'=>"AccountancyCode", 'checked'=>0, 'position'=>30),
120    'u.email'=>array('label'=>"EMail", 'checked'=>1, 'position'=>35),
121    'u.api_key'=>array('label'=>"ApiKey", 'checked'=>0, 'position'=>40, "enabled"=>($conf->api->enabled && $user->admin)),
122    'u.fk_soc'=>array('label'=>"Company", 'checked'=>($contextpage == 'employeelist' ? 0 : 1), 'position'=>45),
123    'u.salary'=>array('label'=>"Salary", 'checked'=>1, 'position'=>80, 'enabled'=>($conf->salaries->enabled && !empty($user->rights->salaries->readall))),
124    'u.datelastlogin'=>array('label'=>"LastConnexion", 'checked'=>1, 'position'=>100),
125	'u.datepreviouslogin'=>array('label'=>"PreviousConnexion", 'checked'=>0, 'position'=>110),
126	'u.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500),
127	'u.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500),
128	'u.statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000),
129);
130// Extra fields
131include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_array_fields.tpl.php';
132
133$object->fields = dol_sort_array($object->fields, 'position');
134$arrayfields = dol_sort_array($arrayfields, 'position');
135
136// Init search fields
137$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
138$search_user = GETPOST('search_user', 'alpha');
139$search_login = GETPOST('search_login', 'alpha');
140$search_lastname = GETPOST('search_lastname', 'alpha');
141$search_firstname = GETPOST('search_firstname', 'alpha');
142$search_gender = GETPOST('search_gender', 'alpha');
143$search_employee = GETPOST('search_employee', 'alpha');
144$search_accountancy_code = GETPOST('search_accountancy_code', 'alpha');
145$search_email = GETPOST('search_email', 'alpha');
146$search_api_key = GETPOST('search_api_key', 'alphanohtml');
147$search_statut = GETPOST('search_statut', 'intcomma');
148$search_thirdparty = GETPOST('search_thirdparty', 'alpha');
149$search_supervisor = GETPOST('search_supervisor', 'intcomma');
150$optioncss = GETPOST('optioncss', 'alpha');
151$search_categ = GETPOST("search_categ", 'int');
152$catid = GETPOST('catid', 'int');
153
154// Default search
155if ($search_statut == '') $search_statut = '1';
156if ($mode == 'employee' && !GETPOSTISSET('search_employee')) $search_employee = 1;
157
158// Define value to know what current user can do on users
159$permissiontoadd = (!empty($user->admin) || $user->rights->user->user->creer);
160$canreaduser = (!empty($user->admin) || $user->rights->user->user->lire);
161$canedituser = (!empty($user->admin) || $user->rights->user->user->creer);
162$candisableuser = (!empty($user->admin) || $user->rights->user->user->supprimer);
163$canreadgroup = $canreaduser;
164$caneditgroup = $canedituser;
165if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS))
166{
167	$canreadgroup = (!empty($user->admin) || $user->rights->user->group_advance->read);
168	$caneditgroup = (!empty($user->admin) || $user->rights->user->group_advance->write);
169}
170
171$error = 0;
172
173$childids = $user->getAllChildIds(1);
174
175
176/*
177 * Actions
178 */
179
180if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; }
181if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'confirm_createbills') { $massaction = ''; }
182
183$parameters = array();
184$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
185if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
186
187if (empty($reshook))
188{
189	// Selection of new fields
190	include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
191
192	// Purge search criteria
193	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
194	{
195		$search_user = "";
196		$search_login = "";
197		$search_lastname = "";
198		$search_firstname = "";
199		$search_gender = "";
200		$search_employee = "";
201		$search_accountancy_code = "";
202		$search_email = "";
203		$search_statut = "";
204		$search_thirdparty = "";
205		$search_supervisor = "";
206		$search_api_key = "";
207		$search_datelastlogin = "";
208		$search_datepreviouslogin = "";
209		$search_date_creation = "";
210		$search_date_update = "";
211		$search_array_options = array();
212		$search_categ = 0;
213	}
214
215	// Mass actions
216	$objectclass = 'User';
217	$objectlabel = 'User';
218	$uploaddir = $conf->user->dir_output;
219	include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
220
221	// Disable or Enable records
222	if (!$error && ($massaction == 'disable' || $massaction == 'reactivate') && $permissiontoadd)
223	{
224		$objecttmp = new User($db);
225
226		if (!$error)
227		{
228			$db->begin();
229
230			$nbok = 0;
231			foreach ($toselect as $toselectid)
232			{
233				if ($toselectid == $user->id) {
234					setEventMessages($langs->trans($massaction == 0 ? 'CantDisableYourself' : 'CanEnableYourself'), null, 'errors');
235					$error++;
236					break;
237				}
238
239				$result = $objecttmp->fetch($toselectid);
240				if ($result > 0) {
241					if ($objecttmp->admin) {
242						setEventMessages($langs->trans($massaction == 0 ? 'CantDisableAnAdminUserWithMassActions' : 'CantEnableAnAdminUserWithMassActions', $objecttmp->login), null, 'errors');
243						$error++;
244						break;
245					}
246
247					$result = $objecttmp->setstatus($massaction == 'disable' ? 0 : 1);
248					if ($result == 0) {
249						// Nothing is done
250					} elseif ($result < 0) {
251						setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
252						$error++;
253						break;
254					} else $nbok++;
255				} else {
256					setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
257					$error++;
258					break;
259				}
260			}
261
262			if (!$error && !empty($conf->file->main_limit_users)) {
263				$nb = $object->getNbOfUsers("active");
264				if ($nb >= $conf->file->main_limit_users) {
265					$error++;
266					setEventMessages($langs->trans("YourQuotaOfUsersIsReached"), null, 'errors');
267				}
268			}
269
270			if (!$error)
271			{
272				if ($nbok > 1) setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
273				else setEventMessages($langs->trans("RecordsModified", $nbok), null, 'mesgs');
274				$db->commit();
275			} else {
276				$db->rollback();
277			}
278		}
279	}
280}
281
282
283/*
284 * View
285 */
286
287$formother = new FormOther($db);
288
289//$help_url="EN:Module_MyObject|FR:Module_MyObject_FR|ES:Módulo_MyObject";
290$help_url = '';
291if ($contextpage == 'employeelist' && $search_employee == 1) {
292	$text = $langs->trans("ListOfEmployees");
293} else {
294	$text = $langs->trans("ListOfUsers");
295}
296
297$user2 = new User($db);
298
299$sql = "SELECT DISTINCT u.rowid, u.lastname, u.firstname, u.admin, u.fk_soc, u.login, u.email, u.api_key, u.accountancy_code, u.gender, u.employee, u.photo,";
300$sql .= " u.salary, u.datelastlogin, u.datepreviouslogin,";
301$sql .= " u.ldap_sid, u.statut, u.entity,";
302$sql .= " u.tms as date_update, u.datec as date_creation,";
303$sql .= " u2.rowid as id2, u2.login as login2, u2.firstname as firstname2, u2.lastname as lastname2, u2.admin as admin2, u2.fk_soc as fk_soc2, u2.email as email2, u2.gender as gender2, u2.photo as photo2, u2.entity as entity2, u2.statut as statut2,";
304$sql .= " s.nom as name, s.canvas, ";
305// Add fields from extrafields
306if (!empty($extrafields->attributes[$object->table_element]['label'])) {
307	foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
308		$sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.' as options_'.$key.', ' : '');
309	}
310}
311// Add fields from hooks
312$parameters = array();
313$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
314$sql .= preg_replace('/^,/', '', $hookmanager->resPrint);
315$sql = preg_replace('/,\s*$/', '', $sql);
316$sql .= " FROM ".MAIN_DB_PREFIX."user as u";
317if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
318	$sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (u.rowid = ef.fk_object)";
319}
320$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON u.fk_soc = s.rowid";
321$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u2 ON u.fk_user = u2.rowid";
322if (!empty($search_categ) || !empty($catid)) $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_user as cu ON u.rowid = cu.fk_user"; // We'll need this table joined to the select in order to filter by categ
323// Add fields from hooks
324$parameters = array();
325$reshook = $hookmanager->executeHooks('printUserListWhere', $parameters); // Note that $action and $object may have been modified by hook
326if ($reshook > 0) {
327	$sql .= $hookmanager->resPrint;
328} else {
329	$sql .= " WHERE u.entity IN (".getEntity('user').")";
330}
331if ($socid > 0) $sql .= " AND u.fk_soc = ".$socid;
332//if ($search_user != '')       $sql.=natural_search(array('u.login', 'u.lastname', 'u.firstname'), $search_user);
333if ($search_supervisor > 0)   $sql .= " AND u.fk_user IN (".$db->sanitize($db->escape($search_supervisor)).")";
334if ($search_thirdparty != '') $sql .= natural_search(array('s.nom'), $search_thirdparty);
335if ($search_login != '')      $sql .= natural_search("u.login", $search_login);
336if ($search_lastname != '')   $sql .= natural_search("u.lastname", $search_lastname);
337if ($search_firstname != '')  $sql .= natural_search("u.firstname", $search_firstname);
338if ($search_gender != '' && $search_gender != '-1')     $sql .= " AND u.gender = '".$db->escape($search_gender)."'"; // Cannot use natural_search as looking for %man% also includes woman
339if (is_numeric($search_employee) && $search_employee >= 0) {
340	$sql .= ' AND u.employee = '.(int) $search_employee;
341}
342if ($search_accountancy_code != '')  $sql .= natural_search("u.accountancy_code", $search_accountancy_code);
343if ($search_email != '')             $sql .= natural_search("u.email", $search_email);
344if ($search_api_key != '')           $sql .= natural_search("u.api_key", $search_api_key);
345if ($search_statut != '' && $search_statut >= 0) $sql .= " AND u.statut IN (".$db->sanitize($db->escape($search_statut)).")";
346if ($sall)                           $sql .= natural_search(array_keys($fieldstosearchall), $sall);
347if ($catid > 0)     $sql .= " AND cu.fk_categorie = ".((int) $catid);
348if ($catid == -2)   $sql .= " AND cu.fk_categorie IS NULL";
349if ($search_categ > 0)   $sql .= " AND cu.fk_categorie = ".$db->escape($search_categ);
350if ($search_categ == -2) $sql .= " AND cu.fk_categorie IS NULL";
351if ($mode == 'employee' && empty($user->rights->salaries->readall)) $sql .= " AND u.fk_user IN (".join(',', $childids).")";
352// Add where from extra fields
353include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
354// Add where from hooks
355$parameters = array();
356$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook
357$sql .= $hookmanager->resPrint;
358$sql .= $db->order($sortfield, $sortorder);
359
360// Count total nb of records
361$nbtotalofrecords = '';
362if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
363{
364	$resql = $db->query($sql);
365	$nbtotalofrecords = $db->num_rows($resql);
366	if (($page * $limit) > $nbtotalofrecords)	// if total of record found is smaller than page * limit, goto and load page 0
367	{
368		$page = 0;
369		$offset = 0;
370	}
371}
372// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set.
373if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit)))
374{
375	$num = $nbtotalofrecords;
376} else {
377	if ($limit) $sql .= $db->plimit($limit + 1, $offset);
378
379	$resql = $db->query($sql);
380	if (!$resql)
381	{
382		dol_print_error($db);
383		exit;
384	}
385
386	$num = $db->num_rows($resql);
387}
388
389// Direct jump if only one record found
390if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page)
391{
392	$obj = $db->fetch_object($resql);
393	$id = $obj->rowid;
394	header("Location: ".DOL_URL_ROOT.'/user/card.php?id='.$id);
395	exit;
396}
397
398// Output page
399// --------------------------------------------------------------------
400
401llxHeader('', $langs->trans("ListOfUsers"), $help_url);
402
403$param = '';
404if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&amp;contextpage='.urlencode($contextpage);
405if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&amp;limit='.urlencode($limit);
406if ($sall != '') $param .= '&amp;sall='.urlencode($sall);
407if ($search_user != '') $param .= "&amp;search_user=".urlencode($search_user);
408if ($search_login != '') $param .= "&amp;search_login=".urlencode($search_login);
409if ($search_lastname != '') $param .= "&amp;search_lastname=".urlencode($search_lastname);
410if ($search_firstname != '') $param .= "&amp;search_firstname=".urlencode($search_firstname);
411if ($search_gender != '') $param .= "&amp;search_gender=".urlencode($search_gender);
412if ($search_employee != '') $param .= "&amp;search_employee=".urlencode($search_employee);
413if ($search_accountancy_code != '') $param .= "&amp;search_accountancy_code=".urlencode($search_accountancy_code);
414if ($search_email != '') $param .= "&amp;search_email=".urlencode($search_email);
415if ($search_api_key != '') $param .= "&amp;search_api_key=".urlencode($search_api_key);
416if ($search_supervisor > 0) $param .= "&amp;search_supervisor=".urlencode($search_supervisor);
417if ($search_statut != '') $param .= "&amp;search_statut=".urlencode($search_statut);
418if ($optioncss != '') $param .= '&amp;optioncss='.urlencode($optioncss);
419if ($mode != '')      $param .= '&amp;mode='.urlencode($mode);
420if ($search_categ > 0) $param .= "&amp;search_categ=".urlencode($search_categ);
421// Add $param from extra fields
422include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
423
424// List of mass actions available
425$arrayofmassactions = array();
426if ($permissiontoadd) $arrayofmassactions['disable'] = $langs->trans("DisableUser");
427if ($permissiontoadd) $arrayofmassactions['reactivate'] = $langs->trans("Reactivate");
428//if ($permissiontodelete) $arrayofmassactions['predelete'] = '<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
429
430if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) $arrayofmassactions = array();
431$massactionbutton = $form->selectMassAction('', $arrayofmassactions);
432
433print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
434if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
435print '<input type="hidden" name="token" value="'.newToken().'">';
436print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
437print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
438print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
439print '<input type="hidden" name="mode" value="'.$mode.'">';
440print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
441
442$url = DOL_URL_ROOT.'/user/card.php?action=create'.($mode == 'employee' ? '&employee=1' : '').'&leftmenu=';
443if (!empty($socid)) $url .= '&socid='.$socid;
444
445$newcardbutton = dolGetButtonTitle($langs->trans('NewUser'), '', 'fa fa-plus-circle', $url, '', $permissiontoadd);
446
447$moreparam = array('morecss'=>'btnTitleSelected');
448$morehtmlright .= dolGetButtonTitle($langs->trans("List"), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/user/list.php'.(($search_statut != '' && $search_statut >= 0) ? '?search_statut='.$search_statut : ''), '', 1, $moreparam);
449$moreparam = array('morecss'=>'marginleftonly');
450$morehtmlright .= dolGetButtonTitle($langs->trans("HierarchicView"), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/user/hierarchy.php'.(($search_statut != '' && $search_statut >= 0) ? '?search_statut='.$search_statut : ''), '', 1, $moreparam);
451
452print_barre_liste($text, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'user', 0, $morehtmlright.' '.$newcardbutton, '', $limit, 0, 0, 1);
453
454// Add code for pre mass action (confirmation or email presend form)
455$topicmail = "SendUserRef";
456$modelmail = "user";
457$objecttmp = new User($db);
458$trackid = 'use'.$object->id;
459include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
460
461if (!empty($catid))
462{
463	print "<div id='ways'>";
464	$c = new Categorie($db);
465	$ways = $c->print_all_ways(' &gt; ', 'user/list.php');
466	print " &gt; ".$ways[0]."<br>\n";
467	print "</div><br>";
468}
469
470if ($search_all)
471{
472	foreach ($fieldstosearchall as $key => $val) $fieldstosearchall[$key] = $langs->trans($val);
473	print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'</div>';
474}
475
476$moreforfilter = '';
477/*$moreforfilter.='<div class="divsearchfield">';
478 $moreforfilter.= $langs->trans('MyFilter') . ': <input type="text" name="search_myfield" value="'.dol_escape_htmltag($search_myfield).'">';
479 $moreforfilter.= '</div>';*/
480
481// Filter on categories
482if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire)
483{
484	$moreforfilter .= '<div class="divsearchfield">';
485	$moreforfilter .= $langs->trans('Categories').': ';
486	$moreforfilter .= $formother->select_categories(Categorie::TYPE_USER, $search_categ, 'search_categ', 1);
487	$moreforfilter .= '</div>';
488}
489
490$parameters = array();
491$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
492if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint;
493else $moreforfilter = $hookmanager->resPrint;
494
495if (!empty($moreforfilter))
496{
497	print '<div class="liste_titre liste_titre_bydiv centpercent">';
498	print $moreforfilter;
499	print '</div>';
500}
501
502$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
503$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
504$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
505
506print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
507print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
508
509// Fields title search
510// --------------------------------------------------------------------
511print '<tr class="liste_titre_filter">';
512if (!empty($arrayfields['u.login']['checked']))
513{
514	print '<td class="liste_titre"><input type="text" name="search_login" class="maxwidth50" value="'.$search_login.'"></td>';
515}
516if (!empty($arrayfields['u.lastname']['checked']))
517{
518	print '<td class="liste_titre"><input type="text" name="search_lastname" class="maxwidth50" value="'.$search_lastname.'"></td>';
519}
520if (!empty($arrayfields['u.firstname']['checked']))
521{
522	print '<td class="liste_titre"><input type="text" name="search_firstname" class="maxwidth50" value="'.$search_firstname.'"></td>';
523}
524if (!empty($arrayfields['u.gender']['checked']))
525{
526	print '<td class="liste_titre">';
527	$arraygender = array('man'=>$langs->trans("Genderman"), 'woman'=>$langs->trans("Genderwoman"), 'other'=>$langs->trans("Genderother"));
528	print $form->selectarray('search_gender', $arraygender, $search_gender, 1);
529	print '</td>';
530}
531if (!empty($arrayfields['u.employee']['checked']))
532{
533	print '<td class="liste_titre">';
534	print $form->selectyesno('search_employee', $search_employee, 1, false, 1);
535	print '</td>';
536}
537// Supervisor
538if (!empty($arrayfields['u.fk_user']['checked']))
539{
540    print '<td class="liste_titre">';
541    print $form->select_dolusers($search_supervisor, 'search_supervisor', 1, array(), 0, '', 0, 0, 0, 0, '', 0, '', 'maxwidth200');
542    print '</td>';
543}
544if (!empty($arrayfields['u.accountancy_code']['checked']))
545{
546	print '<td class="liste_titre"><input type="text" name="search_accountancy_code" class="maxwidth50" value="'.$search_accountancy_code.'"></td>';
547}
548if (!empty($arrayfields['u.email']['checked']))
549{
550	print '<td class="liste_titre"><input type="text" name="search_email" class="maxwidth75" value="'.$search_email.'"></td>';
551}
552if (!empty($arrayfields['u.api_key']['checked']))
553{
554	print '<td class="liste_titre"><input type="text" name="search_api_key" class="maxwidth50" value="'.$search_api_key.'"></td>';
555}
556if (!empty($arrayfields['u.fk_soc']['checked']))
557{
558	print '<td class="liste_titre"><input type="text" name="search_thirdparty" class="maxwidth75" value="'.$search_thirdparty.'"></td>';
559}
560if (!empty($arrayfields['u.entity']['checked']))
561{
562	print '<td class="liste_titre"></td>';
563}
564if (!empty($arrayfields['u.salary']['checked']))
565{
566    print '<td class="liste_titre"></td>';
567}
568if (!empty($arrayfields['u.datelastlogin']['checked']))
569{
570	print '<td class="liste_titre"></td>';
571}
572if (!empty($arrayfields['u.datepreviouslogin']['checked']))
573{
574	print '<td class="liste_titre"></td>';
575}
576// Extra fields
577include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
578// Fields from hook
579$parameters = array('arrayfields'=>$arrayfields);
580$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook
581print $hookmanager->resPrint;
582if (!empty($arrayfields['u.datec']['checked']))
583{
584	// Date creation
585	print '<td class="liste_titre">';
586	print '</td>';
587}
588if (!empty($arrayfields['u.tms']['checked']))
589{
590	// Date modification
591	print '<td class="liste_titre">';
592	print '</td>';
593}
594if (!empty($arrayfields['u.statut']['checked']))
595{
596	// Status
597	print '<td class="liste_titre center">';
598	print $form->selectarray('search_statut', array('-1'=>'', '0'=>$langs->trans('Disabled'), '1'=>$langs->trans('Enabled')), $search_statut);
599	print '</td>';
600}
601// Action column
602print '<td class="liste_titre maxwidthsearch">';
603$searchpicto = $form->showFilterButtons();
604print $searchpicto;
605print '</td>';
606print '</tr>'."\n";
607
608
609print '<tr class="liste_titre">';
610if (!empty($arrayfields['u.login']['checked']))          print_liste_field_titre("Login", $_SERVER['PHP_SELF'], "u.login", $param, "", "", $sortfield, $sortorder);
611if (!empty($arrayfields['u.lastname']['checked']))       print_liste_field_titre("Lastname", $_SERVER['PHP_SELF'], "u.lastname", $param, "", "", $sortfield, $sortorder);
612if (!empty($arrayfields['u.firstname']['checked']))      print_liste_field_titre("FirstName", $_SERVER['PHP_SELF'], "u.firstname", $param, "", "", $sortfield, $sortorder);
613if (!empty($arrayfields['u.gender']['checked']))         print_liste_field_titre("Gender", $_SERVER['PHP_SELF'], "u.gender", $param, "", "", $sortfield, $sortorder);
614if (!empty($arrayfields['u.employee']['checked']))       print_liste_field_titre("Employee", $_SERVER['PHP_SELF'], "u.employee", $param, "", "", $sortfield, $sortorder);
615if (!empty($arrayfields['u.fk_user']['checked']))        print_liste_field_titre("HierarchicalResponsible", $_SERVER['PHP_SELF'], "u.fk_user", $param, "", "", $sortfield, $sortorder);
616if (!empty($arrayfields['u.accountancy_code']['checked'])) print_liste_field_titre("AccountancyCode", $_SERVER['PHP_SELF'], "u.accountancy_code", $param, "", "", $sortfield, $sortorder);
617if (!empty($arrayfields['u.email']['checked']))          print_liste_field_titre("EMail", $_SERVER['PHP_SELF'], "u.email", $param, "", "", $sortfield, $sortorder);
618if (!empty($arrayfields['u.api_key']['checked']))        print_liste_field_titre("ApiKey", $_SERVER['PHP_SELF'], "u.api_key", $param, "", "", $sortfield, $sortorder);
619if (!empty($arrayfields['u.fk_soc']['checked']))         print_liste_field_titre("Company", $_SERVER['PHP_SELF'], "u.fk_soc", $param, "", "", $sortfield, $sortorder);
620if (!empty($arrayfields['u.entity']['checked']))         print_liste_field_titre("Entity", $_SERVER['PHP_SELF'], "u.entity", $param, "", "", $sortfield, $sortorder);
621if (!empty($arrayfields['u.salary']['checked']))         print_liste_field_titre("Salary", $_SERVER['PHP_SELF'], "u.salary", $param, "", "", $sortfield, $sortorder, 'right ');
622if (!empty($arrayfields['u.datelastlogin']['checked']))  print_liste_field_titre("LastConnexion", $_SERVER['PHP_SELF'], "u.datelastlogin", $param, "", '', $sortfield, $sortorder, 'center ');
623if (!empty($arrayfields['u.datepreviouslogin']['checked'])) print_liste_field_titre("PreviousConnexion", $_SERVER['PHP_SELF'], "u.datepreviouslogin", $param, "", '', $sortfield, $sortorder, 'center ');
624// Extra fields
625include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
626// Hook fields
627$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
628$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
629print $hookmanager->resPrint;
630if (!empty($arrayfields['u.datec']['checked']))  print_liste_field_titre("DateCreationShort", $_SERVER["PHP_SELF"], "u.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
631if (!empty($arrayfields['u.tms']['checked']))    print_liste_field_titre("DateModificationShort", $_SERVER["PHP_SELF"], "u.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
632if (!empty($arrayfields['u.statut']['checked'])) print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "u.statut", "", $param, '', $sortfield, $sortorder, 'center ');
633// Action column
634print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
635print '</tr>'."\n";
636
637
638// Detect if we need a fetch on each output line
639$needToFetchEachLine = 0;
640if (is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0)
641{
642	foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val)
643	{
644		if (preg_match('/\$object/', $val)) $needToFetchEachLine++; // There is at least one compute field that use $object
645	}
646}
647
648
649// Loop on record
650// --------------------------------------------------------------------
651$i = 0;
652$totalarray = array();
653$arrayofselected = array();
654while ($i < ($limit ? min($num, $limit) : $num))
655{
656	$obj = $db->fetch_object($resql);
657	if (empty($obj)) break; // Should not happen
658
659	// Store properties in $object
660	$object->setVarsFromFetchObj($obj);
661
662	$userstatic->id = $obj->rowid;
663	$userstatic->admin = $obj->admin;
664	$userstatic->ref = $obj->label;
665	$userstatic->login = $obj->login;
666	$userstatic->statut = $obj->statut;
667	$userstatic->email = $obj->email;
668	$userstatic->gender = $obj->gender;
669	$userstatic->socid = $obj->fk_soc;
670	$userstatic->firstname = $obj->firstname;
671	$userstatic->lastname = $obj->lastname;
672	$userstatic->employee = $obj->employee;
673	$userstatic->photo = $obj->photo;
674
675	$li = $userstatic->getNomUrl(-1, '', 0, 0, 24, 1, 'login', '', 1);
676
677	print '<tr class="oddeven">';
678	if (!empty($arrayfields['u.login']['checked']))
679	{
680		print '<td class="nowraponall">';
681		print $li;
682		if (!empty($conf->multicompany->enabled) && $obj->admin && !$obj->entity)
683		{
684		  	print img_picto($langs->trans("SuperAdministrator"), 'redstar', 'class="valignmiddle paddingleft"');
685		} elseif ($obj->admin)
686		{
687			print img_picto($langs->trans("Administrator"), 'star', 'class="valignmiddle paddingleft"');
688		}
689		print '</td>';
690		if (!$i) $totalarray['nbfield']++;
691	}
692	if (!empty($arrayfields['u.lastname']['checked']))
693	{
694		  print '<td class="tdoverflowmax150">'.$obj->lastname.'</td>';
695		if (!$i) $totalarray['nbfield']++;
696	}
697	if (!empty($arrayfields['u.firstname']['checked']))
698	{
699		print '<td class="tdoverflowmax150">'.$obj->firstname.'</td>';
700		if (!$i) $totalarray['nbfield']++;
701	}
702	if (!empty($arrayfields['u.gender']['checked']))
703	{
704		print '<td>';
705		if ($obj->gender) print $langs->trans("Gender".$obj->gender);
706		print '</td>';
707		if (!$i) $totalarray['nbfield']++;
708	}
709	if (!empty($arrayfields['u.employee']['checked']))
710	{
711		print '<td>'.yn($obj->employee).'</td>';
712		if (!$i) $totalarray['nbfield']++;
713	}
714
715	// Supervisor
716	if (!empty($arrayfields['u.fk_user']['checked']))
717	{
718	    // Resp
719	    print '<td class="nowrap">';
720	    if ($obj->login2)
721	    {
722	        $user2->id = $obj->id2;
723	        $user2->login = $obj->login2;
724	        $user2->lastname = $obj->lastname2;
725	        $user2->firstname = $obj->firstname2;
726	        $user2->gender = $obj->gender2;
727	        $user2->photo = $obj->photo2;
728	        $user2->admin = $obj->admin2;
729	        $user2->email = $obj->email2;
730	        $user2->socid = $obj->fk_soc2;
731	        $user2->statut = $obj->statut2;
732	        print $user2->getNomUrl(-1, '', 0, 0, 24, 0, '', '', 1);
733	        if (!empty($conf->multicompany->enabled) && $obj->admin2 && !$obj->entity2)
734	        {
735	            print img_picto($langs->trans("SuperAdministrator"), 'redstar', 'class="valignmiddle paddingleft"');
736	        } elseif ($obj->admin2)
737	        {
738	            print img_picto($langs->trans("Administrator"), 'star', 'class="valignmiddle paddingleft"');
739	        }
740	    }
741	    print '</td>';
742	    if (!$i) $totalarray['nbfield']++;
743	}
744
745	if (!empty($arrayfields['u.accountancy_code']['checked']))
746	{
747		print '<td>'.$obj->accountancy_code.'</td>';
748		if (!$i) $totalarray['nbfield']++;
749	}
750	if (!empty($arrayfields['u.email']['checked']))
751	{
752		print '<td>'.$obj->email.'</td>';
753		if (!$i) $totalarray['nbfield']++;
754	}
755	if (!empty($arrayfields['u.api_key']['checked']))
756	{
757		print '<td>'.$obj->api_key.'</td>';
758		if (!$i) $totalarray['nbfield']++;
759	}
760	if (!empty($arrayfields['u.fk_soc']['checked']))
761	{
762		print "<td>";
763		if ($obj->fk_soc)
764		{
765			$companystatic->id = $obj->fk_soc;
766			$companystatic->name = $obj->name;
767			$companystatic->canvas = $obj->canvas;
768			print $companystatic->getNomUrl(1);
769		} elseif ($obj->ldap_sid)
770		{
771			print $langs->trans("DomainUser");
772		} else {
773			print $langs->trans("InternalUser");
774		}
775		print '</td>';
776		if (!$i) $totalarray['nbfield']++;
777	}
778	// Multicompany enabled
779	if (!empty($conf->multicompany->enabled) && is_object($mc) && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE))
780	{
781		if (!empty($arrayfields['u.entity']['checked']))
782		{
783			print '<td>';
784			if (!$obj->entity)
785			{
786				print $langs->trans("AllEntities");
787			} else {
788				$mc->getInfo($obj->entity);
789				print $mc->label;
790			}
791			print '</td>';
792			if (!$i) $totalarray['nbfield']++;
793		}
794	}
795
796	// Salary
797	if (!empty($arrayfields['u.salary']['checked']))
798	{
799	    print '<td class="nowraponall right">'.($obj->salary ? price($obj->salary) : '').'</td>';
800	    if (!$i) $totalarray['nbfield']++;
801	}
802
803	// Date last login
804	if (!empty($arrayfields['u.datelastlogin']['checked']))
805	{
806		print '<td class="nowrap center">'.dol_print_date($db->jdate($obj->datelastlogin), "dayhour").'</td>';
807		if (!$i) $totalarray['nbfield']++;
808	}
809	// Date previous login
810	if (!empty($arrayfields['u.datepreviouslogin']['checked']))
811	{
812		print '<td class="nowrap center">'.dol_print_date($db->jdate($obj->datepreviouslogin), "dayhour").'</td>';
813		if (!$i) $totalarray['nbfield']++;
814	}
815
816	// Extra fields
817	include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
818	// Fields from hook
819	$parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
820	$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook
821	print $hookmanager->resPrint;
822	// Date creation
823	if (!empty($arrayfields['u.datec']['checked']))
824	{
825		print '<td class="center">';
826		print dol_print_date($db->jdate($obj->date_creation), 'dayhour', 'tzuser');
827		print '</td>';
828		if (!$i) $totalarray['nbfield']++;
829	}
830	// Date modification
831	if (!empty($arrayfields['u.tms']['checked']))
832	{
833		print '<td class="center">';
834		print dol_print_date($db->jdate($obj->date_update), 'dayhour', 'tzuser');
835		print '</td>';
836		if (!$i) $totalarray['nbfield']++;
837	}
838	// Status
839	if (!empty($arrayfields['u.statut']['checked']))
840	{
841		$userstatic->statut = $obj->statut;
842		print '<td class="center">'.$userstatic->getLibStatut(5).'</td>';
843		if (!$i) $totalarray['nbfield']++;
844	}
845	// Action column
846	print '<td class="nowrap center">';
847	if ($massactionbutton || $massaction)   // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
848	{
849		$selected = 0;
850		if (in_array($object->id, $arrayofselected)) $selected = 1;
851		print '<input id="cb'.$object->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$object->id.'"'.($selected ? ' checked="checked"' : '').'>';
852	}
853	print '</td>';
854	if (!$i) $totalarray['nbfield']++;
855
856	print '</tr>'."\n";
857
858	$i++;
859}
860
861// Show total line
862include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
863
864// If no record found
865if ($num == 0)
866{
867	$colspan = 1;
868	foreach ($arrayfields as $key => $val) { if (!empty($val['checked'])) $colspan++; }
869	print '<tr><td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
870}
871
872
873$db->free($resql);
874
875$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
876$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook
877print $hookmanager->resPrint;
878
879print '</table>'."\n";
880print '</div>'."\n";
881
882print '</form>'."\n";
883
884
885// End of page
886llxFooter();
887$db->close();
888