Issues (2811)

public/htdocs/user/hierarchy.php (1 issue)

Labels
Severity
1
<?php
2
3
/* Copyright (C) 2005       Matthieu Valleton           <[email protected]>
4
 * Copyright (C) 2005       Eric Seigne                 <[email protected]>
5
 * Copyright (C) 2006-2015  Laurent Destailleur         <[email protected]>
6
 * Copyright (C) 2007       Patrick Raguin              <[email protected]>
7
 * Copyright (C) 2005-2012  Regis Houssin               <[email protected]>
8
 * Copyright (C) 2019-2024  Frédéric France             <[email protected]>
9
 * Copyright (C) 2024       Rafael San José             <[email protected]>
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23
 */
24
25
use Dolibarr\Code\Core\Classes\Form;
26
use Dolibarr\Code\User\Classes\User;
27
use Dolibarr\Lib\ViewMain;
28
29
/**
30
 *      \file       htdocs/user/hierarchy.php
31
 *      \ingroup    user
32
 *      \brief      Page of hierarchy view of user module
33
 */
34
35
// Load Dolibarr environment
36
require constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
37
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/treeview.lib.php';
38
39
// Load translation files required by page
40
$langs->loadLangs(array('users', 'companies', 'hrm', 'salaries'));
41
42
// Security check (for external users)
43
$socid = 0;
44
if ($user->socid > 0) {
45
    $socid = $user->socid;
46
}
47
48
$optioncss = GETPOST('optioncss', 'alpha');
49
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'userlist'; // To manage different context of search
50
$mode = GETPOST("mode", 'alpha');
51
if (empty($mode)) {
52
    $mode = 'hierarchy';
53
}
54
55
$sortfield = GETPOST('sortfield', 'aZ09comma');
56
$sortorder = GETPOST('sortorder', 'aZ09comma');
57
$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
58
59
60
$search_status = GETPOST('search_status', 'intcomma');
61
if ($search_status == '') {
62
    $search_status = '1';
63
}
64
65
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // Both test are required to be compatible with all browsers
66
    $search_status = "";
67
}
68
69
$search_employee = -1;
70
if ($contextpage == 'employeelist') {
71
    $search_employee = 1;
72
}
73
74
$userstatic = new User($db);
75
76
// Define value to know what current user can do on users
77
$canadduser = (!empty($user->admin) || $user->hasRight("user", "user", "write"));
78
79
// Permission to list
80
if (isModEnabled('salaries') && $contextpage == 'employeelist' && $search_employee == 1) {
81
    if (!$user->hasRight("salaries", "read")) {
82
        accessforbidden();
83
    }
84
} else {
85
    if (!$user->hasRight("user", "user", "read") && empty($user->admin)) {
86
        accessforbidden();
87
    }
88
}
89
90
$childids = $user->getAllChildIds(1);
91
92
/*
93
 * View
94
 */
95
96
$form = new Form($db);
97
98
$help_url = 'EN:Module_Users|FR:Module_Utilisateurs|ES:M&oacute;dulo_Usuarios|DE:Modul_Benutzer';
99
if ($contextpage == 'employeelist' && $search_employee == 1) {
100
    $title = $langs->trans("Employees");
101
} else {
102
    $title = $langs->trans("Users");
103
}
104
$arrayofjs = array(
105
    '/includes/jquery/plugins/jquerytreeview/jquery.treeview.js',
106
    '/includes/jquery/plugins/jquerytreeview/lib/jquery.cookie.js',
107
);
108
$arrayofcss = array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.css');
109
110
ViewMain::llxHeader('', $title, $help_url, '', 0, 0, $arrayofjs, $arrayofcss, '', 'bodyforlist mod-user page-hierarchy');
111
112
$filters = [];
113
if (($search_status != '' && $search_status >= 0)) {
114
    $filters[] = "statut = " . ((int)$search_status);
115
}
116
if (($search_employee != '' && $search_employee >= 0)) {
117
    $filters[] = "employee = " . ((int)$search_employee);
118
}
119
$sqlfilter = '';
120
if (!empty($filters)) {
121
    $sqlfilter = implode(' AND ', $filters);
122
}
123
// Load hierarchy of users
124
$user_arbo_all = $userstatic->get_full_tree(0, '');
125
if ($sqlfilter) {
126
    $user_arbo = $userstatic->get_full_tree(0, $sqlfilter);
127
} else {
128
    $user_arbo = $user_arbo_all;
129
}
130
131
// Count total nb of records
132
$nbtotalofrecords = count($user_arbo);
133
134
135
if (!is_array($user_arbo) && $user_arbo < 0) {
136
    setEventMessages($userstatic->error, $userstatic->errors, 'warnings');
137
} else {
138
    // Define fulltree array
139
    $fulltree = $user_arbo;
140
    //var_dump($fulltree);
141
    // Define data (format for treeview)
142
    $data = array();
143
    $data[0] = array('rowid' => 0, 'fk_menu' => -1, 'title' => "racine", 'mainmenu' => '', 'leftmenu' => '', 'fk_mainmenu' => '', 'fk_leftmenu' => '');
144
145
    foreach ($fulltree as $key => $val) {
0 ignored issues
show
The expression $fulltree of type integer is not traversable.
Loading history...
146
        $userstatic->id = $val['id'];
147
        $userstatic->ref = (string)$val['id'];
148
        $userstatic->login = $val['login'];
149
        $userstatic->firstname = $val['firstname'];
150
        $userstatic->lastname = $val['lastname'];
151
        $userstatic->status = $val['statut'];
152
        $userstatic->email = $val['email'];
153
        $userstatic->gender = $val['gender'];
154
        $userstatic->socid = $val['fk_soc'];
155
        $userstatic->admin = $val['admin'];
156
        $userstatic->entity = $val['entity'];
157
        $userstatic->photo = $val['photo'];
158
159
        $entity = $val['entity'];
160
        $entitystring = '';
161
162
        // TODO Set of entitystring should be done with a hook
163
        if (isModEnabled('multicompany') && is_object($mc)) {
164
            if (empty($entity)) {
165
                $entitystring = $langs->trans("AllEntities");
166
            } else {
167
                $mc->getInfo($entity);
168
                $entitystring = $mc->label;
169
            }
170
        }
171
172
        $li = $userstatic->getNomUrl(-1, '', 0, 1);
173
        if (isModEnabled('multicompany') && $userstatic->admin && !$userstatic->entity) {
174
            $li .= img_picto($langs->trans("SuperAdministratorDesc"), 'redstar', 'class="valignmiddle paddingright paddingleft"');
175
        } elseif ($userstatic->admin) {
176
            $li .= img_picto($langs->trans("AdministratorDesc"), 'star', 'class="valignmiddle paddingright paddingleft"');
177
        }
178
        $li .= ' <span class="opacitymedium">(' . $val['login'] . ($entitystring ? ' - ' . $entitystring : '') . ')</span>';
179
180
        $entry = '<table class="nobordernopadding centpercent"><tr class="trtree"><td class="' . ($val['statut'] ? 'usertdenabled' : 'usertddisabled') . '">' . $li . '</td><td align="right" class="' . ($val['statut'] ? 'usertdenabled' : 'usertddisabled') . '">' . $userstatic->getLibStatut(2) . '</td></tr></table>';
181
182
        $data[$val['rowid']] = array(
183
            'rowid' => $val['rowid'],
184
            'fk_menu' => $val['fk_user'], // TODO Replace fk_menu with fk_parent
185
            'statut' => $val['statut'],
186
            'entry' => $entry
187
        );
188
    }
189
190
    // Loop on $data to link user linked to a parent that was excluded by the filter
191
    foreach ($data as $key => $tmpdata) {
192
        $idparent = $tmpdata['fk_menu'];
193
        // Loop to check if parent exists
194
        if ($idparent > 0) {
195
            $parentfound = array_key_exists($idparent, $data) ? 1 : 0;
196
197
            $i = 0;
198
            while (!$parentfound && $i < 50) {
199
                // Parent was not found but we need it to show the child, so we reintroduce the parent
200
                if (!empty($user_arbo_all[$idparent])) {
201
                    $val = $user_arbo_all[$idparent];
202
                    $userstatic->id = $val['id'];
203
                    $userstatic->ref = (string)$val['id'];
204
                    $userstatic->login = $val['login'];
205
                    $userstatic->firstname = $val['firstname'];
206
                    $userstatic->lastname = $val['lastname'];
207
                    $userstatic->status = $val['statut'];
208
                    $userstatic->email = $val['email'];
209
                    $userstatic->gender = $val['gender'];
210
                    $userstatic->socid = $val['fk_soc'];
211
                    $userstatic->admin = $val['admin'];
212
                    $userstatic->entity = $val['entity'];
213
                    $userstatic->photo = $val['photo'];
214
215
                    $entity = $val['entity'];
216
                    $entitystring = '';
217
218
                    // TODO Set of entitystring should be done with a hook
219
                    if (isModEnabled('multicompany') && is_object($mc)) {
220
                        if (empty($entity)) {
221
                            $entitystring = $langs->trans("AllEntities");
222
                        } else {
223
                            $mc->getInfo($entity);
224
                            $entitystring = $mc->label;
225
                        }
226
                    }
227
228
                    $li = '<span class="opacitymedium">';
229
                    $li .= $userstatic->getNomUrl(-1, '', 0, 1);
230
                    if (isModEnabled('multicompany') && $userstatic->admin && !$userstatic->entity) {
231
                        $li .= img_picto($langs->trans("SuperAdministrator"), 'redstar');
232
                    } elseif ($userstatic->admin) {
233
                        $li .= img_picto($langs->trans("Administrator"), 'star');
234
                    }
235
                    $li .= ' <span class="opacitymedium">(' . $val['login'] . ($entitystring ? ' - ' . $entitystring : '') . ')</span>';
236
                    $li .= ' - <span class="opacitymedium">' . $langs->trans("ExcludedByFilter") . '</span>';
237
                    $li .= '</span>';
238
239
                    $entry = '<table class="nobordernopadding centpercent"><tr class="trtree"><td class="' . ($val['statut'] ? 'usertdenabled' : 'usertddisabled') . '">' . $li . '</td><td align="right" class="' . ($val['statut'] ? 'usertdenabled' : 'usertddisabled') . '">' . $userstatic->getLibStatut(2) . '</td></tr></table>';
240
241
                    $data[$idparent] = array(
242
                        'rowid' => $idparent,
243
                        'fk_menu' => $user_arbo_all[$idparent]['fk_user'],
244
                        'statut' => $user_arbo_all[$idparent]['statut'],
245
                        'entry' => $entry
246
                    );
247
                    $idparent = $user_arbo_all[$idparent]['fk_user'];
248
                    if ($idparent > 0) {
249
                        $parentfound = array_key_exists($idparent, $data) ? 1 : 0;
250
                    } else {
251
                        $parentfound = 1;
252
                    }
253
                    //var_dump($data[$idparent]);
254
                } else {
255
                    // We should not be here. If a record has a parent id, parent id should be into $user_arbo_all
256
                    $data[$key]['fk_menu'] = -2;
257
                    if (empty($data[-2])) {
258
                        $li = '<span class="opacitymedium">' . $langs->trans("WarningParentIDDoesNotExistAnymore") . '</span>';
259
                        $entry = '<table class="nobordernopadding centpercent"><tr class="trtree"><td class="usertddisabled">' . $li . '</td><td align="right" class="usertddisabled"></td></tr></table>';
260
                        $data[-2] = array(
261
                            'rowid' => '-2',
262
                            'fk_menu' => null,
263
                            'statut' => '1',
264
                            'entry' => $entry
265
                        );
266
                    }
267
                    $parentfound = 1;
268
                }
269
270
                $i++;
271
            }
272
        }
273
    }
274
    //var_dump($data);exit;
275
276
    $param = "&search_status=" . urlencode($search_status);
277
    $param = "&contextpage=" . urlencode($contextpage);
278
279
    $newcardbutton = '';
280
    $newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars paddingleft imgforviewmode', constant('BASE_URL') . '/user/list.php?mode=common' . preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss' => 'reposition'));
281
    $newcardbutton .= dolGetButtonTitle($langs->trans('HierarchicView'), '', 'fa fa-stream paddingleft imgforviewmode', constant('BASE_URL') . '/user/hierarchy.php?mode=hierarchy' . preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', (($mode == 'hierarchy') ? 2 : 1), array('morecss' => 'reposition'));
282
    $newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', constant('BASE_URL') . '/user/list.php?mode=kanban' . preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss' => 'reposition'));
283
    $newcardbutton .= dolGetButtonTitleSeparator();
284
    $newcardbutton .= dolGetButtonTitle($langs->trans('NewUser'), '', 'fa fa-plus-circle', constant('BASE_URL') . '/user/card.php?action=create' . ($mode == 'employee' ? '&employee=1' : '') . '&leftmenu=', '', $canadduser);
285
286
    $massactionbutton = '';
287
    $num = 0;
288
    $limit = 0;
289
290
    print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'user', 0, $newcardbutton, '', $limit, 0, 0, 1);
291
292
    print '<form method="POST" id="searchFormList" action="' . $_SERVER["PHP_SELF"] . '">' . "\n";
293
    if ($optioncss != '') {
294
        print '<input type="hidden" name="optioncss" value="' . $optioncss . '">';
295
    }
296
    print '<input type="hidden" name="token" value="' . newToken() . '">';
297
    print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
298
    print '<input type="hidden" name="sortfield" value="' . $sortfield . '">';
299
    print '<input type="hidden" name="sortorder" value="' . $sortorder . '">';
300
    print '<input type="hidden" name="page" value="' . $page . '">';
301
    print '<input type="hidden" name="contextpage" value="' . $contextpage . '">';
302
    print '<input type="hidden" name="mode" value="' . $mode . '">';
303
304
    print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
305
    print '<table class="liste nohover centpercent">';
306
307
    print '<tr class="liste_titre_filter">';
308
    // Action column
309
    if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
310
        print '<td class="liste_titre maxwidthsearch">';
311
        $searchpicto = $form->showFilterAndCheckAddButtons(0);
312
        print $searchpicto;
313
        print '</td>';
314
    }
315
    print '<td class="liste_titre">&nbsp;</td>';
316
    print '<td class="liste_titre">&nbsp;</td>';
317
    // Status
318
    print '<td class="liste_titre right parentonrightofpage">';
319
    print $form->selectarray('search_status', array('-1' => '', '0' => $langs->trans('Disabled'), '1' => $langs->trans('Enabled')), $search_status, 0, 0, 0, '', 0, 0, 0, '', 'minwidth75imp onrightofpage width100');
320
    print '</td>';
321
    // Action column
322
    if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
323
        print '<td class="liste_titre maxwidthsearch">';
324
        $searchpicto = $form->showFilterAndCheckAddButtons(0);
325
        print $searchpicto;
326
        print '</td>';
327
    }
328
    print '</tr>';
329
330
    print '<tr class="liste_titre">';
331
    // Action column
332
    if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
333
        print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', '', '', '', 'maxwidthsearch ');
334
    }
335
    print_liste_field_titre("HierarchicView");
336
    print_liste_field_titre('<div id="iddivjstreecontrol"><a href="#">' . img_picto('', 'folder', 'class="paddingright"') . '<span class="hideonsmartphone">' . $langs->trans("UndoExpandAll") . '</span></a> | <a href="#">' . img_picto('', 'folder-open', 'class="paddingright"') . '<span class="hideonsmartphone">' . $langs->trans("ExpandAll") . '</span></a></div>', $_SERVER['PHP_SELF'], "", '', "", 'align="center"');
337
    print_liste_field_titre("Status", $_SERVER['PHP_SELF'], "", '', "", '', '', '', 'right onrightofpage');
338
    // Action column
339
    if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
340
        print_liste_field_titre('', $_SERVER["PHP_SELF"], "", '', '', '', '', '', 'maxwidthsearch ');
341
    }
342
    print '</tr>';
343
344
345
    $nbofentries = (count($data) - 1);
346
347
    if ($nbofentries > 0) {
348
        print '<tr>';
349
        // Action column
350
        if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
351
            print '<td></td>';
352
        }
353
        print '<td colspan="3">';
354
        tree_recur($data, $data[0], 0);
355
        print '</td>';
356
        // Action column
357
        if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
358
            print '<td></td>';
359
        }
360
        print '</tr>';
361
    } else {
362
        print '<tr class="oddeven">';
363
        print '<td colspan="3">';
364
        print '<table class="nobordernopadding"><tr class="nobordernopadding"><td>' . img_picto_common('', 'treemenu/branchbottom.gif') . '</td>';
365
        print '<td valign="middle">';
366
        print $langs->trans("NoCategoryYet");
367
        print '</td>';
368
        print '<td>&nbsp;</td>';
369
        print '</table>';
370
        print '</td>';
371
        print '<td></td>';
372
        print '</tr>';
373
    }
374
375
    print "</table>";
376
    print '</div>';
377
378
    print "</form>\n";
379
}
380
381
//
382
/*print '<script type="text/javascript">
383
jQuery(document).ready(function() {
384
    function init_myfunc()
385
    {
386
        jQuery(".usertddisabled").hide();
387
    }
388
    init_myfunc();
389
});
390
</script>';
391
*/
392
393
// End of page
394
ViewMain::llxFooter();
395
$db->close();
396