prepareNodeData()   D
last analyzed

Complexity

Conditions 23
Paths 30

Size

Total Lines 135
Code Lines 87

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 87
c 0
b 0
f 0
nc 30
nop 15
dl 0
loc 135
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-2025 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
use TeampassClasses\SessionManager\SessionManager;
24
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
25
use TeampassClasses\Language\Language;
26
use TeampassClasses\PerformChecks\PerformChecks;
27
use TeampassClasses\ConfigManager\ConfigManager;
28
use TeampassClasses\NestedTree\NestedTree;
29
30
// Load functions
31
require_once 'main.functions.php';
32
33
// init
34
loadClasses('DB');
35
$session = SessionManager::getSession();
36
$request = SymfonyRequest::createFromGlobals();
37
$lang = new Language($session->get('user-language') ?? 'english');
38
39
// Load config
40
$configManager = new ConfigManager();
41
$SETTINGS = $configManager->getAllSettings();
42
43
// Do checks
44
// Instantiate the class with posted data
45
$checkUserAccess = new PerformChecks(
46
    dataSanitizer(
47
        [
48
            'type' => null !== $request->request->get('type') ? htmlspecialchars($request->request->get('type')) : '',
49
        ],
50
        [
51
            'type' => 'trim|escape',
52
        ],
53
    ),
54
    [
55
        'user_id' => returnIfSet($session->get('user-id'), null),
56
        'user_key' => returnIfSet($session->get('key'), null),
57
    ]
58
);
59
// Handle the case
60
echo $checkUserAccess->caseHandler();
61
if (
62
    $checkUserAccess->userAccessPage('items') === false ||
63
    $checkUserAccess->checkSession() === false
64
) {
65
    // Not allowed page
66
    $session->set('system-error_code', ERR_NOT_ALLOWED);
67
    include $SETTINGS['cpassman_dir'] . '/error.php';
68
    exit;
69
}
70
71
// Define Timezone
72
date_default_timezone_set($SETTINGS['timezone'] ?? 'UTC');
73
74
// Set header properties
75
header('Content-type: text/html; charset=utf-8');
76
header('Cache-Control: no-cache, no-store, must-revalidate');
77
78
// --------------------------------- //
79
80
// Load tree
81
$tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
82
83
// Prepare sanitization
84
$data = [
85
    'forbidenPfs' => null !== $session->get('user-forbiden_personal_folders') ? json_encode($session->get('user-forbiden_personal_folders')) : '{}',
86
    'visibleFolders' => null !== $session->get('user-accessible_folders') ? json_encode($session->get('user-accessible_folders')) : '{}',
87
    'userId' => null !== $session->get('user-id') ? $session->get('user-id') : '',
88
    'userLogin' => null !== $session->get('user-login') ? $session->get('user-login') : '',
89
    'userReadOnly' => null !== $session->get('user-read_only') ? $session->get('user-read_only') : '',
90
    'limitedFolders' => null !== $session->get('user-list_folders_limited') ? json_encode($session->get('user-list_folders_limited')) : '{}',
91
    'readOnlyFolders' => null !== $session->get('user-read_only_folders') ? json_encode($session->get('user-read_only_folders')) : '{}',
92
    'personalVisibleFolders' => null !== $session->get('user-personal_visible_folders') ? json_encode($session->get('user-personal_visible_folders')) : '{}',
93
    'userTreeLastRefresh' => null !== $session->get('user-tree_last_refresh_timestamp') ? $session->get('user-tree_last_refresh_timestamp') : '',
94
    'forceRefresh' => null !== $request->query->get('force_refresh') ? $request->query->get('force_refresh') : '',
95
    'nodeId' => null !== $request->query->get('id') ? $request->query->get('id') : '',
96
    'restrictedFoldersForItems' => null !== $request->query->get('list_restricted_folders_for_items') ? json_encode($request->query->get('list_restricted_folders_for_items')) : '{}',
97
    'noAccessFolders' => null !== $session->get('user-no_access_folders') ? json_encode($session->get('user-no_access_folders')) : '{}',
98
    'personalFolders' => null !== $session->get('user-personal_folders') ? json_encode($session->get('user-personal_folders')) : '{}',
99
    'userCanCreateRootFolder' => null !== $session->get('user-can_create_root_folder') ? json_encode($session->get('user-can_create_root_folder')) : '{}',
100
    'userTreeLoadStrategy' => null !== $session->get('user-tree_load_strategy') ? $session->get('user-tree_load_strategy') : '',
101
];
102
103
$filters = [
104
    'forbidenPfs' => 'cast:array',
105
    'visibleFolders' => 'cast:array',
106
    'userId' => 'cast:integer',
107
    'userLogin' => 'trim|escape',
108
    'userReadOnly' => 'cast:boolean',
109
    'limitedFolders' => 'cast:array',
110
    'readOnlyFolders' => 'cast:array',
111
    'personalVisibleFolders' => 'cast:array',
112
    'userTreeLastRefresh' => 'cast:integer',
113
    'forceRefresh' => 'cast:integer',
114
    'nodeId' => 'cast:integer',
115
    'restrictedFoldersForItems' => 'cast:array',
116
    'noAccessFolders' => 'cast:array',
117
    'personalFolders' => 'cast:array',
118
    'userCanCreateRootFolder' => 'cast:array',
119
    'userTreeLoadStrategy' => 'trim|escape',
120
];
121
122
$inputData = dataSanitizer(
123
    $data,
124
    $filters
125
);
126
127
$lastFolderChange = DB::queryFirstRow(
128
    'SELECT valeur FROM ' . prefixTable('misc') . '
129
    WHERE type = %s AND intitule = %s',
130
    'timestamp',
131
    'last_folder_change'
132
);
133
if (DB::count() === 0) {
134
    $lastFolderChange['valeur'] = 0;
135
}
136
137
// Should we use a cache or refresh the tree
138
$goTreeRefresh = loadTreeStrategy(
139
    (int) $lastFolderChange['valeur'],
140
    (int) $inputData['userTreeLastRefresh'],
141
    (null === $session->get('user-tree_structure') || empty($session->get('user-tree_structure')) === true) ? [] : $session->get('user-tree_structure'),
142
    (int) $inputData['userId'],
143
    (int) $inputData['forceRefresh']
144
);
145
// We don't use the cache if an ID of folder is provided
146
if ($goTreeRefresh['state'] === true || empty($inputData['nodeId']) === false || $inputData['userTreeLoadStrategy'] === 'sequential') {
147
    // Build tree
148
    $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
149
150
    if (
151
        isset($inputData['limitedFolders']) === true
152
        && is_array($inputData['limitedFolders']) === true
153
        && count($inputData['limitedFolders']) > 0
154
    ) {
155
        $listFoldersLimitedKeys = array_keys($inputData['limitedFolders']);
156
    } else {
157
        $listFoldersLimitedKeys = array();
158
    }
159
    
160
    // list of items accessible but not in an allowed folder
161
    if (
162
        isset($inputData['restrictedFoldersForItems']) === true
163
        && count($inputData['restrictedFoldersForItems']) > 0
164
    ) {
165
        $listRestrictedFoldersForItemsKeys = @array_keys($inputData['restrictedFoldersForItems']);
166
    } else {
167
        $listRestrictedFoldersForItemsKeys = array();
168
    }
169
    
170
    $ret_json = array();
171
    $last_visible_parent = -1;
172
    $last_visible_parent_level = 1;
173
    $nodeId = isset($inputData['nodeId']) === true && is_int($inputData['nodeId']) === true ? $inputData['nodeId'] : 0;
174
175
    // build the tree to be displayed
176
    if (showFolderToUser(
177
        $nodeId,
178
        $inputData['forbidenPfs'],
179
        $inputData['visibleFolders'],
180
        $listFoldersLimitedKeys,
181
        $listRestrictedFoldersForItemsKeys
182
    ) === true)
183
    {
184
        // Note: Condition with sequential/full option has been removed (see #4900)
185
        $completTree = $tree->getTreeWithChildren();
186
        foreach ($completTree[0]->children as $child) {
187
            recursiveTree(
188
                (int) $child,
189
                $completTree[$child],
190
                /** @scrutinizer ignore-type */ $tree,
191
                $listFoldersLimitedKeys,
192
                $listRestrictedFoldersForItemsKeys,
193
                $last_visible_parent,
194
                $last_visible_parent_level,
195
                $SETTINGS,
196
                $inputData,
197
                $ret_json
198
            );
199
        }
200
    }
201
202
    // Save in SESSION
203
    $session->set('user-tree_structure', $ret_json);
204
    $session->set('user-tree_last_refresh_timestamp', time());
205
206
    $ret_json = json_encode($ret_json);
207
208
    // Save user folders tree
209
    cacheTreeUserHandler(
210
        (int) $inputData['userId'],
211
        $ret_json,
212
        $SETTINGS
213
    );
214
215
    // Add new process
216
    DB::insert(
217
        prefixTable('background_tasks'),
218
        array(
219
            'created_at' => time(),
220
            'process_type' => 'user_build_cache_tree',
221
            'arguments' => json_encode([
222
                'user_id' => (int) $inputData['userId'],
223
            ], JSON_HEX_QUOT | JSON_HEX_TAG),
224
            'updated_at' => null,
225
            'finished_at' => null,
226
            'output' => null,
227
        )
228
    );
229
230
    // Send back
231
    echo $ret_json;
232
} else {
233
    echo $goTreeRefresh['data'];
234
}
235
236
237
/**
238
 * Check if user can see this folder based upon rights
239
 *
240
 * @param integer $nodeId
241
 * @param array $session_forbiden_pfs
242
 * @param array $session_groupes_visibles
243
 * @param array $listFoldersLimitedKeys
244
 * @param array $listRestrictedFoldersForItemsKeys
245
 * @return boolean
246
 */
247
function showFolderToUser(
248
    int $nodeId,
249
    array $session_forbiden_pfs,
250
    array $session_groupes_visibles,
251
    array $listFoldersLimitedKeys,
252
    array $listRestrictedFoldersForItemsKeys
253
): bool
254
{
255
    $big_array = array_diff(
256
        array_unique(
257
            array_merge(
258
                $session_groupes_visibles, 
259
                $listFoldersLimitedKeys, 
260
                $listRestrictedFoldersForItemsKeys
261
            ), 
262
            SORT_NUMERIC
263
        ), 
264
        $session_forbiden_pfs
265
    );
266
    if ($nodeId === 0 || in_array($nodeId, $big_array) === true) {
267
        return true;
268
    }
269
    return false;
270
}
271
272
273
274
/**
275
 * Get through complete tree
276
 *
277
 * @param int     $nodeId                            Id
278
 * @param stdClass   $currentNode                       Tree info
279
 * @param NestedTree   $tree                              The tree
280
 * @param array   $listFoldersLimitedKeys            Limited
281
 * @param array   $listRestrictedFoldersForItemsKeys Restricted
282
 * @param int     $last_visible_parent               Visible parent
283
 * @param int     $last_visible_parent_level         Parent level
284
 * @param array   $SETTINGS                          Teampass settings
285
 * @param array   $inputData,
286
 * @param array   $ret_json
287
 *
288
 * @return array
289
 */
290
function recursiveTree(
291
    int $nodeId,
292
    stdClass $currentNode,
293
    NestedTree $tree,
294
    array $listFoldersLimitedKeys,
295
    array $listRestrictedFoldersForItemsKeys,
296
    int $last_visible_parent,
297
    int $last_visible_parent_level,
298
    array $SETTINGS,
299
    array $inputData,
300
    array &$ret_json = array()
301
) {
302
    // Initialize variables
303
    $text = '';    
304
    $displayThisNode = false;
305
    $nbItemsInSubfolders = $nbSubfolders = $nbItemsInFolder = 0;
306
    $nodeDescendants = $tree->getDescendants($nodeId, true, false, false);
307
    // On combine les tableaux une seule fois pour optimiser
308
    $allowedFolders = array_merge($inputData['personalFolders'], $inputData['visibleFolders']);
309
    
310
    foreach ($nodeDescendants as $node) {
311
        if (!in_array($node->id, $allowedFolders)) {
312
            continue;
313
        }
314
315
        // If it is a personal folder, we check the specific conditions
316
        if (
317
            (int) $node->personal_folder === 1 
318
            && (int) $SETTINGS['enable_pf_feature'] === 1 
319
            && !in_array($node->id, $inputData['personalFolders'])
320
        ) {
321
            continue;
322
        }
323
        
324
        // If we are here, the node must be displayed
325
        $displayThisNode = true;
326
        $nbItemsInSubfolders = (int) $node->nb_items_in_subfolders;
327
        $nbItemsInFolder = (int) $node->nb_items_in_folder;
328
        $nbSubfolders = (int) $node->nb_subfolders;
329
        break;  // Get out as soon as we find a valid node.
330
    }
331
    
332
    if ($displayThisNode === true) {
333
        handleNode(
334
            (int) $nodeId,
335
            $currentNode,
336
            $tree,
337
            $listFoldersLimitedKeys,
338
            $listRestrictedFoldersForItemsKeys,
339
            $last_visible_parent,
340
            $last_visible_parent_level,
341
            $SETTINGS,
342
            $inputData,
343
            $text,
344
            $nbItemsInSubfolders,
345
            $nbSubfolders,
346
            $nbItemsInFolder,
347
            $ret_json
348
        );
349
    }
350
    
351
    return $ret_json;
352
}
353
354
/**
355
 * Permits to get the Node definition
356
 *
357
 * @param integer $nodeId
358
 * @param stdClass $currentNode
359
 * @param NestedTree $tree
360
 * @param array $listFoldersLimitedKeys
361
 * @param array $listRestrictedFoldersForItemsKeys
362
 * @param integer $last_visible_parent
363
 * @param integer $last_visible_parent_level
364
 * @param array $SETTINGS
365
 * @param array $inputData
366
 * @param string $text
367
 * @param integer $nbItemsInSubfolders
368
 * @param integer $nbSubfolders
369
 * @param integer $nbItemsInFolder
370
 * @param array $ret_json
371
 * @return void
372
 */
373
function handleNode(
374
    int $nodeId,
375
    stdClass $currentNode,
376
    NestedTree $tree,
377
    array $listFoldersLimitedKeys,
378
    array $listRestrictedFoldersForItemsKeys,
379
    int $last_visible_parent,
380
    int $last_visible_parent_level,
381
    array $SETTINGS,
382
    array $inputData,
383
    string $text,
384
    int $nbItemsInSubfolders,
385
    int $nbSubfolders,
386
    int $nbItemsInFolder,
387
    array &$ret_json = array()
388
)
389
{
390
    // If personal Folder, convert id into user name
391
    if ((int) $currentNode->title === (int) $inputData['userId'] && (int) $currentNode->nlevel === 1) {
392
        $currentNode->title = $inputData['userLogin'];
393
    }
394
395
    // Decode if needed
396
    $currentNode->title = htmlspecialchars_decode($currentNode->title, ENT_QUOTES);
397
398
    $nodeData = prepareNodeData(
399
        (int) $nodeId,
400
        $inputData['visibleFolders'],
401
        $inputData['readOnlyFolders'],
402
        $inputData['personalVisibleFolders'],
403
        (int) $nbItemsInFolder,
404
        (int) $nbItemsInSubfolders,
405
        (int) $nbSubfolders,
406
        $inputData['limitedFolders'],
407
        isset($SETTINGS['tree_counters']) === true && isset($SETTINGS['enable_tasks_manager']) === true && (int) $SETTINGS['enable_tasks_manager'] === 1 && (int) $SETTINGS['tree_counters'] === 1 ? 1 : 0,
408
        (bool) $inputData['userReadOnly'],
409
        $listFoldersLimitedKeys,
410
        $listRestrictedFoldersForItemsKeys,
411
        $inputData['restrictedFoldersForItems'],
412
        $inputData['personalFolders'],
413
        $tree
414
    );
415
416
    // Prepare JSON 
417
    $tmpRetArray = prepareNodeJson(
418
        $currentNode,
419
        $nodeData,
420
        $inputData,
421
        $ret_json,
422
        $last_visible_parent,
423
        $last_visible_parent_level,
424
        $nodeId,
425
        $text,
426
        $nbSubfolders,
427
        $SETTINGS
428
    );    
429
    $last_visible_parent = $tmpRetArray['last_visible_parent'];
430
    $last_visible_parent_level = $tmpRetArray['last_visible_parent_level'];
431
    $ret_json = $tmpRetArray['ret_json'];
432
433
    // ensure we get the children of the folder
434
    if (isset($currentNode->children) === false) {
435
        $currentNode->children = $tree->getDescendants($nodeId, false, true, true);
436
    }
437
    if ($inputData['userTreeLoadStrategy'] === 'full' && isset($currentNode->children) === true) {
438
        foreach ($currentNode->children as $child) {
439
            recursiveTree(
440
                (int) $child,
441
                $tree->getNode($child),// get node info for this child
442
                /** @scrutinizer ignore-type */ $tree,
443
                $listFoldersLimitedKeys,
444
                $listRestrictedFoldersForItemsKeys,
445
                $last_visible_parent,
446
                $last_visible_parent_level,
447
                $SETTINGS,
448
                $inputData,
449
                $ret_json
450
            );
451
        }
452
    }
453
}
454
455
/**
456
 * Permits to prepare the node data
457
 *
458
 * @param stdClass $currentNode
459
 * @param array $nodeData
460
 * @param array $inputData
461
 * @param array $ret_json
462
 * @param integer $last_visible_parent
463
 * @param integer $last_visible_parent_level
464
 * @param integer $nodeId
465
 * @param string $text
466
 * @param integer $nbSubfolders
467
 * @param array $SETTINGS
468
 * @return array
469
 */
470
function prepareNodeJson(
471
    stdClass $currentNode,
472
    array $nodeData,
473
    array $inputData,
474
    array &$ret_json,
475
    int &$last_visible_parent,
476
    int &$last_visible_parent_level,
477
    int $nodeId,
478
    string $text,
479
    int $nbSubfolders,
480
    array $SETTINGS
481
): array
482
{
483
    $session = SessionManager::getSession();
484
    // Load user's language
485
    $lang = new Language($session->get('user-language') ?? 'english');
486
487
    // prepare json return for current node
488
    $parent = $currentNode->parent_id === '0' ? '#' : 'li_' . $currentNode->parent_id;
489
490
    // handle displaying
491
    if (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true) {
492
        if ($nodeData['hide_node'] === true) {
493
            $last_visible_parent = (int) $parent;
494
            $last_visible_parent_level = $currentNode->nlevel--;
495
        } elseif ($currentNode->nlevel < $last_visible_parent_level) {
496
            $last_visible_parent = -1;
497
        }
498
    }
499
500
    // json
501
    if ($nodeData['hide_node'] === false && $nodeData['show_but_block'] === false) {
502
        array_push(
503
            $ret_json,
504
            array(
505
                'id' => 'li_' . $nodeId,
506
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
507
                'text' => '<i class="'.$currentNode->fa_icon.' tree-folder mr-2" data-folder="'.$currentNode->fa_icon.'"  data-folder-selected="'.$currentNode->fa_icon_selected.'"></i>'.$text.htmlspecialchars($currentNode->title).$nodeData['html'],
508
                'li_attr' => array(
509
                    'class' => 'jstreeopen',
510
                    'title' => 'ID [' . $nodeId . '] ' . $nodeData['title'],
511
                ),
512
                'a_attr' => array(
513
                    'id' => 'fld_' . $nodeId,
514
                    'class' => $nodeData['folderClass'],
515
                    'onclick' => 'ListerItems(' . $nodeId . ', ' . $nodeData['restricted'] . ', 0, 1)',
516
                    'data-title' => htmlspecialchars($currentNode->title),
517
                ),
518
                'is_pf' => in_array($nodeId, $inputData['personalFolders']) === true ? 1 : 0,
519
                'can_edit' => (int) $inputData['userCanCreateRootFolder'],
520
            )
521
        );
522
        
523
        if ($inputData['userTreeLoadStrategy'] === 'sequential') {
524
            $ret_json[count($ret_json) - 1]['children'] = $nbSubfolders > 0 ? true : false;
525
        }
526
527
    } elseif ($nodeData['show_but_block'] === true) {
528
        array_push(
529
            $ret_json,
530
            array(
531
                'id' => 'li_' . $nodeId,
532
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
533
                '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.htmlspecialchars($currentNode->title).$nodeData['html'],
534
                'li_attr' => array(
535
                    'class' => '',
536
                    'title' => 'ID [' . $nodeId . '] ' . $lang->get('no_access'),
537
                ),
538
            )
539
        );
540
    }
541
542
    return [
543
        'last_visible_parent' => (int) $last_visible_parent,
544
        'last_visible_parent_level' => (int) $last_visible_parent_level,
545
        'ret_json' => $ret_json
546
    ];
547
}
548
549
/**
550
 * Get the context of the folder
551
 *
552
 * @param integer $nodeId
553
 * @param array $session_groupes_visibles
554
 * @param array $session_read_only_folders
555
 * @param array $session_personal_visible_groups
556
 * @param integer $nbItemsInFolder
557
 * @param integer $nbItemsInSubfolders
558
 * @param integer $nbSubfolders
559
 * @param array $session_list_folders_limited
560
 * @param integer $tree_counters
561
 * @param bool $session_user_read_only
562
 * @param array $listFoldersLimitedKeys
563
 * @param array $listRestrictedFoldersForItemsKeys
564
 * @param array $session_list_restricted_folders_for_items
565
 * @param array $session_personal_folder
566
 * @param NestedTree $tree
567
 * @return array
568
 */
569
function prepareNodeData(
570
    int $nodeId,
571
    array $session_groupes_visibles,
572
    array $session_read_only_folders,
573
    array $session_personal_visible_groups,
574
    int $nbItemsInFolder,
575
    int $nbItemsInSubfolders,
576
    int $nbSubfolders,
577
    array $session_list_folders_limited,
578
    int $tree_counters,
579
    bool $session_user_read_only,
580
    array $listFoldersLimitedKeys,
581
    array $listRestrictedFoldersForItemsKeys,
582
    array $session_list_restricted_folders_for_items,
583
    array $session_personal_folder,
584
    NestedTree $tree
585
): array
586
{
587
    $session = SessionManager::getSession();
588
    // Load user's language
589
    $lang = new Language($session->get('user-language') ?? 'english');
590
591
    if (in_array($nodeId, $session_groupes_visibles) === true) {
592
        // special case for READ-ONLY folder
593
        if (in_array($nodeId, $session_read_only_folders) === true) {
594
            return [
595
                'html' => '<i class="far fa-eye fa-xs mr-1 ml-1"></i>'.
596
                    ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
597
                'title' => $lang->get('read_only_account'),
598
                'restricted' => 1,
599
                'folderClass' => 'folder_not_droppable',
600
                'show_but_block' => false,
601
                'hide_node' => false,
602
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
603
            ];
604
605
        } elseif (
606
            $session_user_read_only === true
607
            && in_array($nodeId, $session_personal_visible_groups) === false
608
        ) {
609
            return [
610
                'html' => '<i class="far fa-eye fa-xs mr-1"></i>'.
611
                    ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
612
                'title' => $lang->get('read_only_account'),
613
                'restricted' => 0,
614
                'folderClass' => 'folder',
615
                'show_but_block' => false,
616
                'hide_node' => false,
617
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
618
            ];
619
        }
620
        
621
        return [
622
            'html' => ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
623
            'title' => '',
624
            'restricted' => 0,
625
            'folderClass' => 'folder',
626
            'show_but_block' => false,
627
            'hide_node' => false,
628
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
629
        ];
630
631
    } elseif (in_array($nodeId, $listFoldersLimitedKeys) === true) {
632
        return [
633
            'html' => ($session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '') .
634
                ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_folders_limited[$nodeId]) . '</span>' : ''),
635
            'title' => '',
636
            'restricted' => 1,
637
            'folderClass' => 'folder',
638
            'show_but_block' => false,
639
            'hide_node' => false,
640
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
641
        ];
642
643
    } elseif (in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true) {
644
        return [
645
            'html' => $session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '' .
646
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_restricted_folders_for_items[$nodeId]) . '</span>',
647
            'title' => '',
648
            'restricted' => 1,
649
            'folderClass' => 'folder',
650
            'show_but_block' => false,
651
            'hide_node' => false,
652
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
653
        ];
654
655
    } elseif ((int) $nbSubfolders === 0
656
        //&& (int) $show_only_accessible_folders === 1
657
    ) {
658
        // folder should not be visible
659
        // only if it has no descendants
660
        $nodeDirectDescendants = $tree->getDescendants($nodeId, false, false, true);
661
        if (
662
            count(
663
                array_diff(
664
                    $nodeDirectDescendants,
665
                    array_merge(
666
                        $session_groupes_visibles,
667
                        array_keys($session_list_restricted_folders_for_items)
668
                    )
669
                )
670
            ) !== count($nodeDirectDescendants)
671
        ) {
672
            // show it but block it
673
            return [
674
                'html' => '',
675
                'title' => '',
676
                'restricted' => 1,
677
                'folderClass' => 'folder_not_droppable',
678
                'show_but_block' => true,
679
                'hide_node' => false,
680
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
681
            ];
682
        }
683
        
684
        // hide it
685
        return [
686
            'html' => '',
687
            'title' => '',
688
            'restricted' => 1,
689
            'folderClass' => 'folder_not_droppable',
690
            'show_but_block' => false,
691
            'hide_node' => true,
692
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
693
        ];
694
    }
695
696
    return [
697
        'html' => '',
698
        'title' => '',
699
        'restricted' => 1,
700
        'folderClass' => 'folder_not_droppable',
701
        'show_but_block' => true,
702
        'hide_node' => false,
703
        'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
704
    ];
705
}
706
707
708
/**
709
 * Permits to check if we can user a cache instead of loading from DB
710
 *
711
 * @param integer $lastTreeChange
712
 * @param integer $userTreeLastRefresh
713
 * @param array $userSessionTreeStructure
714
 * @param integer $userId
715
 * @param integer $forceRefresh
716
 * @param array $SETTINGS
717
 * @return array
718
 */
719
function loadTreeStrategy(
720
    int $lastTreeChange,
721
    int $userTreeLastRefresh,
722
    array $userSessionTreeStructure,
723
    int $userId,
724
    int $forceRefresh
725
): array
726
{
727
    // Case when refresh is EXPECTED / MANDATORY
728
    if ((int) $forceRefresh === 1) {
729
        return [
730
            'state' => true,
731
            'data' => [],
732
        ];
733
    }
734
735
    // Case when an update in the tree has been done
736
    // Refresh is then mandatory
737
    if ((int) $lastTreeChange > (int) $userTreeLastRefresh) {
738
        return [
739
            'state' => true,
740
            'data' => [],
741
        ];
742
    }
743
744
    // Does this user has the tree structure in session?
745
    // If yes then use it
746
    if (count($userSessionTreeStructure) > 0) {
747
        return [
748
            'state' => false,
749
            'data' => json_encode($userSessionTreeStructure),
750
        ];
751
    }
752
753
    // Does this user has a tree cache
754
    $userCacheTree = DB::queryFirstRow(
755
        'SELECT data
756
        FROM ' . prefixTable('cache_tree') . '
757
        WHERE user_id = %i',
758
        $userId
759
    );
760
    if (empty($userCacheTree['data']) === false && $userCacheTree['data'] !== '[]') {
761
        return [
762
            'state' => false,
763
            'data' => $userCacheTree['data'],
764
        ];
765
    }
766
767
    return [
768
        'state' => true,
769
        'data' => [],
770
    ];
771
}