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
        if ($inputData['userTreeLoadStrategy'] === 'sequential') {
185
            // SEQUENTIAL MODE
186
            $completTree = $tree->getDescendants(empty($nodeId) === true ? 0 : (int) $nodeId, false, true, false);
187
            foreach ($completTree as $child) {
188
                recursiveTree(
189
                    (int) $child->id,
190
                    $child,
191
                    /** @scrutinizer ignore-type */ $tree,
192
                    $listFoldersLimitedKeys,
193
                    $listRestrictedFoldersForItemsKeys,
194
                    $last_visible_parent,
195
                    $last_visible_parent_level,
196
                    $SETTINGS,
197
                    $inputData,
198
                    $ret_json
199
                );
200
            }
201
202
        } else {
203
            // FULL MODE
204
            $completTree = $tree->getTreeWithChildren();
205
            foreach ($completTree[0]->children as $child) {
206
                recursiveTree(
207
                    (int) $child,
208
                    $completTree[$child],
209
                    /** @scrutinizer ignore-type */ $tree,
210
                    $listFoldersLimitedKeys,
211
                    $listRestrictedFoldersForItemsKeys,
212
                    $last_visible_parent,
213
                    $last_visible_parent_level,
214
                    $SETTINGS,
215
                    $inputData,
216
                    $ret_json
217
                );
218
            }
219
        }
220
    }
221
222
    // Save in SESSION
223
    $session->set('user-tree_structure', $ret_json);
224
    $session->set('user-tree_last_refresh_timestamp', time());
225
226
    $ret_json = json_encode($ret_json);
227
228
    // Save user folders tree
229
    cacheTreeUserHandler(
230
        (int) $inputData['userId'],
231
        $ret_json,
232
        $SETTINGS
233
    );
234
235
    // Add new process
236
    DB::insert(
237
        prefixTable('background_tasks'),
238
        array(
239
            'created_at' => time(),
240
            'process_type' => 'user_build_cache_tree',
241
            'arguments' => json_encode([
242
                'user_id' => (int) $inputData['userId'],
243
            ], JSON_HEX_QUOT | JSON_HEX_TAG),
244
            'updated_at' => null,
245
            'finished_at' => null,
246
            'output' => null,
247
        )
248
    );
249
250
    // Send back
251
    echo $ret_json;
252
} else {
253
    echo $goTreeRefresh['data'];
254
}
255
256
257
/**
258
 * Check if user can see this folder based upon rights
259
 *
260
 * @param integer $nodeId
261
 * @param array $session_forbiden_pfs
262
 * @param array $session_groupes_visibles
263
 * @param array $listFoldersLimitedKeys
264
 * @param array $listRestrictedFoldersForItemsKeys
265
 * @return boolean
266
 */
267
function showFolderToUser(
268
    int $nodeId,
269
    array $session_forbiden_pfs,
270
    array $session_groupes_visibles,
271
    array $listFoldersLimitedKeys,
272
    array $listRestrictedFoldersForItemsKeys
273
): bool
274
{
275
    $big_array = array_diff(
276
        array_unique(
277
            array_merge(
278
                $session_groupes_visibles, 
279
                $listFoldersLimitedKeys, 
280
                $listRestrictedFoldersForItemsKeys
281
            ), 
282
            SORT_NUMERIC
283
        ), 
284
        $session_forbiden_pfs
285
    );
286
    if ($nodeId === 0 || in_array($nodeId, $big_array) === true) {
287
        return true;
288
    }
289
    return false;
290
}
291
292
293
294
/**
295
 * Get through complete tree
296
 *
297
 * @param int     $nodeId                            Id
298
 * @param stdClass   $currentNode                       Tree info
299
 * @param NestedTree   $tree                              The tree
300
 * @param array   $listFoldersLimitedKeys            Limited
301
 * @param array   $listRestrictedFoldersForItemsKeys Restricted
302
 * @param int     $last_visible_parent               Visible parent
303
 * @param int     $last_visible_parent_level         Parent level
304
 * @param array   $SETTINGS                          Teampass settings
305
 * @param array   $inputData,
306
 * @param array   $ret_json
307
 *
308
 * @return array
309
 */
310
function recursiveTree(
311
    int $nodeId,
312
    stdClass $currentNode,
313
    NestedTree $tree,
314
    array $listFoldersLimitedKeys,
315
    array $listRestrictedFoldersForItemsKeys,
316
    int $last_visible_parent,
317
    int $last_visible_parent_level,
318
    array $SETTINGS,
319
    array $inputData,
320
    array &$ret_json = array()
321
) {
322
    // Initialize variables
323
    $text = '';    
324
    $displayThisNode = false;
325
    $nbItemsInSubfolders = $nbSubfolders = $nbItemsInFolder = 0;
326
    $nodeDescendants = $tree->getDescendants($nodeId, true, false, false);
327
    // On combine les tableaux une seule fois pour optimiser
328
    $allowedFolders = array_merge($inputData['personalFolders'], $inputData['visibleFolders']);
329
    
330
    foreach ($nodeDescendants as $node) {
331
        if (!in_array($node->id, $allowedFolders)) {
332
            continue;
333
        }
334
335
        // If it is a personal folder, we check the specific conditions
336
        if (
337
            (int) $node->personal_folder === 1 
338
            && (int) $SETTINGS['enable_pf_feature'] === 1 
339
            && !in_array($node->id, $inputData['personalFolders'])
340
        ) {
341
            continue;
342
        }
343
        
344
        // If we are here, the node must be displayed
345
        $displayThisNode = true;
346
        $nbItemsInSubfolders = (int) $node->nb_items_in_subfolders;
347
        $nbItemsInFolder = (int) $node->nb_items_in_folder;
348
        $nbSubfolders = (int) $node->nb_subfolders;
349
        break;  // Get out as soon as we find a valid node.
350
    }
351
    
352
    if ($displayThisNode === true) {
353
        handleNode(
354
            (int) $nodeId,
355
            $currentNode,
356
            $tree,
357
            $listFoldersLimitedKeys,
358
            $listRestrictedFoldersForItemsKeys,
359
            $last_visible_parent,
360
            $last_visible_parent_level,
361
            $SETTINGS,
362
            $inputData,
363
            $text,
364
            $nbItemsInSubfolders,
365
            $nbSubfolders,
366
            $nbItemsInFolder,
367
            $ret_json
368
        );
369
    }
370
    
371
    return $ret_json;
372
}
373
374
/**
375
 * Permits to get the Node definition
376
 *
377
 * @param integer $nodeId
378
 * @param stdClass $currentNode
379
 * @param NestedTree $tree
380
 * @param array $listFoldersLimitedKeys
381
 * @param array $listRestrictedFoldersForItemsKeys
382
 * @param integer $last_visible_parent
383
 * @param integer $last_visible_parent_level
384
 * @param array $SETTINGS
385
 * @param array $inputData
386
 * @param string $text
387
 * @param integer $nbItemsInSubfolders
388
 * @param integer $nbSubfolders
389
 * @param integer $nbItemsInFolder
390
 * @param array $ret_json
391
 * @return void
392
 */
393
function handleNode(
394
    int $nodeId,
395
    stdClass $currentNode,
396
    NestedTree $tree,
397
    array $listFoldersLimitedKeys,
398
    array $listRestrictedFoldersForItemsKeys,
399
    int $last_visible_parent,
400
    int $last_visible_parent_level,
401
    array $SETTINGS,
402
    array $inputData,
403
    string $text,
404
    int $nbItemsInSubfolders,
405
    int $nbSubfolders,
406
    int $nbItemsInFolder,
407
    array &$ret_json = array()
408
)
409
{
410
    // If personal Folder, convert id into user name
411
    if ((int) $currentNode->title === (int) $inputData['userId'] && (int) $currentNode->nlevel === 1) {
412
        $currentNode->title = $inputData['userLogin'];
413
    }
414
415
    // Decode if needed
416
    $currentNode->title = htmlspecialchars_decode($currentNode->title, ENT_QUOTES);
417
418
    $nodeData = prepareNodeData(
419
        (int) $nodeId,
420
        $inputData['visibleFolders'],
421
        $inputData['readOnlyFolders'],
422
        $inputData['personalVisibleFolders'],
423
        (int) $nbItemsInFolder,
424
        (int) $nbItemsInSubfolders,
425
        (int) $nbSubfolders,
426
        $inputData['limitedFolders'],
427
        isset($SETTINGS['tree_counters']) === true && isset($SETTINGS['enable_tasks_manager']) === true && (int) $SETTINGS['enable_tasks_manager'] === 1 && (int) $SETTINGS['tree_counters'] === 1 ? 1 : 0,
428
        (bool) $inputData['userReadOnly'],
429
        $listFoldersLimitedKeys,
430
        $listRestrictedFoldersForItemsKeys,
431
        $inputData['restrictedFoldersForItems'],
432
        $inputData['personalFolders'],
433
        $tree
434
    );
435
436
    // Prepare JSON 
437
    $tmpRetArray = prepareNodeJson(
438
        $currentNode,
439
        $nodeData,
440
        $inputData,
441
        $ret_json,
442
        $last_visible_parent,
443
        $last_visible_parent_level,
444
        $nodeId,
445
        $text,
446
        $nbSubfolders,
447
        $SETTINGS
448
    );    
449
    $last_visible_parent = $tmpRetArray['last_visible_parent'];
450
    $last_visible_parent_level = $tmpRetArray['last_visible_parent_level'];
451
    $ret_json = $tmpRetArray['ret_json'];
452
453
    // ensure we get the children of the folder
454
    if (isset($currentNode->children) === false) {
455
        $currentNode->children = $tree->getDescendants($nodeId, false, true, true);
456
    }
457
    if ($inputData['userTreeLoadStrategy'] === 'full' && isset($currentNode->children) === true) {
458
        foreach ($currentNode->children as $child) {
459
            recursiveTree(
460
                (int) $child,
461
                $tree->getNode($child),// get node info for this child
462
                /** @scrutinizer ignore-type */ $tree,
463
                $listFoldersLimitedKeys,
464
                $listRestrictedFoldersForItemsKeys,
465
                $last_visible_parent,
466
                $last_visible_parent_level,
467
                $SETTINGS,
468
                $inputData,
469
                $ret_json
470
            );
471
        }
472
    }
473
}
474
475
/**
476
 * Permits to prepare the node data
477
 *
478
 * @param stdClass $currentNode
479
 * @param array $nodeData
480
 * @param array $inputData
481
 * @param array $ret_json
482
 * @param integer $last_visible_parent
483
 * @param integer $last_visible_parent_level
484
 * @param integer $nodeId
485
 * @param string $text
486
 * @param integer $nbSubfolders
487
 * @param array $SETTINGS
488
 * @return array
489
 */
490
function prepareNodeJson(
491
    stdClass $currentNode,
492
    array $nodeData,
493
    array $inputData,
494
    array &$ret_json,
495
    int &$last_visible_parent,
496
    int &$last_visible_parent_level,
497
    int $nodeId,
498
    string $text,
499
    int $nbSubfolders,
500
    array $SETTINGS
501
): array
502
{
503
    $session = SessionManager::getSession();
504
    // Load user's language
505
    $lang = new Language($session->get('user-language') ?? 'english');
506
507
    // prepare json return for current node
508
    $parent = $currentNode->parent_id === '0' ? '#' : 'li_' . $currentNode->parent_id;
509
510
    // handle displaying
511
    if (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true) {
512
        if ($nodeData['hide_node'] === true) {
513
            $last_visible_parent = (int) $parent;
514
            $last_visible_parent_level = $currentNode->nlevel--;
515
        } elseif ($currentNode->nlevel < $last_visible_parent_level) {
516
            $last_visible_parent = -1;
517
        }
518
    }
519
520
    // json
521
    if ($nodeData['hide_node'] === false && $nodeData['show_but_block'] === false) {
522
        array_push(
523
            $ret_json,
524
            array(
525
                'id' => 'li_' . $nodeId,
526
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
527
                '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'],
528
                'li_attr' => array(
529
                    'class' => 'jstreeopen',
530
                    'title' => 'ID [' . $nodeId . '] ' . $nodeData['title'],
531
                ),
532
                'a_attr' => array(
533
                    'id' => 'fld_' . $nodeId,
534
                    'class' => $nodeData['folderClass'],
535
                    'onclick' => 'ListerItems(' . $nodeId . ', ' . $nodeData['restricted'] . ', 0, 1)',
536
                    'data-title' => htmlspecialchars($currentNode->title),
537
                ),
538
                'is_pf' => in_array($nodeId, $inputData['personalFolders']) === true ? 1 : 0,
539
                'can_edit' => (int) $inputData['userCanCreateRootFolder'],
540
            )
541
        );
542
        
543
        if ($inputData['userTreeLoadStrategy'] === 'sequential') {
544
            $ret_json[count($ret_json) - 1]['children'] = $nbSubfolders > 0 ? true : false;
545
        }
546
547
    } elseif ($nodeData['show_but_block'] === true) {
548
        array_push(
549
            $ret_json,
550
            array(
551
                'id' => 'li_' . $nodeId,
552
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
553
                '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'],
554
                'li_attr' => array(
555
                    'class' => '',
556
                    'title' => 'ID [' . $nodeId . '] ' . $lang->get('no_access'),
557
                ),
558
            )
559
        );
560
    }
561
562
    return [
563
        'last_visible_parent' => (int) $last_visible_parent,
564
        'last_visible_parent_level' => (int) $last_visible_parent_level,
565
        'ret_json' => $ret_json
566
    ];
567
}
568
569
/**
570
 * Get the context of the folder
571
 *
572
 * @param integer $nodeId
573
 * @param array $session_groupes_visibles
574
 * @param array $session_read_only_folders
575
 * @param array $session_personal_visible_groups
576
 * @param integer $nbItemsInFolder
577
 * @param integer $nbItemsInSubfolders
578
 * @param integer $nbSubfolders
579
 * @param array $session_list_folders_limited
580
 * @param integer $tree_counters
581
 * @param bool $session_user_read_only
582
 * @param array $listFoldersLimitedKeys
583
 * @param array $listRestrictedFoldersForItemsKeys
584
 * @param array $session_list_restricted_folders_for_items
585
 * @param array $session_personal_folder
586
 * @param NestedTree $tree
587
 * @return array
588
 */
589
function prepareNodeData(
590
    int $nodeId,
591
    array $session_groupes_visibles,
592
    array $session_read_only_folders,
593
    array $session_personal_visible_groups,
594
    int $nbItemsInFolder,
595
    int $nbItemsInSubfolders,
596
    int $nbSubfolders,
597
    array $session_list_folders_limited,
598
    int $tree_counters,
599
    bool $session_user_read_only,
600
    array $listFoldersLimitedKeys,
601
    array $listRestrictedFoldersForItemsKeys,
602
    array $session_list_restricted_folders_for_items,
603
    array $session_personal_folder,
604
    NestedTree $tree
605
): array
606
{
607
    $session = SessionManager::getSession();
608
    // Load user's language
609
    $lang = new Language($session->get('user-language') ?? 'english');
610
611
    if (in_array($nodeId, $session_groupes_visibles) === true) {
612
        // special case for READ-ONLY folder
613
        if (in_array($nodeId, $session_read_only_folders) === true) {
614
            return [
615
                'html' => '<i class="far fa-eye fa-xs mr-1 ml-1"></i>'.
616
                    ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
617
                'title' => $lang->get('read_only_account'),
618
                'restricted' => 1,
619
                'folderClass' => 'folder_not_droppable',
620
                'show_but_block' => false,
621
                'hide_node' => false,
622
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
623
            ];
624
625
        } elseif (
626
            $session_user_read_only === true
627
            && in_array($nodeId, $session_personal_visible_groups) === false
628
        ) {
629
            return [
630
                'html' => '<i class="far fa-eye fa-xs mr-1"></i>'.
631
                    ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
632
                'title' => $lang->get('read_only_account'),
633
                'restricted' => 0,
634
                'folderClass' => 'folder',
635
                'show_but_block' => false,
636
                'hide_node' => false,
637
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
638
            ];
639
        }
640
        
641
        return [
642
            'html' => ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
643
            'title' => '',
644
            'restricted' => 0,
645
            'folderClass' => 'folder',
646
            'show_but_block' => false,
647
            'hide_node' => false,
648
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
649
        ];
650
651
    } elseif (in_array($nodeId, $listFoldersLimitedKeys) === true) {
652
        return [
653
            'html' => ($session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '') .
654
                ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_folders_limited[$nodeId]) . '</span>' : ''),
655
            'title' => '',
656
            'restricted' => 1,
657
            'folderClass' => 'folder',
658
            'show_but_block' => false,
659
            'hide_node' => false,
660
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
661
        ];
662
663
    } elseif (in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true) {
664
        return [
665
            'html' => $session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '' .
666
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_restricted_folders_for_items[$nodeId]) . '</span>',
667
            'title' => '',
668
            'restricted' => 1,
669
            'folderClass' => 'folder',
670
            'show_but_block' => false,
671
            'hide_node' => false,
672
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
673
        ];
674
675
    } elseif ((int) $nbSubfolders === 0
676
        //&& (int) $show_only_accessible_folders === 1
677
    ) {
678
        // folder should not be visible
679
        // only if it has no descendants
680
        $nodeDirectDescendants = $tree->getDescendants($nodeId, false, false, true);
681
        if (
682
            count(
683
                array_diff(
684
                    $nodeDirectDescendants,
685
                    array_merge(
686
                        $session_groupes_visibles,
687
                        array_keys($session_list_restricted_folders_for_items)
688
                    )
689
                )
690
            ) !== count($nodeDirectDescendants)
691
        ) {
692
            // show it but block it
693
            return [
694
                'html' => '',
695
                'title' => '',
696
                'restricted' => 1,
697
                'folderClass' => 'folder_not_droppable',
698
                'show_but_block' => true,
699
                'hide_node' => false,
700
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
701
            ];
702
        }
703
        
704
        // hide it
705
        return [
706
            'html' => '',
707
            'title' => '',
708
            'restricted' => 1,
709
            'folderClass' => 'folder_not_droppable',
710
            'show_but_block' => false,
711
            'hide_node' => true,
712
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
713
        ];
714
    }
715
716
    return [
717
        'html' => '',
718
        'title' => '',
719
        'restricted' => 1,
720
        'folderClass' => 'folder_not_droppable',
721
        'show_but_block' => true,
722
        'hide_node' => false,
723
        'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
724
    ];
725
}
726
727
728
/**
729
 * Permits to check if we can user a cache instead of loading from DB
730
 *
731
 * @param integer $lastTreeChange
732
 * @param integer $userTreeLastRefresh
733
 * @param array $userSessionTreeStructure
734
 * @param integer $userId
735
 * @param integer $forceRefresh
736
 * @param array $SETTINGS
737
 * @return array
738
 */
739
function loadTreeStrategy(
740
    int $lastTreeChange,
741
    int $userTreeLastRefresh,
742
    array $userSessionTreeStructure,
743
    int $userId,
744
    int $forceRefresh
745
): array
746
{
747
    // Case when refresh is EXPECTED / MANDATORY
748
    if ((int) $forceRefresh === 1) {
749
        return [
750
            'state' => true,
751
            'data' => [],
752
        ];
753
    }
754
755
    // Case when an update in the tree has been done
756
    // Refresh is then mandatory
757
    if ((int) $lastTreeChange > (int) $userTreeLastRefresh) {
758
        return [
759
            'state' => true,
760
            'data' => [],
761
        ];
762
    }
763
764
    // Does this user has the tree structure in session?
765
    // If yes then use it
766
    if (count($userSessionTreeStructure) > 0) {
767
        return [
768
            'state' => false,
769
            'data' => json_encode($userSessionTreeStructure),
770
        ];
771
    }
772
773
    // Does this user has a tree cache
774
    $userCacheTree = DB::queryFirstRow(
775
        'SELECT data
776
        FROM ' . prefixTable('cache_tree') . '
777
        WHERE user_id = %i',
778
        $userId
779
    );
780
    if (empty($userCacheTree['data']) === false && $userCacheTree['data'] !== '[]') {
781
        return [
782
            'state' => false,
783
            'data' => $userCacheTree['data'],
784
        ];
785
    }
786
787
    return [
788
        'state' => true,
789
        'data' => [],
790
    ];
791
}