Passed
Push — master ( 97a95f...b0e088 )
by Nils
10:41
created

handleNode()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 86
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 1 Features 0
Metric Value
cc 8
eloc 52
nc 12
nop 14
dl 0
loc 86
rs 7.8028
c 12
b 1
f 0

How to fix   Long Method    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
 * @version   3.0.0.22
14
 * @file      tree.php
15
 *
16
 * @author    Nils Laumaillé ([email protected])
17
 * @copyright 2009-2022 Teampass.net
18
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
19
 *
20
 * @see       https://www.teampass.net
21
 */
22
23
24
require_once 'SecureHandler.php';
25
session_name('teampass_session');
26
session_start();
27
if (
28
    isset($_SESSION['CPM']) === false
29
    || $_SESSION['CPM'] !== 1
30
    || isset($_SESSION['key']) === false
31
    || empty($_SESSION['key']) === true
32
) {
33
    die('Hacking attempt...');
34
}
35
36
// Load config
37
include __DIR__.'/../includes/config/tp.config.php';
38
39
// includes
40
require_once $SETTINGS['cpassman_dir'] . '/includes/config/include.php';
41
require_once $SETTINGS['cpassman_dir'] . '/sources/main.functions.php';
42
require_once $SETTINGS['cpassman_dir'] . '/includes/language/' . $_SESSION['user']['user_language'] . '.php';
43
require_once $SETTINGS['cpassman_dir'] . '/includes/config/settings.php';
44
45
// header
46
header('Content-type: text/html; charset=utf-8');
47
header('Cache-Control: no-cache, must-revalidate');
48
49
// Define Timezone
50
if (isset($SETTINGS['timezone'])) {
51
    date_default_timezone_set($SETTINGS['timezone']);
52
} else {
53
    date_default_timezone_set('UTC');
54
}
55
56
// Connect to mysql server
57
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Database/Meekrodb/db.class.php';
58
if (defined('DB_PASSWD_CLEAR') === false) {
59
    define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
60
}
61
DB::$host = DB_HOST;
62
DB::$user = DB_USER;
63
DB::$password = DB_PASSWD_CLEAR;
64
DB::$dbName = DB_NAME;
65
DB::$port = DB_PORT;
66
DB::$encoding = DB_ENCODING;
67
DB::$ssl = DB_SSL;
68
DB::$connect_options = DB_CONNECT_OPTIONS;
69
70
// Superglobal load
71
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
72
$superGlobal = new protect\SuperGlobal\SuperGlobal();
73
74
// Prepare sanitization
75
$data = [
76
    'forbidenPfs' => isset($_SESSION['forbiden_pfs']) === true ? json_encode($_SESSION['forbiden_pfs']) : '{}',
77
    'visibleFolders' => isset($_SESSION['groupes_visibles']) === true ? json_encode($_SESSION['groupes_visibles']) : '{}',
78
    'userId' => isset($_SESSION['user_id']) === true ? $_SESSION['user_id'] : '',
79
    'userLogin' => isset($_SESSION['login']) === true ? $_SESSION['login'] : '',
80
    'userReadOnly' => isset($_SESSION['user_read_only']) === true ? $_SESSION['user_read_only'] : '',
81
    'limitedFolders' => isset($_SESSION['list_folders_limited']) === true ? json_encode($_SESSION['list_folders_limited']) : '{}',
82
    'readOnlyFolders' => isset($_SESSION['read_only_folders']) === true ? json_encode($_SESSION['read_only_folders']) : '{}',
83
    'personalVisibleFolders' => isset($_SESSION['personal_visible_groups']) === true ? json_encode($_SESSION['personal_visible_groups']) : '{}',
84
    'userTreeLastRefresh' => isset($_SESSION['user_tree_last_refresh_timestamp']) === true ? $_SESSION['user_tree_last_refresh_timestamp'] : '',
85
    'forceRefresh' => isset($_GET['force_refresh']) === true ? $_GET['force_refresh'] : '',
86
    'nodeId' => isset($_GET['id']) === true ? $_GET['id'] : '',
87
    'restrictedFoldersForItems' => isset($_GET['list_restricted_folders_for_items']) === true ? json_encode($_GET['list_restricted_folders_for_items']) : '{}',
88
    'noAccessFolders' => isset($_SESSION['no_access_folders']) === true ? json_encode($_SESSION['no_access_folders']) : '{}',
89
    'personalFolders' => isset($_SESSION['personal_folders']) === true ? json_encode($_SESSION['personal_folders']) : '{}',
90
    'userCanCreateRootFolder' => isset($_SESSION['can_create_root_folder']) === true ? json_encode($_SESSION['can_create_root_folder']) : '{}',
91
    'userTreeLoadStrategy' => isset($_SESSION['user']['user_treeloadstrategy']) === true ? $_SESSION['user']['user_treeloadstrategy'] : '',
92
];
93
94
$filters = [
95
    'forbidenPfs' => 'cast:array',
96
    'visibleFolders' => 'cast:array',
97
    'userId' => 'cast:integer',
98
    'userLogin' => 'trim|escape',
99
    'userReadOnly' => 'cast:boolean',
100
    'limitedFolders' => 'cast:array',
101
    'readOnlyFolders' => 'cast:array',
102
    'personalVisibleFolders' => 'cast:array',
103
    'userTreeLastRefresh' => 'cast:integer',
104
    'forceRefresh' => 'cast:integer',
105
    'nodeId' => 'cast:integer',
106
    'restrictedFoldersForItems' => 'cast:array',
107
    'noAccessFolders' => 'cast:array',
108
    'personalFolders' => 'cast:array',
109
    'userCanCreateRootFolder' => 'cast:array',
110
    'userTreeLoadStrategy' => 'trim|escape',
111
];
112
113
$inputData = dataSanitizer(
114
    $data,
115
    $filters,
116
    $SETTINGS['cpassman_dir']
117
);
118
119
$lastFolderChange = DB::queryfirstrow(
120
    'SELECT valeur FROM ' . prefixTable('misc') . '
121
    WHERE type = %s AND intitule = %s',
122
    'timestamp',
123
    'last_folder_change'
124
);
125
if (DB::count() === 0) {
126
    $lastFolderChange['valeur'] = 0;
127
}
128
129
// Should we use a cache or refresh the tree
130
$goTreeRefresh = loadTreeStrategy(
131
    (int) $lastFolderChange['valeur'],
132
    (int) $inputData['userTreeLastRefresh'],
133
    (array) (is_null($superGlobal->get('user_tree_structure', 'SESSION')) === true || empty($superGlobal->get('user_tree_structure', 'SESSION')) === true) ? [] : $superGlobal->get('user_tree_structure', 'SESSION'),
0 ignored issues
show
Bug introduced by
It seems like (array)is_null($superGlo..._structure', 'SESSION') can also be of type null; however, parameter $userSessionTreeStructure of loadTreeStrategy() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

133
    /** @scrutinizer ignore-type */ (array) (is_null($superGlobal->get('user_tree_structure', 'SESSION')) === true || empty($superGlobal->get('user_tree_structure', 'SESSION')) === true) ? [] : $superGlobal->get('user_tree_structure', 'SESSION'),
Loading history...
134
    (int) $inputData['userId'],
135
    (int) $inputData['forceRefresh']
136
);
137
138
// We don't use the cache if an ID of folder is provided
139
if ($goTreeRefresh['state'] === true || empty($inputData['nodeId']) === false || $inputData['userTreeLoadStrategy'] === 'sequential') {
140
    // Build tree
141
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tree/NestedTree/NestedTree.php';
142
    $tree = new Tree\NestedTree\NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
143
144
    if (
145
        isset($inputData['limitedFolders']) === true
146
        && is_array($inputData['limitedFolders']) === true
147
        && count($inputData['limitedFolders']) > 0
148
    ) {
149
        $listFoldersLimitedKeys = array_keys($inputData['limitedFolders']);
150
    } else {
151
        $listFoldersLimitedKeys = array();
152
    }
153
    
154
    // list of items accessible but not in an allowed folder
155
    if (
156
        isset($inputData['restrictedFoldersForItems']) === true
157
        && count($inputData['restrictedFoldersForItems']) > 0
158
    ) {
159
        $listRestrictedFoldersForItemsKeys = @array_keys($inputData['restrictedFoldersForItems']);
160
    } else {
161
        $listRestrictedFoldersForItemsKeys = array();
162
    }
163
    
164
    $ret_json = array();
165
    $last_visible_parent = -1;
166
    $last_visible_parent_level = 1;
167
    $nodeId = isset($inputData['nodeId']) === true && is_int($inputData['nodeId']) === true ? $inputData['nodeId'] : 0;
168
169
    // build the tree to be displayed
170
    if (showFolderToUser(
171
        $nodeId,
172
        $inputData['forbidenPfs'],
173
        $inputData['visibleFolders'],
174
        $listFoldersLimitedKeys,
175
        $listRestrictedFoldersForItemsKeys
176
    ) === true)
177
    {
178
        if ($inputData['userTreeLoadStrategy'] === 'sequential') {
179
            // SEQUENTIAL MODE
180
            $completTree = $tree->getDescendants(empty($nodeId) === true ? 0 : (int) $nodeId, false, true, false);
181
            foreach ($completTree as $child) {
182
                recursiveTree(
183
                    (int) $child->id,
184
                    $child,
185
                    /** @scrutinizer ignore-type */ $tree,
186
                    $listFoldersLimitedKeys,
187
                    $listRestrictedFoldersForItemsKeys,
188
                    $last_visible_parent,
189
                    $last_visible_parent_level,
190
                    $SETTINGS,
191
                    $inputData,
192
                    $ret_json
193
                );
194
            }
195
196
        } else {
197
            // FULL MODE
198
            $completTree = $tree->getTreeWithChildren();
199
            foreach ($completTree[0]->children as $child) {
200
                recursiveTree(
201
                    (int) $child,
202
                    $completTree[$child],
203
                    /** @scrutinizer ignore-type */ $tree,
204
                    $listFoldersLimitedKeys,
205
                    $listRestrictedFoldersForItemsKeys,
206
                    $last_visible_parent,
207
                    $last_visible_parent_level,
208
                    $SETTINGS,
209
                    $inputData,
210
                    $ret_json
211
                );
212
            }
213
        }
214
    }
215
216
    // Save in SESSION
217
    $superGlobal->put('user_tree_structure', $ret_json, 'SESSION');
218
    $superGlobal->put('user_tree_last_refresh_timestamp', time(), 'SESSION');
219
220
    $ret_json = json_encode($ret_json);
221
222
    // Save user folders tree
223
    cacheTreeUserHandler(
224
        (int) $inputData['userId'],
225
        $ret_json,
226
        $SETTINGS
227
    );
228
229
    // Send back
230
    echo $ret_json;
231
} else {
232
    echo $goTreeRefresh['data'];
233
}
234
235
236
/**
237
 * Check if user can see this folder based upon rights
238
 *
239
 * @param integer $nodeId
240
 * @param array $session_forbiden_pfs
241
 * @param array $session_groupes_visibles
242
 * @param array $listFoldersLimitedKeys
243
 * @param array $listRestrictedFoldersForItemsKeys
244
 * @return boolean
245
 */
246
function showFolderToUser(
247
    int $nodeId,
248
    array $session_forbiden_pfs,
249
    array $session_groupes_visibles,
250
    array $listFoldersLimitedKeys,
251
    array $listRestrictedFoldersForItemsKeys
252
): bool
253
{
254
    $big_array = array_diff(array_unique(array_merge($session_groupes_visibles, $listFoldersLimitedKeys, $listRestrictedFoldersForItemsKeys), SORT_NUMERIC), $session_forbiden_pfs);
255
    //print_r($session_groupes_visibles);
256
    if ($nodeId === 0 || in_array($nodeId, $big_array) === true) {
257
        return true;
258
    }
259
    return false;
260
}
261
262
263
/**
264
 * Get some infos for this node
265
 *
266
 * @param integer   $nodeId
267
 * @param integer   $nodeLevel
268
 * @param string    $nodeTitle
269
 * @param integer   $userId
270
 * @param string    $userLogin
271
 * @param bool      $userIsRO
272
 * @param array     $userPF
273
 * @return array
274
 */
275
function getNodeInfos(
276
    int $nodeId,
277
    int $nodeLevel,
278
    string $nodeTitle,
279
    int $userId,
280
    string $userLogin,
281
    bool $userIsRO,
282
    array $userPF
283
) : array
284
{
285
    $ret = [];
286
    // get count of Items in this folder
287
    DB::query(
288
        'SELECT *
289
        FROM ' . prefixTable('items') . '
290
        WHERE inactif=%i AND id_tree = %i',
291
        0,
292
        $nodeId
293
    );
294
    $ret['itemsNb'] = DB::count();
295
296
    // get info about current folder
297
    DB::query(
298
        'SELECT *
299
        FROM ' . prefixTable('nested_tree') . '
300
        WHERE parent_id = %i',
301
        $nodeId
302
    );
303
    $ret['childrenNb'] = DB::count();
304
305
    // Manage node title
306
    if ($userIsRO === true && in_array($nodeId, $userPF) === false) {
307
        // special case for READ-ONLY folder
308
        $ret['title'] = langHdl('read_only_account');
309
    } else {
310
        // If personal Folder, convert id into user name
311
        $ret['title'] = (string) $nodeTitle === (string) $userId && (int) $nodeLevel === 1 ?
312
        $userLogin :
313
        htmlspecialchars_decode($nodeTitle, ENT_QUOTES);
314
    }
315
316
    $ret['text'] = str_replace(
317
        '&',
318
        '&amp;',
319
        $ret['title']
320
    );
321
322
    return $ret;
323
}
324
325
326
/**
327
 * Get through complete tree
328
 *
329
 * @param int     $nodeId                            Id
330
 * @param stdClass   $currentNode                       Tree info
331
 * @param Tree\NestedTree\NestedTree   $tree                              The tree
332
 * @param array   $listFoldersLimitedKeys            Limited
333
 * @param array   $listRestrictedFoldersForItemsKeys Restricted
334
 * @param int     $last_visible_parent               Visible parent
335
 * @param int     $last_visible_parent_level         Parent level
336
 * @param array   $SETTINGS                          Teampass settings
337
 * @param array   $inputData,
338
 * @param array   $ret_json
339
 *
340
 * @return array
341
 */
342
function recursiveTree(
343
    int $nodeId,
344
    stdClass $currentNode,
345
    Tree\NestedTree\NestedTree $tree,
346
    array $listFoldersLimitedKeys,
347
    array $listRestrictedFoldersForItemsKeys,
348
    int $last_visible_parent,
349
    int $last_visible_parent_level,
350
    array $SETTINGS,
351
    array $inputData,
352
    array &$ret_json = array()
353
) {
354
    $text = '';
355
    $title = '';
356
    $show_but_block = false;
357
    
358
    // Load config
359
    include __DIR__.'/../includes/config/tp.config.php';
360
361
    $displayThisNode = false;
362
    $nbChildrenItems = 0;
363
    $nodeDescendants = $nodeDirectDescendants = $tree->getDescendants($nodeId, true, false, true);
364
    array_shift($nodeDirectDescendants); // get only the children
365
366
    // Check if any allowed folder is part of the descendants of this node
367
    foreach ($nodeDescendants as $node) {
368
        // manage tree counters
369
        if (
370
            isKeyExistingAndEqual('tree_counters', 1, $SETTINGS) === true
371
            && in_array(
372
                $node,
373
                array_merge(
374
                    $inputData['visibleFolders'],
375
                    is_null($inputData['restrictedFoldersForItems']) === true ? [] : $inputData['restrictedFoldersForItems']
376
                )
377
            ) === true
378
        ) {
379
            DB::query(
380
                'SELECT * FROM ' . prefixTable('items') . '
381
                WHERE inactif=%i AND id_tree = %i',
382
                0,
383
                $node
384
            );
385
            $nbChildrenItems += DB::count();
386
        }
387
388
        if (
389
            in_array($node, array_merge($inputData['personalFolders'], $inputData['visibleFolders'])) === true
390
        ) {
391
            // Final check - is PF allowed?
392
            $nodeDetails = $tree->getNode($node);
393
            if (
394
                (int) $nodeDetails->personal_folder === 1
395
                && (int) $SETTINGS['enable_pf_feature'] === 1
396
                && in_array($node, $inputData['personalFolders']) === false
397
            ) {
398
                $displayThisNode = false;
399
            } else {
400
                $displayThisNode = true;
401
                // not adding a break in order to permit a correct count of items
402
            }
403
            $text = '';
404
        }
405
    }
406
    
407
    if ($displayThisNode === true) {
408
        handleNode(
409
            (int) $nodeId,
410
            $currentNode,
411
            $tree,
412
            $listFoldersLimitedKeys,
413
            $listRestrictedFoldersForItemsKeys,
414
            $last_visible_parent,
415
            $last_visible_parent_level,
416
            $SETTINGS,
417
            $inputData,
418
            $text,
419
            $nbChildrenItems,
420
            $nodeDescendants,
421
            $nodeDirectDescendants,
422
            $ret_json
423
        );
424
    }
425
    
426
    return $ret_json;
427
}
428
429
/**
430
 * Permits to get the Node definition
431
 *
432
 * @param integer $nodeId
433
 * @param stdClass $currentNode
434
 * @param Tree\NestedTree\NestedTree $tree
435
 * @param array $listFoldersLimitedKeys
436
 * @param array $listRestrictedFoldersForItemsKeys
437
 * @param integer $last_visible_parent
438
 * @param integer $last_visible_parent_level
439
 * @param array $SETTINGS
440
 * @param array $inputData
441
 * @param string $text
442
 * @param integer $nbChildrenItems
443
 * @param array $nodeDescendants
444
 * @param array $nodeDirectDescendants
445
 * @param array $ret_json
446
 * @return void
447
 */
448
function handleNode(
449
    int $nodeId,
450
    stdClass $currentNode,
451
    Tree\NestedTree\NestedTree $tree,
452
    array $listFoldersLimitedKeys,
453
    array $listRestrictedFoldersForItemsKeys,
454
    int $last_visible_parent,
455
    int $last_visible_parent_level,
456
    array $SETTINGS,
457
    array $inputData,
458
    string $text,
459
    int $nbChildrenItems,
460
    array $nodeDescendants,
461
    array $nodeDirectDescendants,
462
    array &$ret_json = array()
463
)
464
{
465
    // get info about current folder
466
    DB::query(
467
        'SELECT * FROM ' . prefixTable('items') . '
468
        WHERE inactif=%i AND id_tree = %i',
469
        0,
470
        $nodeId
471
    );
472
    $itemsNb = DB::count();
473
474
    // If personal Folder, convert id into user name
475
    if ((int) $currentNode->title === (int) $inputData['userId'] && (int) $currentNode->nlevel === 1) {
476
        $currentNode->title = $inputData['userLogin'];
477
    }
478
479
    // Decode if needed
480
    $currentNode->title = htmlspecialchars_decode($currentNode->title, ENT_QUOTES);
481
482
    $nodeData = prepareNodeData(
483
        (int) $nodeId,
484
        $inputData['visibleFolders'],
485
        $inputData['readOnlyFolders'],
486
        $inputData['personalVisibleFolders'],
487
        (int) $nbChildrenItems,
488
        $nodeDescendants,
489
        (int) $itemsNb,
490
        $inputData['limitedFolders'],
491
        (int) $SETTINGS['show_only_accessible_folders'],
492
        $nodeDirectDescendants,
493
        isset($SETTINGS['tree_counters']) === true ? (int) $SETTINGS['tree_counters'] : 0,
494
        (bool) $inputData['userReadOnly'],
495
        $listFoldersLimitedKeys,
496
        $listRestrictedFoldersForItemsKeys,
497
        $inputData['restrictedFoldersForItems'],
498
        $inputData['personalFolders']
499
    );
500
501
    // Prepare JSON 
502
    $tmpRetArray = prepareNodeJson(
503
        $currentNode,
504
        $nodeData,
505
        $inputData,
506
        $ret_json,
507
        $last_visible_parent,
508
        $last_visible_parent_level,
509
        $nodeId,
510
        $text,
511
        $SETTINGS
512
    );    
513
    $last_visible_parent = $tmpRetArray['last_visible_parent'];
514
    $last_visible_parent_level = $tmpRetArray['last_visible_parent_level'];
515
    $ret_json = $tmpRetArray['ret_json'];
516
517
    // ensure we get the children of the folder
518
    if (isset($currentNode->children) === false) {
519
        $currentNode->children = $tree->getDescendants($nodeId, false, true, true);
520
    }
521
    if ($inputData['userTreeLoadStrategy'] === 'full' && isset($currentNode->children) === true) {
522
        foreach ($currentNode->children as $child) {
523
            recursiveTree(
524
                (int) $child,
525
                $tree->getNode($child),// get node info for this child
526
                /** @scrutinizer ignore-type */ $tree,
527
                $listFoldersLimitedKeys,
528
                $listRestrictedFoldersForItemsKeys,
529
                $last_visible_parent,
530
                $last_visible_parent_level,
531
                $SETTINGS,
532
                $inputData,
533
                $ret_json
534
            );
535
        }
536
    }
537
}
538
539
/**
540
 * Permits to prepare the node data
541
 *
542
 * @param stdClass $currentNode
543
 * @param array $nodeData
544
 * @param array $inputData
545
 * @param array $ret_json
546
 * @param integer $last_visible_parent
547
 * @param integer $last_visible_parent_level
548
 * @param integer $nodeId
549
 * @param string $text
550
 * @param array $SETTINGS
551
 * @return array
552
 */
553
function prepareNodeJson(
554
    stdClass $currentNode,
555
    array $nodeData,
556
    array $inputData,
557
    array &$ret_json,
558
    int &$last_visible_parent,
559
    int &$last_visible_parent_level,
560
    int $nodeId,
561
    string $text,
562
    array $SETTINGS
563
): array
564
{
565
    // prepare json return for current node
566
    $parent = $currentNode->parent_id === '0' ? '#' : 'li_' . $currentNode->parent_id;
567
568
    // handle displaying
569
    if (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true) {
570
        if ($nodeData['hide_node'] === true) {
571
            $last_visible_parent = (int) $parent;
572
            $last_visible_parent_level = $currentNode->nlevel--;
573
        } elseif ($currentNode->nlevel < $last_visible_parent_level) {
574
            $last_visible_parent = -1;
575
        }
576
    }
577
578
    // json
579
    if ($nodeData['hide_node'] === false && $nodeData['show_but_block'] === false) {
580
        array_push(
581
            $ret_json,
582
            array(
583
                'id' => 'li_' . $nodeId,
584
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
585
                'text' => '<i class="'.$currentNode->fa_icon.' tree-folder mr-2" data-folder="'.$currentNode->fa_icon.'"  data-folder-selected="'.$currentNode->fa_icon_selected.'"></i>'.$text.$currentNode->title.$nodeData['html'],
586
                'li_attr' => array(
587
                    'class' => 'jstreeopen',
588
                    'title' => 'ID [' . $nodeId . '] ' . $nodeData['title'],
589
                ),
590
                'a_attr' => array(
591
                    'id' => 'fld_' . $nodeId,
592
                    'class' => $nodeData['folderClass'],
593
                    'onclick' => 'ListerItems(' . $nodeId . ', ' . $nodeData['restricted'] . ', 0, 1)',
594
                    'data-title' => $currentNode->title,
595
                ),
596
                'is_pf' => in_array($nodeId, $inputData['personalFolders']) === true ? 1 : 0,
597
                'can_edit' => (int) $inputData['userCanCreateRootFolder'],
598
                //'children' => count($nodeDirectDescendants) > 0 ? true : false,
599
            )
600
        );
601
        
602
        if ($inputData['userTreeLoadStrategy'] === 'sequential') {
603
            $ret_json[count($ret_json) - 1]['children'] = count($nodeDirectDescendants) > 0 ? true : false;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $nodeDirectDescendants seems to be never defined.
Loading history...
604
        }
605
606
    } elseif ($nodeData['show_but_block'] === true) {
607
        array_push(
608
            $ret_json,
609
            array(
610
                'id' => 'li_' . $nodeId,
611
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
612
                'text' => '<i class="'.$currentNode->fa_icon.' tree-folder mr-2" data-folder="'.$currentNode->fa_icon.'"  data-folder-selected="'.$currentNode->fa_icon_selected.'"></i>'.'<i class="fas fa-times fa-xs text-danger mr-1 ml-1"></i>'.$text.$currentNode->title.$nodeData['html'],
613
                'li_attr' => array(
614
                    'class' => '',
615
                    'title' => 'ID [' . $nodeId . '] ' . langHdl('no_access'),
616
                ),
617
            )
618
        );
619
    }
620
621
    return [
622
        'last_visible_parent' => (int) $last_visible_parent,
623
        'last_visible_parent_level' => (int) $last_visible_parent_level,
624
        'ret_json' => $ret_json
625
    ];
626
}
627
628
/**
629
 * Get the context of the folder
630
 *
631
 * @param integer $nodeId
632
 * @param array $session_groupes_visibles
633
 * @param array $session_read_only_folders
634
 * @param array $session_personal_visible_groups
635
 * @param integer $nbChildrenItems
636
 * @param array $nodeDescendants
637
 * @param integer $itemsNb
638
 * @param array $session_list_folders_limited
639
 * @param integer $show_only_accessible_folders
640
 * @param array $nodeDirectDescendants
641
 * @param integer $tree_counters
642
 * @param bool $session_user_read_only
643
 * @param array $listFoldersLimitedKeys
644
 * @param array $listRestrictedFoldersForItemsKeys
645
 * @param array $session_list_restricted_folders_for_items
646
 * @param array $session_personal_folder
647
 * @return array
648
 */
649
function prepareNodeData(
650
    int $nodeId,
651
    array $session_groupes_visibles,
652
    array $session_read_only_folders,
653
    array $session_personal_visible_groups,
654
    int $nbChildrenItems,
655
    array $nodeDescendants,
656
    int $itemsNb,
657
    array $session_list_folders_limited,
658
    int $show_only_accessible_folders,
659
    array $nodeDirectDescendants,
660
    int $tree_counters,
661
    bool $session_user_read_only,
662
    array $listFoldersLimitedKeys,
663
    array $listRestrictedFoldersForItemsKeys,
664
    array $session_list_restricted_folders_for_items,
665
    array $session_personal_folder
666
): array
667
{
668
    if (in_array($nodeId, $session_groupes_visibles) === true) {
669
        // special case for READ-ONLY folder
670
        if (in_array($nodeId, $session_read_only_folders) === true) {
671
            return [
672
                '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 .
673
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
674
                'title' => langHdl('read_only_account'),
675
                'restricted' => 1,
676
                'folderClass' => 'folder_not_droppable',
677
                'show_but_block' => false,
678
                'hide_node' => false,
679
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
680
            ];
681
682
        } elseif (
683
            $session_user_read_only === true
684
            && in_array($nodeId, $session_personal_visible_groups) === false
685
        ) {
686
            return [
687
                '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 .
688
                    ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
689
                'title' => langHdl('read_only_account'),
690
                'restricted' => 0,
691
                'folderClass' => 'folder',
692
                'show_but_block' => false,
693
                'hide_node' => false,
694
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
695
            ];
696
        }
697
        
698
        return [
699
            'html' => '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $itemsNb .
700
                ($tree_counters === 1 ? '/'.$nbChildrenItems .'/'.(count($nodeDescendants) - 1)  : '') . '</span>',
701
            'title' => '',
702
            'restricted' => 0,
703
            'folderClass' => 'folder',
704
            'show_but_block' => false,
705
            'hide_node' => false,
706
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
707
        ];
708
709
    } elseif (in_array($nodeId, $listFoldersLimitedKeys) === true) {
710
        return [
711
            'html' => ($session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '') .
712
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_folders_limited[$nodeId]) . '</span>',
713
            'title' => '',
714
            'restricted' => 1,
715
            'folderClass' => 'folder',
716
            'show_but_block' => false,
717
            'hide_node' => false,
718
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
719
        ];
720
721
    } elseif (in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true) {
722
        return [
723
            'html' => $session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '' .
724
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_restricted_folders_for_items[$nodeId]) . '</span>',
725
            'title' => '',
726
            'restricted' => 1,
727
            'folderClass' => 'folder',
728
            'show_but_block' => false,
729
            'hide_node' => false,
730
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
731
        ];
732
733
    } elseif ((int) $show_only_accessible_folders === 1
734
        && (int) $nbChildrenItems === 0
735
    ) {
736
        // folder should not be visible
737
        // only if it has no descendants
738
        if (
739
            count(
740
                array_diff(
741
                    $nodeDirectDescendants,
742
                    array_merge(
743
                        $session_groupes_visibles,
744
                        array_keys($session_list_restricted_folders_for_items)
745
                    )
746
                )
747
            ) !== count($nodeDirectDescendants)
748
        ) {
749
            // show it but block it
750
            return [
751
                'html' => '',
752
                'title' => '',
753
                'restricted' => 1,
754
                'folderClass' => 'folder_not_droppable',
755
                'show_but_block' => true,
756
                'hide_node' => false,
757
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
758
            ];
759
        }
760
        
761
        // hide it
762
        return [
763
            'html' => '',
764
            'title' => '',
765
            'restricted' => 1,
766
            'folderClass' => 'folder_not_droppable',
767
            'show_but_block' => false,
768
            'hide_node' => true,
769
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
770
        ];
771
    }
772
773
    return [
774
        'html' => '',
775
        'title' => isset($title) === true ? $title : '',
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $title seems to never exist and therefore isset should always be false.
Loading history...
776
        'restricted' => 1,
777
        'folderClass' => 'folder_not_droppable',
778
        'show_but_block' => true,
779
        'hide_node' => false,
780
        'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
781
    ];
782
}
783
784
785
/**
786
 * Permits to check if we can user a cache instead of loading from DB
787
 *
788
 * @param integer $lastTreeChange
789
 * @param integer $userTreeLastRefresh
790
 * @param array $userSessionTreeStructure
791
 * @param integer $userId
792
 * @param integer $forceRefresh
793
 * @param array $SETTINGS
794
 * @return array
795
 */
796
function loadTreeStrategy(
797
    int $lastTreeChange,
798
    int $userTreeLastRefresh,
799
    array $userSessionTreeStructure,
800
    int $userId,
801
    int $forceRefresh
802
): array
803
{
804
    // Case when refresh is EXPECTED / MANDATORY
805
    if ((int) $forceRefresh === 1) {
806
        return [
807
            'state' => true,
808
            'data' => [],
809
        ];
810
    }
811
812
    // Case when an update in the tree has been done
813
    // Refresh is then mandatory
814
    if ((int) $lastTreeChange > (int) $userTreeLastRefresh) {
815
        return [
816
            'state' => true,
817
            'data' => [],
818
        ];
819
    }
820
821
    // Does this user has the tree structure in session?
822
    // If yes then use it
823
    if (count($userSessionTreeStructure) > 0) {
824
        return [
825
            'state' => false,
826
            'data' => json_encode($userSessionTreeStructure),
827
        ];
828
    }
829
830
    // Does this user has a tree cache
831
    $userCacheTree = DB::queryfirstrow(
832
        'SELECT data
833
        FROM ' . prefixTable('cache_tree') . '
834
        WHERE user_id = %i',
835
        $userId
836
    );
837
    if (empty($userCacheTree['data']) === false && $userCacheTree['data'] !== '[]') {
838
        return [
839
            'state' => false,
840
            'data' => $userCacheTree['data'],
841
        ];
842
    }
843
844
    return [
845
        'state' => true,
846
        'data' => [],
847
    ];
848
}