Passed
Push — master ( b117f4...9373fc )
by Nils
05:56
created

buildNodeTree()   D

Complexity

Conditions 22
Paths 2

Size

Total Lines 91
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 15
Bugs 0 Features 0
Metric Value
cc 22
eloc 57
c 15
b 0
f 0
nc 2
nop 16
dl 0
loc 91
rs 4.1666

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Teampass - a collaborative passwords manager.
7
 * ---
8
 * This library is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @project   Teampass
13
 * @file      tree.php
14
 *
15
 * @author    Nils Laumaillé ([email protected])
16
 * @copyright 2009-2022 Teampass.net
17
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
18
 *
19
 * @see       https://www.teampass.net
20
 */
21
22
23
require_once 'SecureHandler.php';
24
session_name('teampass_session');
25
session_start();
26
if (
27
    isset($_SESSION['CPM']) === false
28
    || $_SESSION['CPM'] !== 1
29
    || isset($_SESSION['key']) === false
30
    || empty($_SESSION['key']) === true
31
) {
32
    die('Hacking attempt...');
33
}
34
35
// Load config
36
if (file_exists('../includes/config/tp.config.php')) {
37
    include_once '../includes/config/tp.config.php';
38
} elseif (file_exists('./includes/config/tp.config.php')) {
39
    include_once './includes/config/tp.config.php';
40
} else {
41
    throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
42
}
43
44
// includes
45
require_once $SETTINGS['cpassman_dir'] . '/includes/config/include.php';
46
require_once $SETTINGS['cpassman_dir'] . '/sources/SplClassLoader.php';
47
require_once $SETTINGS['cpassman_dir'] . '/sources/main.functions.php';
48
require_once $SETTINGS['cpassman_dir'] . '/includes/language/' . $_SESSION['user_language'] . '.php';
49
require_once $SETTINGS['cpassman_dir'] . '/includes/config/settings.php';
50
51
// header
52
header('Content-type: text/html; charset=utf-8');
53
header('Cache-Control: no-cache, must-revalidate');
54
55
// Define Timezone
56
if (isset($SETTINGS['timezone'])) {
57
    date_default_timezone_set($SETTINGS['timezone']);
58
} else {
59
    date_default_timezone_set('UTC');
60
}
61
62
// Connect to mysql server
63
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Database/Meekrodb/db.class.php';
64
if (defined('DB_PASSWD_CLEAR') === false) {
65
    define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
66
}
67
DB::$host = DB_HOST;
68
DB::$user = DB_USER;
69
DB::$password = DB_PASSWD_CLEAR;
70
DB::$dbName = DB_NAME;
71
DB::$port = DB_PORT;
72
DB::$encoding = DB_ENCODING;
73
74
// Superglobal load
75
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
76
$superGlobal = new protect\SuperGlobal\SuperGlobal();
77
$get = [];
78
$get['user_tree_structure'] = $superGlobal->get('user_tree_structure', 'GET');
79
$get['user_tree_last_refresh_timestamp'] = $superGlobal->get('user_tree_last_refresh_timestamp', 'GET');
80
$get['force_refresh'] = $superGlobal->get('force_refresh', 'GET');
81
$get['id'] = $superGlobal->get('id', 'GET');
82
$session = [];
83
$session['forbiden_pfs'] = $superGlobal->get('forbiden_pfs', 'SESSION');
84
$session['groupes_visibles'] = $superGlobal->get('groupes_visibles', 'SESSION');
85
$session['list_restricted_folders_for_items'] = $superGlobal->get('list_restricted_folders_for_items', 'SESSION');
86
$session['user_id'] = $superGlobal->get('user_id', 'SESSION');
87
$session['login'] = $superGlobal->get('login', 'SESSION');
88
$session['user_read_only'] = $superGlobal->get('user_read_only', 'SESSION');
89
//$session['personal_folder'] = explode(';', $superGlobal->get('personal_folder', 'SESSION'));
90
$session['list_folders_limited'] = $superGlobal->get('list_folders_limited', 'SESSION');
91
$session['read_only_folders'] = $superGlobal->get('read_only_folders', 'SESSION');
92
$session['personal_visible_groups'] = $superGlobal->get('personal_visible_groups', 'SESSION');
93
$lastFolderChange = DB::query(
94
    'SELECT * FROM ' . prefixTable('misc') . '
95
    WHERE type = %s AND intitule = %s',
96
    'timestamp',
97
    'last_folder_change'
98
);
99
if (
100
    empty($get['user_tree_structure']) === true
101
    || ($get['user_tree_last_refresh_timestamp'] !== null && strtotime($lastFolderChange) > strtotime($get['user_tree_last_refresh_timestamp']))
102
    || (isset($get['force_refresh']) === true && (int) $get['force_refresh'] === 1)
103
) {
104
    // Build tree
105
    $tree = new SplClassLoader('Tree\NestedTree', $SETTINGS['cpassman_dir'] . '/includes/libraries');
106
    $tree->register();
107
    $tree = new Tree\NestedTree\NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
108
109
    if (
110
        isset($session['list_folders_limited']) === true
111
        && is_array($session['list_folders_limited']) === true
112
        && count($session['list_folders_limited']) > 0
113
    ) {
114
        $listFoldersLimitedKeys = array_keys($session['list_folders_limited']);
115
    } else {
116
        $listFoldersLimitedKeys = array();
117
    }
118
    
119
    // list of items accessible but not in an allowed folder
120
    if (
121
        isset($session['list_restricted_folders_for_items']) === true
122
        && count($session['list_restricted_folders_for_items']) > 0
123
    ) {
124
        $listRestrictedFoldersForItemsKeys = @array_keys($session['list_restricted_folders_for_items']);
125
    } else {
126
        $listRestrictedFoldersForItemsKeys = array();
127
    }
128
    
129
    //$_SESSION['user_treeloadstrategy'] = 'sequential';
130
    $ret_json = array();
131
    $last_visible_parent = -1;
132
    $last_visible_parent_level = 1;
133
134
    // build the tree to be displayed
135
    if (
136
        isset($get['id']) === true
137
        && is_numeric(intval($get['id'])) === true
138
        && isset($_SESSION['user_treeloadstrategy']) === true
139
        && $_SESSION['user_treeloadstrategy'] === 'sequential'
140
    ) {
141
        $ret_json = buildNodeTree(
142
            $get['id'],
143
            $listFoldersLimitedKeys,
144
            $listRestrictedFoldersForItemsKeys,
145
            /** @scrutinizer ignore-type */ $tree,
146
            $SETTINGS,
147
            $session['forbiden_pfs'],
148
            $session['groupes_visibles'],
149
            $session['list_restricted_folders_for_items'],
150
            $session['user_id'],
151
            $session['login'],
152
            $superGlobal->get('no_access_folders', 'SESSION'),
153
            $superGlobal->get('personal_folders', 'SESSION'),
154
            $session['list_folders_limited'],
155
            $session['read_only_folders'],
156
            $superGlobal->get('personal_folders', 'SESSION'),
157
            $session['personal_visible_groups'],
158
            $session['user_read_only']
0 ignored issues
show
Unused Code introduced by
The call to buildNodeTree() has too many arguments starting with $session['user_read_only']. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

158
        $ret_json = /** @scrutinizer ignore-call */ buildNodeTree(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
159
        );
160
    } elseif (
161
        isset($_SESSION['user_treeloadstrategy']) === true
162
        && $_SESSION['user_treeloadstrategy'] === 'sequential'
163
    ) {
164
        $ret_json = buildNodeTree(
165
            0,
166
            $listFoldersLimitedKeys,
167
            $listRestrictedFoldersForItemsKeys,
168
            /** @scrutinizer ignore-type */ $tree,
169
            $SETTINGS,
170
            $session['forbiden_pfs'],
171
            $session['groupes_visibles'],
172
            $session['list_restricted_folders_for_items'],
173
            $session['user_id'],
174
            $session['login'],
175
            $superGlobal->get('no_access_folders', 'SESSION'),
176
            $superGlobal->get('personal_folders', 'SESSION'),
177
            $session['list_folders_limited'],
178
            $session['read_only_folders'],
179
            $superGlobal->get('personal_folders', 'SESSION'),
180
            $session['personal_visible_groups'],
181
            $session['user_read_only']
182
        );
183
    } else {
184
        $completTree = $tree->getTreeWithChildren();
185
        foreach ($completTree[0]->children as $child) {
186
            recursiveTree(
187
                $child,
188
                $completTree,
189
                /** @scrutinizer ignore-type */ $tree,
190
                $listFoldersLimitedKeys,
191
                $listRestrictedFoldersForItemsKeys,
192
                $last_visible_parent,
193
                $last_visible_parent_level,
194
                $SETTINGS,
195
                $session['forbiden_pfs'],
196
                $session['groupes_visibles'],
197
                $session['list_restricted_folders_for_items'],
198
                $session['user_id'],
199
                $session['login'],
200
                $session['user_read_only'],
201
                $superGlobal->get('personal_folders', 'SESSION'),
202
                $session['list_folders_limited'],
203
                $session['read_only_folders'],
204
                $session['personal_visible_groups'],
205
                $superGlobal->get('can_create_root_folder', 'SESSION'),
206
                $ret_json
207
            );
208
        }
209
    }
210
211
    // Save in SESSION
212
    $superGlobal->put('user_tree_structure', $ret_json, 'SESSION');
213
    $superGlobal->put('user_tree_last_refresh_timestamp', time(), 'SESSION');
214
215
    // Send back
216
    echo json_encode($ret_json);
217
} else {
218
    echo $get['user_tree_structure'];
219
}
220
221
/**
222
 * Get through asked folders
223
 *
224
 * @param [int] $nodeId
0 ignored issues
show
Documentation Bug introduced by
The doc comment [int] at position 0 could not be parsed: Unknown type name '[' at position 0 in [int].
Loading history...
225
 * @param [array] $listFoldersLimitedKeys
226
 * @param [array] $listRestrictedFoldersForItemsKeys
227
 * @param [array] $tree
228
 * @param [array] $SETTINGS
229
 * @param [array] $session_forbiden_pfs
230
 * @param [array] $session_groupes_visibles
231
 * @param [array] $session_list_restricted_folders_for_items
232
 * @param [int] $session_user_id
233
 * @param [string] $session_login
234
 * @param [array] $session_no_access_folders
235
 * @param [array] $session_list_folders_limited
236
 * @param [array] $session_read_only_folders
237
 * @param [array] $session_personal_folders
238
 * @param [array] $session_personal_visible_groups
239
 * @param [int] $session_user_read_only
240
 * @return array
241
 */
242
function buildNodeTree(
243
    $nodeId,
244
    $listFoldersLimitedKeys,
245
    $listRestrictedFoldersForItemsKeys,
246
    $tree,
247
    $SETTINGS,
248
    $session_forbiden_pfs,
249
    $session_groupes_visibles,
250
    $session_list_restricted_folders_for_items,
251
    $session_user_id,
252
    $session_login,
253
    $session_no_access_folders,
254
    $session_list_folders_limited,
255
    $session_read_only_folders,
256
    $session_personal_folders,
257
    $session_personal_visible_groups,
258
    $session_user_read_only
259
) {
260
    // Prepare superGlobal variables
261
    $ret_json = array();
262
263
    // Be sure that user can only see folders he/she is allowed to
264
    if (
265
        in_array($nodeId, $session_forbiden_pfs) === false
266
        || in_array($nodeId, $session_groupes_visibles) === true
267
        || in_array($nodeId, $listFoldersLimitedKeys) === true
268
        || in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true
269
    ) {
270
        $nbChildrenItems = 0;
271
272
        // Check if any allowed folder is part of the descendants of this node
273
        $nodeDescendants = $tree->getDescendants($nodeId, false, true, false);
274
        foreach ($nodeDescendants as $node) {
275
            if ((in_array($node->id, $session_forbiden_pfs) === false
276
                    || in_array($node->id, $session_groupes_visibles) === true
277
                    || in_array($node->id, $listFoldersLimitedKeys) === true
278
                    || in_array($node->id, $listRestrictedFoldersForItemsKeys)) === true
279
                && (in_array(
280
                    $node->id,
281
                    array_merge($session_groupes_visibles, $session_list_restricted_folders_for_items)
282
                ) === true
283
                    || (is_array($listFoldersLimitedKeys) === true && in_array($node->id, $listFoldersLimitedKeys) === true)
284
                    || (is_array($listRestrictedFoldersForItemsKeys) === true && in_array($node->id, $listRestrictedFoldersForItemsKeys) === true)
285
                    || in_array($node->id, $session_no_access_folders) === true)
286
            ) {
287
                $nodeElements= buildNodeTreeElements(
288
                    $ret_json,
289
                    $node,
290
                    $session_user_id,
291
                    $session_login,
292
                    $session_user_read_only,
293
                    $session_personal_folders,
294
                    $session_groupes_visibles,
295
                    $session_read_only_folders,
296
                    $session_personal_visible_groups,
297
                    $nbChildrenItems,
298
                    $nodeDescendants,
299
                    $listFoldersLimitedKeys,
300
                    $session_list_folders_limited,
301
                    $listRestrictedFoldersForItemsKeys,
302
                    $session_list_restricted_folders_for_items,
303
                    $SETTINGS,
304
                    $tree->numDescendants($node->id)
305
                );
306
307
                // json    
308
                array_push(
309
                    $ret_json,
310
                    array(
311
                        'id' => 'li_' . $node->id,
312
                        'parent' => $nodeElements['parent'],
313
                        'text' => '<i class="fas fa-folder mr-2"></i>'.($nodeElements['show_but_block'] === true ? '<i class="fas fa-times fa-xs text-danger mr-1"></i>' : '') . $nodeElements['text'],
314
                        'children' => ($nodeElements['childrenNb'] === 0 ? false : true),
315
                        'fa_icon' => 'folder',
316
                        'li_attr' => array(
317
                            'class' => ($snodeElements['how_but_block'] === true ? '' : 'jstreeopen'),
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $snodeElements does not exist. Did you maybe mean $nodeElements?
Loading history...
318
                            'title' => 'ID [' . $node->id . '] ' . ($nodeElements['show_but_block'] === true ? langHdl('no_access') : $nodeElements['title']),
319
                        ),
320
                        'a_attr' => $nodeElements['show_but_block'] === true ? (array(
321
                            'id' => 'fld_' . $node->id,
322
                            'class' => $nodeElements['folderClass'],
323
                            'onclick' => 'ListerItems(' . $node->id . ', ' . $nodeElements['restricted'] . ', 0, 1)',
324
                            'data-title' => $node->title,
325
                        )) : '',
326
                        'is_pf' => in_array($node->id, $session_personal_folders) === true ? 1 : 0,
327
                    )
328
                );
329
            }
330
        }
331
    }
332
    return $ret_json;
333
}
334
335
336
function buildNodeTreeElements(
337
    $ret_json,
0 ignored issues
show
Unused Code introduced by
The parameter $ret_json is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

337
    /** @scrutinizer ignore-unused */ $ret_json,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
338
    $node,
339
    $session_user_id,
340
    $session_login,
341
    $session_user_read_only,
342
    $session_personal_folders,
343
    $session_groupes_visibles,
344
    $session_read_only_folders,
345
    $session_personal_visible_groups,
346
    $nbChildrenItems,
347
    $nodeDescendants,
348
    $listFoldersLimitedKeys,
349
    $session_list_folders_limited,
350
    $listRestrictedFoldersForItemsKeys,
351
    $session_list_restricted_folders_for_items,
352
    $SETTINGS,
353
    $numDescendants
354
)
355
{
356
    $show_but_block = false;
357
    $title = '';
358
359
    // get count of Items in this folder
360
    DB::query(
361
        'SELECT *
362
        FROM ' . prefixTable('items') . '
363
        WHERE inactif=%i AND id_tree = %i',
364
        0,
365
        $node->id
366
    );
367
    $itemsNb = DB::count();
368
369
    // get info about current folder
370
    DB::query(
371
        'SELECT *
372
        FROM ' . prefixTable('nested_tree') . '
373
        WHERE parent_id = %i',
374
        $node->id
375
    );
376
    $childrenNb = DB::count();
377
378
    // If personal Folder, convert id into user name
379
    $node->title = $node->title === $session_user_id && (int) $node->nlevel === 1 ?
380
        $session_login :
381
        ($node->title === null ? '' : htmlspecialchars_decode($node->title, ENT_QUOTES));
382
383
    // prepare json return for current node
384
    $parent = $node->parent_id === 0 ? '#' : 'li_' . $node->parent_id;
385
386
    // special case for READ-ONLY folder
387
    $title = $session_user_read_only === true && in_array($node->id, $session_personal_folders) === false ? langHdl('read_only_account') : $title;
388
    $text = str_replace('&', '&amp;', $node->title);
389
    $restricted = '0';
390
    $folderClass = 'folder';
391
392
    if (in_array($node->id, $session_groupes_visibles) === true) {
393
        if (in_array($node->id, $session_read_only_folders) === true) {
394
            $text = "<i class='far fa-eye fa-xs mr-1 ml-1'></i>" . $text;
395
            $title = langHdl('read_only_account');
396
            $restricted = 1;
397
            $folderClass = 'folder_not_droppable';
398
        } elseif ($session_user_read_only === true && !in_array($node->id, $session_personal_visible_groups)) {
399
            $text = "<i class='far fa-eye fa-xs mr-1 ml-1'></i>" . $text;
400
        }
401
        $text .=
402
            ' <span class=\'badge badge-danger ml-2 items_count\' id=\'itcount_' . $node->id . '\'>' . $itemsNb . '</span>'
403
            .(isset($SETTINGS['tree_counters']) && (int) $SETTINGS['tree_counters'] === 1 ?
404
                '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  :
405
                '')
406
            .'</span>';
407
408
        return array(
409
            'text' => $text,
410
            'title' => $title,
411
            'restricted' => $restricted,
412
            'folderClass' => $folderClass,
413
            'show_but_block' => $show_but_block,
414
            'parent' => $parent,
415
            'restricted' => $restricted,
416
            'childrenNb' => $childrenNb,
417
            'itemsNb' => $itemsNb,
418
        );
419
    }
420
    
421
    if (in_array($node->id, $listFoldersLimitedKeys)) {
422
        $restricted = 1;
423
        $text .= 
424
            $session_user_read_only === true ?
425
                "<i class='far fa-eye fa-xs mr-1 ml-1'></i>" :
426
                '<span class="badge badge-danger ml-2 items_count" id="itcount_' . $node->id . '">' . count($session_list_folders_limited[$node->id]) . '</span>';
427
428
        return array(
429
            'text' => $text,
430
            'title' => $title,
431
            'restricted' => $restricted,
432
            'folderClass' => $folderClass,
433
            'show_but_block' => $show_but_block,
434
            'parent' => $parent,
435
            'restricted' => $restricted,
436
            'childrenNb' => $childrenNb,
437
            'itemsNb' => $itemsNb,
438
        );
439
    }
440
    
441
    if (in_array($node->id, $listRestrictedFoldersForItemsKeys)) {
442
        $restricted = 1;
443
        if ($session_user_read_only === true) {
444
            $text = "<i class='far fa-eye fa-xs mr-1 ml-1'></i>" . $text;
445
        }
446
        $text .= $session_user_read_only === true ? 
447
            "<i class='far fa-eye fa-xs mr-1 ml-1'></i>" :
448
            '<span class="badge badge-danger ml-2 items_count" id="itcount_' . $node->id . '">' . count($session_list_restricted_folders_for_items[$node->id]) . '</span>';
449
        
450
        return array(
451
            'text' => $text,
452
            'title' => $title,
453
            'restricted' => $restricted,
454
            'folderClass' => $folderClass,
455
            'show_but_block' => $show_but_block,
456
            'parent' => $parent,
457
            'restricted' => $restricted,
458
            'childrenNb' => $childrenNb,
459
            'itemsNb' => $itemsNb,
460
        );
461
    }
462
463
    // default case
464
    $restricted = 1;
465
    $folderClass = 'folder_not_droppable';
466
    if (isset($SETTINGS['show_only_accessible_folders']) && (int) $SETTINGS['show_only_accessible_folders'] === 1) {
467
        // folder is not visible
468
        if ($numDescendants > 0) {
469
            // show it but block it
470
            $show_but_block = true;
471
        } else {
472
            // hide it
473
            return array();
474
        }
475
    } else {
476
        // folder is visible but not accessible by user
477
        $show_but_block = true;
478
    }
479
480
    return array(
481
        'text' => $text,
482
        'title' => $title,
483
        'restricted' => $restricted,
484
        'folderClass' => $folderClass,
485
        'show_but_block' => $show_but_block,
486
        'parent' => $parent,
487
        'restricted' => $restricted,
488
        'childrenNb' => $childrenNb,
489
        'itemsNb' => $itemsNb,
490
    );
491
}
492
493
/**
494
 * Get through complete tree
495
 *
496
 * @param int     $nodeId                            Id
497
 * @param array   $completTree                       Tree info
498
 * @param array   $tree                              The tree
499
 * @param array   $listFoldersLimitedKeys            Limited
500
 * @param array   $listRestrictedFoldersForItemsKeys Restricted
501
 * @param int     $last_visible_parent               Visible parent
502
 * @param int     $last_visible_parent_level         Parent level
503
 * @param array   $SETTINGS                          Teampass settings
504
 * @param string  $session_forbiden_pfs,
505
 * @param string  $session_groupes_visibles,
506
 * @param string  $session_list_restricted_folders_for_items,
507
 * @param int     $session_user_id,
508
 * @param string  $session_login,
509
 * @param string  $session_user_read_only,
510
 * @param array   $session_personal_folder,
511
 * @param string  $session_list_folders_limited,
512
 * @param string  $session_read_only_folders,
513
 * @param string  $session_personal_visible_groups
514
 * @param int     $can_create_root_folder
515
 * @param array   $ret_json                          Array
516
 *
517
 * @return array
518
 */
519
function recursiveTree(
520
    $nodeId,
521
    $completTree,
522
    $tree,
523
    $listFoldersLimitedKeys,
524
    $listRestrictedFoldersForItemsKeys,
525
    $last_visible_parent,
526
    $last_visible_parent_level,
527
    $SETTINGS,
528
    $session_forbiden_pfs,
529
    $session_groupes_visibles,
530
    $session_list_restricted_folders_for_items,
531
    $session_user_id,
532
    $session_login,
533
    $session_user_read_only,
534
    $session_personal_folder,
535
    $session_list_folders_limited,
536
    $session_read_only_folders,
537
    $session_personal_visible_groups,
538
    $can_create_root_folder,
539
    &$ret_json = array()
540
) {
541
    $text = '';
542
    $title = '';
543
    $show_but_block = false;
544
545
    // Load config
546
    if (file_exists('../includes/config/tp.config.php')) {
547
        include '../includes/config/tp.config.php';
548
    } elseif (file_exists('./includes/config/tp.config.php')) {
549
        include './includes/config/tp.config.php';
550
    } else {
551
        throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
552
    }
553
    
554
    // Be sure that user can only see folders he/she is allowed to
555
    if (
556
        in_array($completTree[$nodeId]->id, $session_forbiden_pfs) === false
557
        || in_array($completTree[$nodeId]->id, $session_groupes_visibles) === true
558
    ) {
559
        $displayThisNode = false;
560
        $nbChildrenItems = 0;
561
        $nodeDirectDescendants = $tree->getDescendants($completTree[$nodeId]->id, false, false, true);
562
563
        // Check if any allowed folder is part of the descendants of this node
564
        $nodeDescendants = $tree->getDescendants($completTree[$nodeId]->id, true, false, true);
565
        foreach ($nodeDescendants as $node) {
566
            // manage tree counters
567
            if (
568
                isset($SETTINGS['tree_counters']) === true
569
                && (int) $SETTINGS['tree_counters'] === 1
570
                && in_array(
571
                    $node,
572
                    array_merge($session_groupes_visibles, $session_list_restricted_folders_for_items)
573
                ) === true
574
            ) {
575
                DB::query(
576
                    'SELECT * FROM ' . prefixTable('items') . '
577
                    WHERE inactif=%i AND id_tree = %i',
578
                    0,
579
                    $node
580
                );
581
                $nbChildrenItems += DB::count();
582
            }
583
584
            if (
585
                in_array($node, $session_groupes_visibles) === true
586
            ) {
587
                // Final check - is PF allowed?
588
                $nodeDetails = $tree->getNode($node);
589
                if (
590
                    (int) $nodeDetails->personal_folder === 1
591
                    && (int) $SETTINGS['enable_pf_feature'] === 1
592
                    && in_array($node, $session_personal_folder) === false
593
                ) {
594
                    $displayThisNode = false;
595
                } else {
596
                    $displayThisNode = true;
597
                    // not adding a break in order to permit a correct count of items
598
                }
599
                $text = '';
600
            }
601
        }
602
        
603
        if ($displayThisNode === true) {
604
            handleNode(
605
                $nodeId,
606
                $completTree,
607
                $tree,
608
                $listFoldersLimitedKeys,
609
                $listRestrictedFoldersForItemsKeys,
610
                $last_visible_parent,
611
                $last_visible_parent_level,
612
                $SETTINGS,
613
                $session_forbiden_pfs,
614
                $session_groupes_visibles,
615
                $session_list_restricted_folders_for_items,
616
                $session_user_id,
617
                $session_login,
618
                $session_user_read_only,
619
                $session_personal_folder,
620
                $session_list_folders_limited,
621
                $session_read_only_folders,
622
                $session_personal_visible_groups,
623
                $text,
624
                $nbChildrenItems,
625
                $nodeDescendants,
626
                $nodeDirectDescendants,
627
                $can_create_root_folder,
628
                $ret_json
629
            );
630
        }
631
    }
632
    return $ret_json;
633
}
634
635
636
function handleNode(
637
    $nodeId,
638
    $completTree,
639
    $tree,
640
    $listFoldersLimitedKeys,
641
    $listRestrictedFoldersForItemsKeys,
642
    $last_visible_parent,
643
    $last_visible_parent_level,
644
    $SETTINGS,
645
    $session_forbiden_pfs,
646
    $session_groupes_visibles,
647
    $session_list_restricted_folders_for_items,
648
    $session_user_id,
649
    $session_login,
650
    $session_user_read_only,
651
    $session_personal_folder,
652
    $session_list_folders_limited,
653
    $session_read_only_folders,
654
    $session_personal_visible_groups,
655
    $text,
656
    $nbChildrenItems,
657
    $nodeDescendants,
658
    $nodeDirectDescendants,
659
    $can_create_root_folder, 
660
    &$ret_json = array()
661
)
662
{
663
    // get info about current folder
664
    DB::query(
665
        'SELECT * FROM ' . prefixTable('items') . '
666
        WHERE inactif=%i AND id_tree = %i',
667
        0,
668
        $completTree[$nodeId]->id
669
    );
670
    $itemsNb = DB::count();
671
672
    // If personal Folder, convert id into user name
673
    if ((int) $completTree[$nodeId]->title === (int) $session_user_id && (int) $completTree[$nodeId]->nlevel === 1) {
674
        $completTree[$nodeId]->title = $session_login;
675
    }
676
677
    // Decode if needed
678
    $completTree[$nodeId]->title = htmlspecialchars_decode($completTree[$nodeId]->title, ENT_QUOTES);
679
680
    $nodeData = prepareNodeData(
681
        $completTree,
682
        (int) $completTree[$nodeId]->id,
683
        $session_groupes_visibles,
684
        $session_read_only_folders,
685
        $session_personal_visible_groups,
686
        (int) $nbChildrenItems,
687
        $nodeDescendants,
688
        (int) $itemsNb,
689
        $session_list_folders_limited,
690
        (int) $SETTINGS['show_only_accessible_folders'],
691
        $nodeDirectDescendants,
692
        (int) $SETTINGS['tree_counters'],
693
        (int) $session_user_read_only,
694
        $listFoldersLimitedKeys,
695
        $listRestrictedFoldersForItemsKeys,
696
        $session_list_restricted_folders_for_items,
697
        $session_personal_folder
698
    );
699
700
    // prepare json return for current node
701
    $parent = $completTree[$nodeId]->parent_id === '0' ? '#' : 'li_' . $completTree[$nodeId]->parent_id;
702
703
    // handle displaying
704
    if (
705
        isset($SETTINGS['show_only_accessible_folders']) === true
706
        && (int) $SETTINGS['show_only_accessible_folders'] === 1
707
    ) {
708
        if ($nodeData['hide_node'] === true) {
709
            $last_visible_parent = (int) $parent;
710
            $last_visible_parent_level = $completTree[$nodeId]->nlevel--;
711
        } elseif ($completTree[$nodeId]->nlevel < $last_visible_parent_level) {
712
            $last_visible_parent = -1;
713
        }
714
    }
715
716
    // json
717
    if ($nodeData['hide_node'] === false && $nodeData['show_but_block'] === false) {
718
        array_push(
719
            $ret_json,
720
            array(
721
                'id' => 'li_' . $completTree[$nodeId]->id,
722
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
723
                'text' => '<i class="fas '.$completTree[$nodeId]->fa_icon.' tree-folder mr-2" data-folder="'.$completTree[$nodeId]->fa_icon.'"  data-folder-selected="'.$completTree[$nodeId]->fa_icon_selected.'"></i>'.$text.$completTree[$nodeId]->title.$nodeData['html'],
724
                'li_attr' => array(
725
                    'class' => 'jstreeopen',
726
                    'title' => 'ID [' . $completTree[$nodeId]->id . '] ' . $nodeData['title'],
727
                ),
728
                'a_attr' => array(
729
                    'id' => 'fld_' . $completTree[$nodeId]->id,
730
                    'class' => $nodeData['folderClass'],
731
                    'onclick' => 'ListerItems(' . $completTree[$nodeId]->id . ', ' . $nodeData['restricted'] . ', 0, 1)',
732
                    'data-title' => $completTree[$nodeId]->title,
733
                ),
734
                'is_pf' => in_array($completTree[$nodeId]->id, $session_personal_folder) === true ? 1 : 0,
735
                'can_edit' => (int) $can_create_root_folder,
736
            )
737
        );
738
    } elseif ($nodeData['show_but_block'] === true) {
739
        array_push(
740
            $ret_json,
741
            array(
742
                'id' => 'li_' . $completTree[$nodeId]->id,
743
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
744
                'text' => '<i class="fas '.$completTree[$nodeId]->fa_icon.' tree-folder mr-2" data-folder="'.$completTree[$nodeId]->fa_icon.'"  data-folder-selected="'.$completTree[$nodeId]->fa_icon_selected.'"></i>'.'<i class="fas fa-times fa-xs text-danger mr-1 ml-1"></i>'.$text.$completTree[$nodeId]->title.$nodeData['html'],
745
                'li_attr' => array(
746
                    'class' => '',
747
                    'title' => 'ID [' . $completTree[$nodeId]->id . '] ' . langHdl('no_access'),
748
                ),
749
            )
750
        );
751
    }
752
    
753
    foreach ($completTree[$nodeId]->children as $child) {
754
        recursiveTree(
755
            $child,
756
            $completTree,
757
            /** @scrutinizer ignore-type */ $tree,
758
            $listFoldersLimitedKeys,
759
            $listRestrictedFoldersForItemsKeys,
760
            $last_visible_parent,
761
            $last_visible_parent_level,
762
            $SETTINGS,
763
            $session_forbiden_pfs,
764
            $session_groupes_visibles,
765
            $session_list_restricted_folders_for_items,
766
            $session_user_id,
767
            $session_login,
768
            $session_user_read_only,
769
            $session_personal_folder,
770
            $session_list_folders_limited,
771
            $session_read_only_folders,
772
            $session_personal_visible_groups,
773
            $can_create_root_folder,
774
            $ret_json
775
        );
776
    }
777
}
778
779
780
781
function prepareNodeData(
782
    $completTree,
783
    $nodeId,
784
    $session_groupes_visibles,
785
    $session_read_only_folders,
786
    $session_personal_visible_groups,
787
    $nbChildrenItems,
788
    $nodeDescendants,
789
    $itemsNb,
790
    $session_list_folders_limited,
791
    $show_only_accessible_folders,
792
    $nodeDirectDescendants,
793
    $tree_counters,
794
    $session_user_read_only,
795
    $listFoldersLimitedKeys,
796
    $listRestrictedFoldersForItemsKeys,
797
    $session_list_restricted_folders_for_items,
798
    $session_personal_folder
799
): array
800
{
801
    // special case for READ-ONLY folder
802
    $title = '';
803
    if (
804
        $session_user_read_only === true
805
        && in_array($completTree[$nodeId]->id, $session_user_read_only) === false
806
    ) {
807
        $title = langHdl('read_only_account');
808
    }
809
810
    if (in_array($nodeId, $session_groupes_visibles) === true) {
811
        if (in_array($nodeId, $session_read_only_folders) === true) {
812
            return [
813
                'html' => '<i class="far fa-eye fa-xs mr-1 ml-1"></i><span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
814
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
815
                'title' => langHdl('read_only_account'),
816
                'restricted' => 1,
817
                'folderClass' => 'folder_not_droppable',
818
                'show_but_block' => false,
819
                'hide_node' => false,
820
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
821
            ];
822
        }
823
824
        if (
825
            $session_user_read_only === true
826
            && in_array($nodeId, $session_personal_visible_groups) === false
827
        ) {
828
            return [
829
                'html' => '<i class="far fa-eye fa-xs mr-1"></i><span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
830
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
831
                'title' => $title,
832
                'restricted' => 0,
833
                'folderClass' => 'folder',
834
                'show_but_block' => false,
835
                'hide_node' => false,
836
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
837
            ];
838
        }
839
        
840
        return [
841
            'html' => '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
842
                ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
843
            'title' => $title,
844
            'restricted' => 0,
845
            'folderClass' => 'folder',
846
            'show_but_block' => false,
847
            'hide_node' => false,
848
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
849
        ];
850
    }
851
    
852
    if (in_array($nodeId, $listFoldersLimitedKeys) === true) {
853
        return [
854
            'html' => ($session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '') .
855
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_folders_limited[$nodeId]) . '</span>',
856
            'title' => $title,
857
            'restricted' => 1,
858
            'folderClass' => 'folder',
859
            'show_but_block' => false,
860
            'hide_node' => false,
861
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
862
        ];
863
    }
864
    
865
    if (in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true) {
866
        return [
867
            'html' => $session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '' .
868
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_restricted_folders_for_items[$nodeId]) . '</span>',
869
            'title' => $title,
870
            'restricted' => 1,
871
            'folderClass' => 'folder',
872
            'show_but_block' => false,
873
            'hide_node' => false,
874
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
875
        ];
876
    }
877
    
878
    if ((int) $show_only_accessible_folders === 1
879
        && $nbChildrenItems === 0
880
    ) {
881
        // folder should not be visible
882
        // only if it has no descendants
883
        if (
884
            count(
885
                array_diff(
886
                    $nodeDirectDescendants,
887
                    array_merge(
888
                        $session_groupes_visibles,
889
                        array_keys($session_list_restricted_folders_for_items)
890
                    )
891
                )
892
            ) !== count($nodeDirectDescendants)
893
        ) {
894
            // show it but block it
895
            return [
896
                'html' => '',
897
                'title' => $title,
898
                'restricted' => 1,
899
                'folderClass' => 'folder_not_droppable',
900
                'show_but_block' => true,
901
                'hide_node' => false,
902
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
903
            ];
904
        }
905
        
906
        // hide it
907
        return [
908
            'html' => '',
909
            'title' => $title,
910
            'restricted' => 1,
911
            'folderClass' => 'folder_not_droppable',
912
            'show_but_block' => false,
913
            'hide_node' => true,
914
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
915
        ];
916
    }
917
918
    return [
919
        'html' => '',
920
        'title' => isset($title) === true ? $title : '',
921
        'restricted' => 1,
922
        'folderClass' => 'folder_not_droppable',
923
        'show_but_block' => true,
924
        'hide_node' => false,
925
        'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
926
    ];
927
}