Passed
Push — master ( efcd91...5154a4 )
by Nils
04:52
created

buildNodeTreeElements()   C

Complexity

Conditions 15
Paths 48

Size

Total Lines 127
Code Lines 85

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 0
Metric Value
cc 15
eloc 85
c 8
b 0
f 0
nc 48
nop 16
dl 0
loc 127
rs 5.0606

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
    $nodeId = isset($get['id']) === true && is_int($get['id']) === true ? $get['id'] : 0;
134
135
    // build the tree to be displayed
136
    if (showFolderToUser(
137
        $nodeId,
138
        $session['forbiden_pfs'],
139
        $session['groupes_visibles'],
140
        $listFoldersLimitedKeys,
141
        $listRestrictedFoldersForItemsKeys
142
    ) === true)
143
    {
144
        if (isset($_SESSION['user_treeloadstrategy']) === true
145
            && $_SESSION['user_treeloadstrategy'] === 'sequential'
146
        ) {
147
            // SEQUENTIAL MODE
148
            // Is this folder visible by user
149
            $ret_json = buildNodeTree(
150
                $nodeId,
151
                $listFoldersLimitedKeys,
152
                $listRestrictedFoldersForItemsKeys,
153
                /** @scrutinizer ignore-type */ $tree,
154
                $SETTINGS,
155
                $session['forbiden_pfs'],
156
                $session['groupes_visibles'],
157
                $session['list_restricted_folders_for_items'],
158
                $session['user_id'],
159
                $session['login'],
160
                $superGlobal->get('no_access_folders', 'SESSION'),
161
                $superGlobal->get('personal_folders', 'SESSION'),
162
                $session['list_folders_limited'],
163
                $session['read_only_folders'],
164
                $superGlobal->get('personal_folders', 'SESSION'),
165
                $session['personal_visible_groups'],
166
                $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

166
            $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...
167
            );
168
        } else {
169
            // FULL MODE
170
            $completTree = $tree->getTreeWithChildren();
171
            foreach ($completTree[0]->children as $child) {
172
                recursiveTree(
173
                    $child,
174
                    $completTree,
175
                    /** @scrutinizer ignore-type */ $tree,
176
                    $listFoldersLimitedKeys,
177
                    $listRestrictedFoldersForItemsKeys,
178
                    $last_visible_parent,
179
                    $last_visible_parent_level,
180
                    $SETTINGS,
181
                    $session['forbiden_pfs'],
182
                    $session['groupes_visibles'],
183
                    $session['list_restricted_folders_for_items'],
184
                    $session['user_id'],
185
                    $session['login'],
186
                    $session['user_read_only'],
187
                    $superGlobal->get('personal_folders', 'SESSION'),
188
                    $session['list_folders_limited'],
189
                    $session['read_only_folders'],
190
                    $session['personal_visible_groups'],
191
                    $superGlobal->get('can_create_root_folder', 'SESSION'),
192
                    $ret_json
193
                );
194
            }
195
        }
196
    }
197
198
    // Save in SESSION
199
    $superGlobal->put('user_tree_structure', $ret_json, 'SESSION');
200
    $superGlobal->put('user_tree_last_refresh_timestamp', time(), 'SESSION');
201
202
    // Send back
203
    echo json_encode($ret_json);
204
} else {
205
    echo $get['user_tree_structure'];
206
}
207
208
/**
209
 * Check if user can see this folder based upon rights
210
 *
211
 * @param integer $nodeId
212
 * @param array $session_forbiden_pfs
213
 * @param array $session_groupes_visibles
214
 * @param array $listFoldersLimitedKeys
215
 * @param array $listRestrictedFoldersForItemsKeys
216
 * @return boolean
217
 */
218
function showFolderToUser(
219
    int $nodeId,
220
    array $session_forbiden_pfs,
221
    array $session_groupes_visibles,
222
    array $listFoldersLimitedKeys,
223
    array $listRestrictedFoldersForItemsKeys,
224
): bool
225
{
226
    if (
227
        in_array($nodeId, $session_forbiden_pfs) === false
228
        || in_array($nodeId, $session_groupes_visibles) === true
229
        || in_array($nodeId, $listFoldersLimitedKeys) === true
230
        || in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true
231
    ) {
232
        return true;
233
    }
234
    return false;
235
}
236
237
/**
238
 * Get through asked folders
239
 *
240
 * @param int $nodeId
241
 * @param array $listFoldersLimitedKeys
242
 * @param array $listRestrictedFoldersForItemsKeys
243
 * @param array $tree
244
 * @param array $SETTINGS
245
 * @param array $session_forbiden_pfs
246
 * @param array $session_groupes_visibles
247
 * @param array $session_list_restricted_folders_for_items
248
 * @param int $session_user_id
249
 * @param string $session_login
250
 * @param array $session_no_access_folders
251
 * @param array $session_list_folders_limited
252
 * @param array $session_read_only_folders
253
 * @param array $session_personal_folders
254
 * @param array $session_personal_visible_groups
255
 * @param int $session_user_read_only
256
 * @return array
257
 */
258
function buildNodeTree(
259
    $nodeId,
260
    $listFoldersLimitedKeys,
261
    $listRestrictedFoldersForItemsKeys,
262
    $tree,
263
    $SETTINGS,
264
    $session_forbiden_pfs,
265
    $session_groupes_visibles,
266
    $session_list_restricted_folders_for_items,
267
    $session_user_id,
268
    $session_login,
269
    $session_no_access_folders,
270
    $session_list_folders_limited,
271
    $session_read_only_folders,
272
    $session_personal_folders,
273
    $session_personal_visible_groups,
274
    $session_user_read_only
275
) {
276
    // Prepare superGlobal variables
277
    $ret_json = array();
278
    $nbChildrenItems = 0;
279
280
    // Check if any allowed folder is part of the descendants of this node
281
    $nodeDescendants = $tree->getDescendants($nodeId, false, true, false);
282
    foreach ($nodeDescendants as $node) {
283
        if (showFolderToUser(
284
                $node->id,
285
                $session_forbiden_pfs,
286
                $session_groupes_visibles,
287
                $listFoldersLimitedKeys,
288
                $listRestrictedFoldersForItemsKeys
289
            ) === true
290
            && (in_array(
291
                $node->id,
292
                array_merge($session_groupes_visibles, $session_list_restricted_folders_for_items)
293
            ) === true
294
                || (is_array($listFoldersLimitedKeys) === true && in_array($node->id, $listFoldersLimitedKeys) === true)
295
                || (is_array($listRestrictedFoldersForItemsKeys) === true && in_array($node->id, $listRestrictedFoldersForItemsKeys) === true)
296
                || in_array($node->id, $session_no_access_folders) === true)
297
        ) {
298
            $nodeElements= buildNodeTreeElements(
299
                $node,
300
                $session_user_id,
301
                $session_login,
302
                $session_user_read_only,
303
                $session_personal_folders,
304
                $session_groupes_visibles,
305
                $session_read_only_folders,
306
                $session_personal_visible_groups,
307
                $nbChildrenItems,
308
                $nodeDescendants,
309
                $listFoldersLimitedKeys,
310
                $session_list_folders_limited,
311
                $listRestrictedFoldersForItemsKeys,
312
                $session_list_restricted_folders_for_items,
313
                $SETTINGS,
314
                $tree->numDescendants($node->id)
315
            );
316
317
            // json    
318
            array_push(
319
                $ret_json,
320
                array(
321
                    'id' => 'li_' . $node->id,
322
                    'parent' => $nodeElements['parent'],
323
                    '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'],
324
                    'children' => ($nodeElements['childrenNb'] === 0 ? false : true),
325
                    'fa_icon' => 'folder',
326
                    'li_attr' => array(
327
                        'class' => ($nodeElements['show_but_block'] === true ? '' : 'jstreeopen'),
328
                        'title' => 'ID [' . $node->id . '] ' . ($nodeElements['show_but_block'] === true ? langHdl('no_access') : $nodeElements['title']),
329
                    ),
330
                    'a_attr' => $nodeElements['show_but_block'] === true ? (array(
331
                        'id' => 'fld_' . $node->id,
332
                        'class' => $nodeElements['folderClass'],
333
                        'onclick' => 'ListerItems(' . $node->id . ', ' . $nodeElements['restricted'] . ', 0, 1)',
334
                        'data-title' => $node->title,
335
                    )) : '',
336
                    'is_pf' => in_array($node->id, $session_personal_folders) === true ? 1 : 0,
337
                )
338
            );
339
        }
340
    }
341
342
    return $ret_json;
343
}
344
345
/**
346
 * Get some infos for this node
347
 *
348
 * @param integer   $nodeId
349
 * @param integer   $nodeLevel
350
 * @param string    $nodeTitle
351
 * @param integer   $userId
352
 * @param string    $userLogin
353
 * @param bool      $userIsRO
354
 * @param array     $userPF
355
 * @return array
356
 */
357
function getNodeInfos(
358
    int $nodeId,
359
    int $nodeLevel,
360
    string $nodeTitle,
361
    int $userId,
362
    string $userLogin,
363
    bool $userIsRO,
364
    array $userPF
365
) : array
366
{
367
    $ret = [];
368
    // get count of Items in this folder
369
    DB::query(
370
        'SELECT *
371
        FROM ' . prefixTable('items') . '
372
        WHERE inactif=%i AND id_tree = %i',
373
        0,
374
        $nodeId
375
    );
376
    $ret['itemsNb'] = DB::count();
377
378
    // get info about current folder
379
    DB::query(
380
        'SELECT *
381
        FROM ' . prefixTable('nested_tree') . '
382
        WHERE parent_id = %i',
383
        $nodeId
384
    );
385
    $ret['childrenNb'] = DB::count();
386
387
    // Manage node title
388
    if ($userIsRO === true && in_array($node->id, $userPF) === false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $node does not exist. Did you maybe mean $nodeId?
Loading history...
389
        // special case for READ-ONLY folder
390
        $ret['title'] = langHdl('read_only_account');
391
    } else {
392
        // If personal Folder, convert id into user name
393
        $ret['title'] = $nodeTitle === $userId && (int) $nodeLevel === 1 ?
0 ignored issues
show
introduced by
The condition $nodeTitle === $userId is always false.
Loading history...
394
        $userLogin :
395
        ($nodeTitle === null ? '' : htmlspecialchars_decode($nodeTitle, ENT_QUOTES));
0 ignored issues
show
introduced by
The condition $nodeTitle === null is always false.
Loading history...
396
    }
397
398
    $ret['text'] = str_replace(
399
        '&',
400
        '&amp;',
401
        $ret['nodeTitle']
402
    );
403
404
    return $ret;
405
}
406
407
function buildNodeTreeElements(
408
    $node,
409
    $session_user_id,
410
    $session_login,
411
    $session_user_read_only,
412
    $session_personal_folders,
413
    $session_groupes_visibles,
414
    $session_read_only_folders,
415
    $session_personal_visible_groups,
416
    $nbChildrenItems,
417
    $nodeDescendants,
418
    $listFoldersLimitedKeys,
419
    $session_list_folders_limited,
420
    $listRestrictedFoldersForItemsKeys,
421
    $session_list_restricted_folders_for_items,
422
    $SETTINGS,
423
    $numDescendants
424
)
425
{
426
    // Get info for this node
427
    $nodeInfos = getNodeInfos(
428
        $node->id,
429
        $node->nlevel,
430
        $node->title,
431
        $session_user_id,
432
        $session_login,
433
        $session_user_read_only,
434
        $session_personal_folders
435
    );
436
    $itemsNb = $nodeInfos['itemsNb'];
437
    $childrenNb = $nodeInfos['childrenNb'];
438
    $title = $nodeInfos['title'];
439
    $text = $nodeInfos['text'];
440
441
    // prepare json return for current node
442
    $parent = $node->parent_id === 0 ? '#' : 'li_' . $node->parent_id;
443
444
    if (in_array($node->id, $session_groupes_visibles) === true) {
445
        if (in_array($node->id, $session_read_only_folders) === true) {
446
            return array(
447
                'text' => '<i class="far fa-eye fa-xs mr-1 ml-1"></i>' . $text
448
                    .' <span class=\'badge badge-danger ml-2 items_count\' id=\'itcount_' . $node->id . '\'>' . $itemsNb . '</span>'
449
                    .(isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true ?
450
                        '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)
451
                        : '')
452
                    .'</span>',
453
                'title' => langHdl('read_only_account'),
454
                'restricted' => 1,
455
                'folderClass' => 'folder_not_droppable',
456
                'show_but_block' => false,
457
                'parent' => $parent,
458
                'childrenNb' => $childrenNb,
459
                'itemsNb' => $itemsNb,
460
            );
461
        }
462
        
463
        return array(
464
            'text' => ($session_user_read_only === true && in_array($node->id, $session_personal_visible_groups) === false) ?
465
                ('<i class="far fa-eye fa-xs mr-1 ml-1"></i>' . $text
466
                .' <span class=\'badge badge-danger ml-2 items_count\' id=\'itcount_' . $node->id . '\'>' . $itemsNb . '</span>'
467
                .(isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true ?
468
                    '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  :
469
                    '')
470
                .'</span>') :
471
                (' <span class=\'badge badge-danger ml-2 items_count\' id=\'itcount_' . $node->id . '\'>' . $itemsNb . '</span>'
472
                .(isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true ?
473
                    '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  :
474
                    '')
475
                .'</span>'),
476
            'title' => langHdl('read_only_account'),
477
            'restricted' => 1,
478
            'folderClass' => 'folder_not_droppable',
479
            'show_but_block' => false,
480
            'parent' => $parent,
481
            'childrenNb' => $childrenNb,
482
            'itemsNb' => $itemsNb,
483
        );
484
    }
485
    
486
    if (in_array($node->id, $listFoldersLimitedKeys) === true) {
487
        return array(
488
            'text' => $text . ($session_user_read_only === true ?
489
                '<i class="far fa-eye fa-xs mr-1 ml-1"></i>' :
490
                '<span class="badge badge-danger ml-2 items_count" id="itcount_' . $node->id . '">' . count($session_list_folders_limited[$node->id]) . '</span>'
491
            ),
492
            'title' => $title,
493
            'restricted' => 1,
494
            'folderClass' => 'folder',
495
            'show_but_block' => false,
496
            'parent' => $parent,
497
            'childrenNb' => $childrenNb,
498
            'itemsNb' => $itemsNb,
499
        );
500
    }
501
    
502
    if (in_array($node->id, $listRestrictedFoldersForItemsKeys) === true) {        
503
        return array(
504
            'text' => $text . ($session_user_read_only === true ? 
505
                '<i class="far fa-eye fa-xs mr-1 ml-1"></i>' :
506
                '<span class="badge badge-danger ml-2 items_count" id="itcount_' . $node->id . '">' . count($session_list_restricted_folders_for_items[$node->id]) . '</span>'
507
            ),
508
            'title' => $title,
509
            'restricted' => 1,
510
            'folderClass' => 'folder',
511
            'show_but_block' => false,
512
            'parent' => $parent,
513
            'childrenNb' => $childrenNb,
514
            'itemsNb' => $itemsNb,
515
        );
516
    }
517
518
    // default case
519
    if (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true
520
        && (int) $numDescendants === 0)
521
    {
522
        return array();
523
    }
524
525
    return array(
526
        'text' => $text,
527
        'title' => $title,
528
        'restricted' => 1,
529
        'folderClass' => 'folder_not_droppable',
530
        'show_but_block' => true,   // folder is visible but not accessible by user
531
        'parent' => $parent,
532
        'childrenNb' => $childrenNb,
533
        'itemsNb' => $itemsNb,
534
    );
535
}
536
537
/**
538
 * Get through complete tree
539
 *
540
 * @param int     $nodeId                            Id
541
 * @param array   $completTree                       Tree info
542
 * @param array   $tree                              The tree
543
 * @param array   $listFoldersLimitedKeys            Limited
544
 * @param array   $listRestrictedFoldersForItemsKeys Restricted
545
 * @param int     $last_visible_parent               Visible parent
546
 * @param int     $last_visible_parent_level         Parent level
547
 * @param array   $SETTINGS                          Teampass settings
548
 * @param string  $session_forbiden_pfs,
549
 * @param string  $session_groupes_visibles,
550
 * @param string  $session_list_restricted_folders_for_items,
551
 * @param int     $session_user_id,
552
 * @param string  $session_login,
553
 * @param string  $session_user_read_only,
554
 * @param array   $session_personal_folder,
555
 * @param string  $session_list_folders_limited,
556
 * @param string  $session_read_only_folders,
557
 * @param string  $session_personal_visible_groups
558
 * @param int     $can_create_root_folder
559
 * @param array   $ret_json                          Array
560
 *
561
 * @return array
562
 */
563
function recursiveTree(
564
    $nodeId,
565
    $completTree,
566
    $tree,
567
    $listFoldersLimitedKeys,
568
    $listRestrictedFoldersForItemsKeys,
569
    $last_visible_parent,
570
    $last_visible_parent_level,
571
    $SETTINGS,
572
    $session_forbiden_pfs,
573
    $session_groupes_visibles,
574
    $session_list_restricted_folders_for_items,
575
    $session_user_id,
576
    $session_login,
577
    $session_user_read_only,
578
    $session_personal_folder,
579
    $session_list_folders_limited,
580
    $session_read_only_folders,
581
    $session_personal_visible_groups,
582
    $can_create_root_folder,
583
    &$ret_json = array()
584
) {
585
    $text = '';
586
    $title = '';
587
    $show_but_block = false;
588
589
    // Load config
590
    if (file_exists('../includes/config/tp.config.php')) {
591
        include '../includes/config/tp.config.php';
592
    } elseif (file_exists('./includes/config/tp.config.php')) {
593
        include './includes/config/tp.config.php';
594
    } else {
595
        throw new Exception("Error file '/includes/config/tp.config.php' not exists", 1);
596
    }
597
    
598
    // Be sure that user can only see folders he/she is allowed to
599
    if (
600
        in_array($completTree[$nodeId]->id, $session_forbiden_pfs) === false
601
        || in_array($completTree[$nodeId]->id, $session_groupes_visibles) === true
602
    ) {
603
        $displayThisNode = false;
604
        $nbChildrenItems = 0;
605
        $nodeDirectDescendants = $tree->getDescendants($completTree[$nodeId]->id, false, false, true);
606
607
        // Check if any allowed folder is part of the descendants of this node
608
        $nodeDescendants = $tree->getDescendants($completTree[$nodeId]->id, true, false, true);
609
        foreach ($nodeDescendants as $node) {
610
            // manage tree counters
611
            if (
612
                isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true
613
                && in_array(
614
                    $node,
615
                    array_merge($session_groupes_visibles, $session_list_restricted_folders_for_items)
616
                ) === true
617
            ) {
618
                DB::query(
619
                    'SELECT * FROM ' . prefixTable('items') . '
620
                    WHERE inactif=%i AND id_tree = %i',
621
                    0,
622
                    $node
623
                );
624
                $nbChildrenItems += DB::count();
625
            }
626
627
            if (
628
                in_array($node, $session_groupes_visibles) === true
629
            ) {
630
                // Final check - is PF allowed?
631
                $nodeDetails = $tree->getNode($node);
632
                if (
633
                    (int) $nodeDetails->personal_folder === 1
634
                    && (int) $SETTINGS['enable_pf_feature'] === 1
635
                    && in_array($node, $session_personal_folder) === false
636
                ) {
637
                    $displayThisNode = false;
638
                } else {
639
                    $displayThisNode = true;
640
                    // not adding a break in order to permit a correct count of items
641
                }
642
                $text = '';
643
            }
644
        }
645
        
646
        if ($displayThisNode === true) {
647
            handleNode(
648
                $nodeId,
649
                $completTree,
650
                $tree,
651
                $listFoldersLimitedKeys,
652
                $listRestrictedFoldersForItemsKeys,
653
                $last_visible_parent,
654
                $last_visible_parent_level,
655
                $SETTINGS,
656
                $session_forbiden_pfs,
657
                $session_groupes_visibles,
658
                $session_list_restricted_folders_for_items,
659
                $session_user_id,
660
                $session_login,
661
                $session_user_read_only,
662
                $session_personal_folder,
663
                $session_list_folders_limited,
664
                $session_read_only_folders,
665
                $session_personal_visible_groups,
666
                $text,
667
                $nbChildrenItems,
668
                $nodeDescendants,
669
                $nodeDirectDescendants,
670
                $can_create_root_folder,
671
                $ret_json
672
            );
673
        }
674
    }
675
    return $ret_json;
676
}
677
678
679
function handleNode(
680
    $nodeId,
681
    $completTree,
682
    $tree,
683
    $listFoldersLimitedKeys,
684
    $listRestrictedFoldersForItemsKeys,
685
    $last_visible_parent,
686
    $last_visible_parent_level,
687
    $SETTINGS,
688
    $session_forbiden_pfs,
689
    $session_groupes_visibles,
690
    $session_list_restricted_folders_for_items,
691
    $session_user_id,
692
    $session_login,
693
    $session_user_read_only,
694
    $session_personal_folder,
695
    $session_list_folders_limited,
696
    $session_read_only_folders,
697
    $session_personal_visible_groups,
698
    $text,
699
    $nbChildrenItems,
700
    $nodeDescendants,
701
    $nodeDirectDescendants,
702
    $can_create_root_folder, 
703
    &$ret_json = array()
704
)
705
{
706
    // get info about current folder
707
    DB::query(
708
        'SELECT * FROM ' . prefixTable('items') . '
709
        WHERE inactif=%i AND id_tree = %i',
710
        0,
711
        $completTree[$nodeId]->id
712
    );
713
    $itemsNb = DB::count();
714
715
    // If personal Folder, convert id into user name
716
    if ((int) $completTree[$nodeId]->title === (int) $session_user_id && (int) $completTree[$nodeId]->nlevel === 1) {
717
        $completTree[$nodeId]->title = $session_login;
718
    }
719
720
    // Decode if needed
721
    $completTree[$nodeId]->title = htmlspecialchars_decode($completTree[$nodeId]->title, ENT_QUOTES);
722
723
    $nodeData = prepareNodeData(
724
        $completTree,
725
        (int) $completTree[$nodeId]->id,
726
        $session_groupes_visibles,
727
        $session_read_only_folders,
728
        $session_personal_visible_groups,
729
        (int) $nbChildrenItems,
730
        $nodeDescendants,
731
        (int) $itemsNb,
732
        $session_list_folders_limited,
733
        (int) $SETTINGS['show_only_accessible_folders'],
734
        $nodeDirectDescendants,
735
        isset($SETTINGS['tree_counters']) === true ? (int) $SETTINGS['tree_counters'] : '',
736
        (int) $session_user_read_only,
737
        $listFoldersLimitedKeys,
738
        $listRestrictedFoldersForItemsKeys,
739
        $session_list_restricted_folders_for_items,
740
        $session_personal_folder
741
    );
742
743
    // prepare json return for current node
744
    $parent = $completTree[$nodeId]->parent_id === '0' ? '#' : 'li_' . $completTree[$nodeId]->parent_id;
745
746
    // handle displaying
747
    if (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true) {
748
        if ($nodeData['hide_node'] === true) {
749
            $last_visible_parent = (int) $parent;
750
            $last_visible_parent_level = $completTree[$nodeId]->nlevel--;
751
        } elseif ($completTree[$nodeId]->nlevel < $last_visible_parent_level) {
752
            $last_visible_parent = -1;
753
        }
754
    }
755
756
    // json
757
    if ($nodeData['hide_node'] === false && $nodeData['show_but_block'] === false) {
758
        array_push(
759
            $ret_json,
760
            array(
761
                'id' => 'li_' . $completTree[$nodeId]->id,
762
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
763
                'text' => '<i class="'.$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'],
764
                'li_attr' => array(
765
                    'class' => 'jstreeopen',
766
                    'title' => 'ID [' . $completTree[$nodeId]->id . '] ' . $nodeData['title'],
767
                ),
768
                'a_attr' => array(
769
                    'id' => 'fld_' . $completTree[$nodeId]->id,
770
                    'class' => $nodeData['folderClass'],
771
                    'onclick' => 'ListerItems(' . $completTree[$nodeId]->id . ', ' . $nodeData['restricted'] . ', 0, 1)',
772
                    'data-title' => $completTree[$nodeId]->title,
773
                ),
774
                'is_pf' => in_array($completTree[$nodeId]->id, $session_personal_folder) === true ? 1 : 0,
775
                'can_edit' => (int) $can_create_root_folder,
776
            )
777
        );
778
    } elseif ($nodeData['show_but_block'] === true) {
779
        array_push(
780
            $ret_json,
781
            array(
782
                'id' => 'li_' . $completTree[$nodeId]->id,
783
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
784
                'text' => '<i class="'.$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'],
785
                'li_attr' => array(
786
                    'class' => '',
787
                    'title' => 'ID [' . $completTree[$nodeId]->id . '] ' . langHdl('no_access'),
788
                ),
789
            )
790
        );
791
    }
792
    
793
    foreach ($completTree[$nodeId]->children as $child) {
794
        recursiveTree(
795
            $child,
796
            $completTree,
797
            /** @scrutinizer ignore-type */ $tree,
798
            $listFoldersLimitedKeys,
799
            $listRestrictedFoldersForItemsKeys,
800
            $last_visible_parent,
801
            $last_visible_parent_level,
802
            $SETTINGS,
803
            $session_forbiden_pfs,
804
            $session_groupes_visibles,
805
            $session_list_restricted_folders_for_items,
806
            $session_user_id,
807
            $session_login,
808
            $session_user_read_only,
809
            $session_personal_folder,
810
            $session_list_folders_limited,
811
            $session_read_only_folders,
812
            $session_personal_visible_groups,
813
            $can_create_root_folder,
814
            $ret_json
815
        );
816
    }
817
}
818
819
820
821
function prepareNodeData(
822
    $completTree,
823
    $nodeId,
824
    $session_groupes_visibles,
825
    $session_read_only_folders,
826
    $session_personal_visible_groups,
827
    $nbChildrenItems,
828
    $nodeDescendants,
829
    $itemsNb,
830
    $session_list_folders_limited,
831
    $show_only_accessible_folders,
832
    $nodeDirectDescendants,
833
    $tree_counters,
834
    $session_user_read_only,
835
    $listFoldersLimitedKeys,
836
    $listRestrictedFoldersForItemsKeys,
837
    $session_list_restricted_folders_for_items,
838
    $session_personal_folder
839
): array
840
{
841
    // special case for READ-ONLY folder
842
    $title = '';
843
    if (
844
        $session_user_read_only === true
845
        && in_array($completTree[$nodeId]->id, $session_user_read_only) === false
846
    ) {
847
        $title = langHdl('read_only_account');
848
    }
849
850
    if (in_array($nodeId, $session_groupes_visibles) === true) {
851
        if (in_array($nodeId, $session_read_only_folders) === true) {
852
            return [
853
                '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 .
854
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
855
                'title' => langHdl('read_only_account'),
856
                'restricted' => 1,
857
                'folderClass' => 'folder_not_droppable',
858
                'show_but_block' => false,
859
                'hide_node' => false,
860
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
861
            ];
862
        }
863
864
        elseif (
865
            $session_user_read_only === true
866
            && in_array($nodeId, $session_personal_visible_groups) === false
867
        ) {
868
            return [
869
                '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 .
870
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
871
                'title' => $title,
872
                'restricted' => 0,
873
                'folderClass' => 'folder',
874
                'show_but_block' => false,
875
                'hide_node' => false,
876
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
877
            ];
878
        }
879
        
880
        return [
881
            'html' => '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
882
                ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
883
            'title' => $title,
884
            'restricted' => 0,
885
            'folderClass' => 'folder',
886
            'show_but_block' => false,
887
            'hide_node' => false,
888
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
889
        ];
890
    }
891
    
892
    elseif (in_array($nodeId, $listFoldersLimitedKeys) === true) {
893
        return [
894
            'html' => ($session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '') .
895
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_folders_limited[$nodeId]) . '</span>',
896
            'title' => $title,
897
            'restricted' => 1,
898
            'folderClass' => 'folder',
899
            'show_but_block' => false,
900
            'hide_node' => false,
901
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
902
        ];
903
    }
904
    
905
    elseif (in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true) {
906
        return [
907
            'html' => $session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '' .
908
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_restricted_folders_for_items[$nodeId]) . '</span>',
909
            'title' => $title,
910
            'restricted' => 1,
911
            'folderClass' => 'folder',
912
            'show_but_block' => false,
913
            'hide_node' => false,
914
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
915
        ];
916
    }
917
    
918
    elseif ((int) $show_only_accessible_folders === 1
919
        && (int) $nbChildrenItems === 0
920
    ) {
921
        // folder should not be visible
922
        // only if it has no descendants
923
        if (
924
            count(
925
                array_diff(
926
                    $nodeDirectDescendants,
927
                    array_merge(
928
                        $session_groupes_visibles,
929
                        array_keys($session_list_restricted_folders_for_items)
930
                    )
931
                )
932
            ) !== count($nodeDirectDescendants)
933
        ) {
934
            // show it but block it
935
            return [
936
                'html' => '',
937
                'title' => $title,
938
                'restricted' => 1,
939
                'folderClass' => 'folder_not_droppable',
940
                'show_but_block' => true,
941
                'hide_node' => false,
942
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
943
            ];
944
        }
945
        
946
        // hide it
947
        return [
948
            'html' => '',
949
            'title' => $title,
950
            'restricted' => 1,
951
            'folderClass' => 'folder_not_droppable',
952
            'show_but_block' => false,
953
            'hide_node' => true,
954
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
955
        ];
956
    }
957
958
    return [
959
        'html' => '',
960
        'title' => isset($title) === true ? $title : '',
961
        'restricted' => 1,
962
        'folderClass' => 'folder_not_droppable',
963
        'show_but_block' => true,
964
        'hide_node' => false,
965
        'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
966
    ];
967
}