Passed
Pull Request — master (#3790)
by
unknown
04:51
created

showFolderToUser()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 11
c 2
b 0
f 0
nc 2
nop 5
dl 0
loc 23
rs 9.9
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-2023 Teampass.net
17
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
18
 *
19
 * @see       https://www.teampass.net
20
 */
21
22
23
require_once 'SecureHandler.php';
24
session_name('teampass_session');
25
session_start();
26
if (
27
    isset($_SESSION['CPM']) === false
28
    || $_SESSION['CPM'] !== 1
29
    || isset($_SESSION['key']) === false
30
    || empty($_SESSION['key']) === true
31
) {
32
    die('Hacking attempt...');
33
}
34
35
// Load config
36
include __DIR__.'/../includes/config/tp.config.php';
37
38
// includes
39
require_once $SETTINGS['cpassman_dir'] . '/includes/config/include.php';
40
require_once $SETTINGS['cpassman_dir'] . '/sources/main.functions.php';
41
require_once $SETTINGS['cpassman_dir'] . '/includes/language/' . $_SESSION['user']['user_language'] . '.php';
42
require_once $SETTINGS['cpassman_dir'] . '/includes/config/settings.php';
43
44
// header
45
header('Content-type: text/html; charset=utf-8');
46
header('Cache-Control: no-cache, must-revalidate');
47
48
// Define Timezone
49
if (isset($SETTINGS['timezone'])) {
50
    date_default_timezone_set($SETTINGS['timezone']);
51
} else {
52
    date_default_timezone_set('UTC');
53
}
54
55
// Connect to mysql server
56
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Database/Meekrodb/db.class.php';
57
if (defined('DB_PASSWD_CLEAR') === false) {
58
    define('DB_PASSWD_CLEAR', defuseReturnDecrypted(DB_PASSWD, $SETTINGS));
59
}
60
DB::$host = DB_HOST;
61
DB::$user = DB_USER;
62
DB::$password = DB_PASSWD_CLEAR;
63
DB::$dbName = DB_NAME;
64
DB::$port = DB_PORT;
65
DB::$encoding = DB_ENCODING;
66
DB::$ssl = DB_SSL;
67
DB::$connect_options = DB_CONNECT_OPTIONS;
68
69
// Superglobal load
70
require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/protect/SuperGlobal/SuperGlobal.php';
71
$superGlobal = new protect\SuperGlobal\SuperGlobal();
72
73
// Prepare sanitization
74
$data = [
75
    'forbidenPfs' => isset($_SESSION['forbiden_pfs']) === true ? json_encode($_SESSION['forbiden_pfs']) : '{}',
76
    'visibleFolders' => isset($_SESSION['groupes_visibles']) === true ? json_encode($_SESSION['groupes_visibles']) : '{}',
77
    'userId' => isset($_SESSION['user_id']) === true ? $_SESSION['user_id'] : '',
78
    'userLogin' => isset($_SESSION['login']) === true ? $_SESSION['login'] : '',
79
    'userReadOnly' => isset($_SESSION['user_read_only']) === true ? $_SESSION['user_read_only'] : '',
80
    'limitedFolders' => isset($_SESSION['list_folders_limited']) === true ? json_encode($_SESSION['list_folders_limited']) : '{}',
81
    'readOnlyFolders' => isset($_SESSION['read_only_folders']) === true ? json_encode($_SESSION['read_only_folders']) : '{}',
82
    'personalVisibleFolders' => isset($_SESSION['personal_visible_groups']) === true ? json_encode($_SESSION['personal_visible_groups']) : '{}',
83
    'userTreeLastRefresh' => isset($_SESSION['user_tree_last_refresh_timestamp']) === true ? $_SESSION['user_tree_last_refresh_timestamp'] : '',
84
    'forceRefresh' => isset($_GET['force_refresh']) === true ? $_GET['force_refresh'] : '',
85
    'nodeId' => isset($_GET['id']) === true ? $_GET['id'] : '',
86
    'restrictedFoldersForItems' => isset($_GET['list_restricted_folders_for_items']) === true ? json_encode($_GET['list_restricted_folders_for_items']) : '{}',
87
    'noAccessFolders' => isset($_SESSION['no_access_folders']) === true ? json_encode($_SESSION['no_access_folders']) : '{}',
88
    'personalFolders' => isset($_SESSION['personal_folders']) === true ? json_encode($_SESSION['personal_folders']) : '{}',
89
    'userCanCreateRootFolder' => isset($_SESSION['can_create_root_folder']) === true ? json_encode($_SESSION['can_create_root_folder']) : '{}',
90
    'userTreeLoadStrategy' => isset($_SESSION['user']['user_treeloadstrategy']) === true ? $_SESSION['user']['user_treeloadstrategy'] : '',
91
];
92
93
$filters = [
94
    'forbidenPfs' => 'cast:array',
95
    'visibleFolders' => 'cast:array',
96
    'userId' => 'cast:integer',
97
    'userLogin' => 'trim|escape',
98
    'userReadOnly' => 'cast:boolean',
99
    'limitedFolders' => 'cast:array',
100
    'readOnlyFolders' => 'cast:array',
101
    'personalVisibleFolders' => 'cast:array',
102
    'userTreeLastRefresh' => 'cast:integer',
103
    'forceRefresh' => 'cast:integer',
104
    'nodeId' => 'cast:integer',
105
    'restrictedFoldersForItems' => 'cast:array',
106
    'noAccessFolders' => 'cast:array',
107
    'personalFolders' => 'cast:array',
108
    'userCanCreateRootFolder' => 'cast:array',
109
    'userTreeLoadStrategy' => 'trim|escape',
110
];
111
112
$inputData = dataSanitizer(
113
    $data,
114
    $filters,
115
    $SETTINGS['cpassman_dir']
116
);
117
118
$lastFolderChange = DB::queryfirstrow(
119
    'SELECT valeur FROM ' . prefixTable('misc') . '
120
    WHERE type = %s AND intitule = %s',
121
    'timestamp',
122
    'last_folder_change'
123
);
124
if (DB::count() === 0) {
125
    $lastFolderChange['valeur'] = 0;
126
}
127
128
// Should we use a cache or refresh the tree
129
$goTreeRefresh = loadTreeStrategy(
130
    (int) $lastFolderChange['valeur'],
131
    (int) $inputData['userTreeLastRefresh'],
132
    /** @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'),
133
    (int) $inputData['userId'],
134
    (int) $inputData['forceRefresh']
135
);
136
137
// We don't use the cache if an ID of folder is provided
138
if ($goTreeRefresh['state'] === true || empty($inputData['nodeId']) === false || $inputData['userTreeLoadStrategy'] === 'sequential') {
139
    // Build tree
140
    require_once $SETTINGS['cpassman_dir'] . '/includes/libraries/Tree/NestedTree/NestedTree.php';
141
    $tree = new Tree\NestedTree\NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
142
143
    if (
144
        isset($inputData['limitedFolders']) === true
145
        && is_array($inputData['limitedFolders']) === true
146
        && count($inputData['limitedFolders']) > 0
147
    ) {
148
        $listFoldersLimitedKeys = array_keys($inputData['limitedFolders']);
149
    } else {
150
        $listFoldersLimitedKeys = array();
151
    }
152
    
153
    // list of items accessible but not in an allowed folder
154
    if (
155
        isset($inputData['restrictedFoldersForItems']) === true
156
        && count($inputData['restrictedFoldersForItems']) > 0
157
    ) {
158
        $listRestrictedFoldersForItemsKeys = @array_keys($inputData['restrictedFoldersForItems']);
159
    } else {
160
        $listRestrictedFoldersForItemsKeys = array();
161
    }
162
    
163
    $ret_json = array();
164
    $last_visible_parent = -1;
165
    $last_visible_parent_level = 1;
166
    $nodeId = isset($inputData['nodeId']) === true && is_int($inputData['nodeId']) === true ? $inputData['nodeId'] : 0;
167
168
    // build the tree to be displayed
169
    if (showFolderToUser(
170
        $nodeId,
171
        $inputData['forbidenPfs'],
172
        $inputData['visibleFolders'],
173
        $listFoldersLimitedKeys,
174
        $listRestrictedFoldersForItemsKeys
175
    ) === true)
176
    {
177
        if ($inputData['userTreeLoadStrategy'] === 'sequential') {
178
            // SEQUENTIAL MODE
179
            $completTree = $tree->getDescendants(empty($nodeId) === true ? 0 : (int) $nodeId, false, true, false);
180
            foreach ($completTree as $child) {
181
                recursiveTree(
182
                    (int) $child->id,
183
                    $child,
184
                    /** @scrutinizer ignore-type */ $tree,
185
                    $listFoldersLimitedKeys,
186
                    $listRestrictedFoldersForItemsKeys,
187
                    $last_visible_parent,
188
                    $last_visible_parent_level,
189
                    $SETTINGS,
190
                    $inputData,
191
                    $ret_json
192
                );
193
            }
194
195
        } else {
196
            // FULL MODE
197
            $completTree = $tree->getTreeWithChildren();
198
            foreach ($completTree[0]->children as $child) {
199
                recursiveTree(
200
                    (int) $child,
201
                    $completTree[$child],
202
                    /** @scrutinizer ignore-type */ $tree,
203
                    $listFoldersLimitedKeys,
204
                    $listRestrictedFoldersForItemsKeys,
205
                    $last_visible_parent,
206
                    $last_visible_parent_level,
207
                    $SETTINGS,
208
                    $inputData,
209
                    $ret_json
210
                );
211
            }
212
        }
213
    }
214
215
    // Save in SESSION
216
    $superGlobal->put('user_tree_structure', $ret_json, 'SESSION');
217
    $superGlobal->put('user_tree_last_refresh_timestamp', time(), 'SESSION');
218
219
    $ret_json = json_encode($ret_json);
220
221
    // Save user folders tree
222
    cacheTreeUserHandler(
223
        (int) $inputData['userId'],
224
        $ret_json,
225
        $SETTINGS
226
    );
227
228
    // Send back
229
    echo $ret_json;
230
} else {
231
    echo $goTreeRefresh['data'];
232
}
233
234
235
/**
236
 * Check if user can see this folder based upon rights
237
 *
238
 * @param integer $nodeId
239
 * @param array $session_forbiden_pfs
240
 * @param array $session_groupes_visibles
241
 * @param array $listFoldersLimitedKeys
242
 * @param array $listRestrictedFoldersForItemsKeys
243
 * @return boolean
244
 */
245
function showFolderToUser(
246
    int $nodeId,
247
    array $session_forbiden_pfs,
248
    array $session_groupes_visibles,
249
    array $listFoldersLimitedKeys,
250
    array $listRestrictedFoldersForItemsKeys
251
): bool
252
{
253
    $big_array = array_diff(
254
        array_unique(
255
            array_merge(
256
                $session_groupes_visibles, 
257
                $listFoldersLimitedKeys, 
258
                $listRestrictedFoldersForItemsKeys
259
            ), 
260
            SORT_NUMERIC
261
        ), 
262
        $session_forbiden_pfs
263
    );
264
    if ($nodeId === 0 || in_array($nodeId, $big_array) === true) {
265
        return true;
266
    }
267
    return false;
268
}
269
270
271
272
/**
273
 * Get through complete tree
274
 *
275
 * @param int     $nodeId                            Id
276
 * @param stdClass   $currentNode                       Tree info
277
 * @param Tree\NestedTree\NestedTree   $tree                              The tree
278
 * @param array   $listFoldersLimitedKeys            Limited
279
 * @param array   $listRestrictedFoldersForItemsKeys Restricted
280
 * @param int     $last_visible_parent               Visible parent
281
 * @param int     $last_visible_parent_level         Parent level
282
 * @param array   $SETTINGS                          Teampass settings
283
 * @param array   $inputData,
284
 * @param array   $ret_json
285
 *
286
 * @return array
287
 */
288
function recursiveTree(
289
    int $nodeId,
290
    stdClass $currentNode,
291
    Tree\NestedTree\NestedTree $tree,
292
    array $listFoldersLimitedKeys,
293
    array $listRestrictedFoldersForItemsKeys,
294
    int $last_visible_parent,
295
    int $last_visible_parent_level,
296
    array $SETTINGS,
297
    array $inputData,
298
    array &$ret_json = array()
299
) {
300
    $text = '';
301
    $title = '';
302
    $show_but_block = false;
303
    
304
    // Load config
305
    include __DIR__.'/../includes/config/tp.config.php';
306
307
    $displayThisNode = false;
308
    $nbItemsInSubfolders = $nbSubfolders = $nbItemsInFolder = 0;
309
    $nodeDescendants = $tree->getDescendants($nodeId, true, false, false);
310
    
311
    foreach ($nodeDescendants as $node) {
312
        if (
313
            in_array($node->id, array_merge($inputData['personalFolders'], $inputData['visibleFolders'])) === true
314
        ) {
315
            // Final check - is PF allowed?
316
            if (
317
                (int) $node->personal_folder === 1
318
                && (int) $SETTINGS['enable_pf_feature'] === 1
319
                && in_array($node->id, $inputData['personalFolders']) === false
320
            ) {
321
                $displayThisNode = false;
322
            } else {
323
                $displayThisNode = true;
324
                $nbItemsInSubfolders = (int) $node->nb_items_in_subfolders;
325
                $nbItemsInFolder = (int) $node->nb_items_in_folder;
326
                $nbSubfolders = (int) $node->nb_subfolders;
327
                break;
328
            }
329
        }
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 Tree\NestedTree\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
    Tree\NestedTree\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
        (int) $SETTINGS['show_only_accessible_folders'],
408
        isset($SETTINGS['tree_counters']) === true && isset($SETTINGS['enable_tasks_manager']) === true && (int) $SETTINGS['enable_tasks_manager'] === 1 && (int) $SETTINGS['tree_counters'] === 1 ? 1 : 0,
409
        (bool) $inputData['userReadOnly'],
410
        $listFoldersLimitedKeys,
411
        $listRestrictedFoldersForItemsKeys,
412
        $inputData['restrictedFoldersForItems'],
413
        $inputData['personalFolders'],
414
        $tree
415
    );
416
417
    // Prepare JSON 
418
    $tmpRetArray = prepareNodeJson(
419
        $currentNode,
420
        $nodeData,
421
        $inputData,
422
        $ret_json,
423
        $last_visible_parent,
424
        $last_visible_parent_level,
425
        $nodeId,
426
        $text,
427
        $nbSubfolders,
428
        $SETTINGS
429
    );    
430
    $last_visible_parent = $tmpRetArray['last_visible_parent'];
431
    $last_visible_parent_level = $tmpRetArray['last_visible_parent_level'];
432
    $ret_json = $tmpRetArray['ret_json'];
433
434
    // ensure we get the children of the folder
435
    if (isset($currentNode->children) === false) {
436
        $currentNode->children = $tree->getDescendants($nodeId, false, true, true);
437
    }
438
    if ($inputData['userTreeLoadStrategy'] === 'full' && isset($currentNode->children) === true) {
439
        foreach ($currentNode->children as $child) {
440
            recursiveTree(
441
                (int) $child,
442
                $tree->getNode($child),// get node info for this child
443
                /** @scrutinizer ignore-type */ $tree,
444
                $listFoldersLimitedKeys,
445
                $listRestrictedFoldersForItemsKeys,
446
                $last_visible_parent,
447
                $last_visible_parent_level,
448
                $SETTINGS,
449
                $inputData,
450
                $ret_json
451
            );
452
        }
453
    }
454
}
455
456
/**
457
 * Permits to prepare the node data
458
 *
459
 * @param stdClass $currentNode
460
 * @param array $nodeData
461
 * @param array $inputData
462
 * @param array $ret_json
463
 * @param integer $last_visible_parent
464
 * @param integer $last_visible_parent_level
465
 * @param integer $nodeId
466
 * @param string $text
467
 * @param integer $nbSubfolders
468
 * @param array $SETTINGS
469
 * @return array
470
 */
471
function prepareNodeJson(
472
    stdClass $currentNode,
473
    array $nodeData,
474
    array $inputData,
475
    array &$ret_json,
476
    int &$last_visible_parent,
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_VARIABLE, expecting T_STRING or T_NAME_QUALIFIED or T_NAME_FULLY_QUALIFIED or T_NAME_RELATIVE on line 476 at column 9
Loading history...
477
    int &$last_visible_parent_level,
478
    int $nodeId,
479
    string $text,
480
    int $nbSubfolders,
481
    array $SETTINGS
482
): array
483
{
484
    // prepare json return for current node
485
    $parent = $currentNode->parent_id === '0' ? '#' : 'li_' . $currentNode->parent_id;
486
487
    // handle displaying
488
    if (isKeyExistingAndEqual('show_only_accessible_folders', 1, $SETTINGS) === true) {
489
        if ($nodeData['hide_node'] === true) {
490
            $last_visible_parent = (int) $parent;
491
            $last_visible_parent_level = $currentNode->nlevel--;
492
        } elseif ($currentNode->nlevel < $last_visible_parent_level) {
493
            $last_visible_parent = -1;
494
        }
495
    }
496
497
    // json
498
    if ($nodeData['hide_node'] === false && $nodeData['show_but_block'] === false) {
499
        array_push(
500
            $ret_json,
501
            array(
502
                'id' => 'li_' . $nodeId,
503
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
504
                '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'],
505
                'li_attr' => array(
506
                    'class' => 'jstreeopen',
507
                    'title' => 'ID [' . $nodeId . '] ' . $nodeData['title'],
508
                ),
509
                'a_attr' => array(
510
                    'id' => 'fld_' . $nodeId,
511
                    'class' => $nodeData['folderClass'],
512
                    'onclick' => 'ListerItems(' . $nodeId . ', ' . $nodeData['restricted'] . ', 0, 1)',
513
                    'data-title' => $currentNode->title,
514
                ),
515
                'is_pf' => in_array($nodeId, $inputData['personalFolders']) === true ? 1 : 0,
516
                'can_edit' => (int) $inputData['userCanCreateRootFolder'],
517
            )
518
        );
519
        
520
        if ($inputData['userTreeLoadStrategy'] === 'sequential') {
521
            $ret_json[count($ret_json) - 1]['children'] = $nbSubfolders > 0 ? true : false;
522
        }
523
524
    } elseif ($nodeData['show_but_block'] === true) {
525
        array_push(
526
            $ret_json,
527
            array(
528
                'id' => 'li_' . $nodeId,
529
                'parent' => $last_visible_parent === -1 ? $parent : $last_visible_parent,
530
                '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'],
531
                'li_attr' => array(
532
                    'class' => '',
533
                    'title' => 'ID [' . $nodeId . '] ' . langHdl('no_access'),
534
                ),
535
            )
536
        );
537
    }
538
539
    return [
540
        'last_visible_parent' => (int) $last_visible_parent,
541
        'last_visible_parent_level' => (int) $last_visible_parent_level,
542
        'ret_json' => $ret_json
543
    ];
544
}
545
546
/**
547
 * Get the context of the folder
548
 *
549
 * @param integer $nodeId
550
 * @param array $session_groupes_visibles
551
 * @param array $session_read_only_folders
552
 * @param array $session_personal_visible_groups
553
 * @param integer $nbItemsInFolder
554
 * @param integer $nbItemsInSubfolders
555
 * @param integer $nbSubfolders
556
 * @param integer $session_list_folders_limited
557
 * @param integer $show_only_accessible_folders
558
 * @param integer $tree_counters
559
 * @param bool $session_user_read_only
560
 * @param array $listFoldersLimitedKeys
561
 * @param array $listRestrictedFoldersForItemsKeys
562
 * @param array $session_list_restricted_folders_for_items
563
 * @param array $session_personal_folder
564
 * @param Tree\NestedTree\NestedTree $tree
565
 * @return array
566
 */
567
function prepareNodeData(
568
    int $nodeId,
569
    array $session_groupes_visibles,
570
    array $session_read_only_folders,
571
    array $session_personal_visible_groups,
572
    int $nbItemsInFolder,
573
    int $nbItemsInSubfolders,
574
    int $nbSubfolders,
575
    array $session_list_folders_limited,
576
    int $show_only_accessible_folders,
577
    int $tree_counters,
578
    bool $session_user_read_only,
579
    array $listFoldersLimitedKeys,
580
    array $listRestrictedFoldersForItemsKeys,
581
    array $session_list_restricted_folders_for_items,
582
    array $session_personal_folder,
583
    Tree\NestedTree\NestedTree $tree
584
): array
585
{
586
    if (in_array($nodeId, $session_groupes_visibles) === true) {
587
        // special case for READ-ONLY folder
588
        if (in_array($nodeId, $session_read_only_folders) === true) {
589
            return [
590
                'html' => '<i class="far fa-eye fa-xs mr-1 ml-1"></i>'.
591
                    ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
592
                'title' => langHdl('read_only_account'),
593
                'restricted' => 1,
594
                'folderClass' => 'folder_not_droppable',
595
                'show_but_block' => false,
596
                'hide_node' => false,
597
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
598
            ];
599
600
        } elseif (
601
            $session_user_read_only === true
602
            && in_array($nodeId, $session_personal_visible_groups) === false
603
        ) {
604
            return [
605
                'html' => '<i class="far fa-eye fa-xs mr-1"></i>'.
606
                    ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
607
                'title' => langHdl('read_only_account'),
608
                'restricted' => 0,
609
                'folderClass' => 'folder',
610
                'show_but_block' => false,
611
                'hide_node' => false,
612
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
613
            ];
614
        }
615
        
616
        return [
617
            'html' => ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . $nbItemsInFolder .'/'.$nbItemsInSubfolders .'/'.$nbSubfolders. '</span>'  : ''),
618
            'title' => '',
619
            'restricted' => 0,
620
            'folderClass' => 'folder',
621
            'show_but_block' => false,
622
            'hide_node' => false,
623
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
624
        ];
625
626
    } elseif (in_array($nodeId, $listFoldersLimitedKeys) === true) {
627
        return [
628
            'html' => ($session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '') .
629
                ($tree_counters === 1 ? '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_folders_limited[$nodeId]) . '</span>' : ''),
630
            'title' => '',
631
            'restricted' => 1,
632
            'folderClass' => 'folder',
633
            'show_but_block' => false,
634
            'hide_node' => false,
635
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
636
        ];
637
638
    } elseif (in_array($nodeId, $listRestrictedFoldersForItemsKeys) === true) {
639
        return [
640
            'html' => $session_user_read_only === true ? '<i class="far fa-eye fa-xs mr-1"></i>' : '' .
641
                '<span class="badge badge-pill badge-light ml-2 items_count" id="itcount_' . $nodeId . '">' . count($session_list_restricted_folders_for_items[$nodeId]) . '</span>',
642
            'title' => '',
643
            'restricted' => 1,
644
            'folderClass' => 'folder',
645
            'show_but_block' => false,
646
            'hide_node' => false,
647
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
648
        ];
649
650
    } elseif ((int) $nbSubfolders === 0
651
        //&& (int) $show_only_accessible_folders === 1
652
    ) {
653
        // folder should not be visible
654
        // only if it has no descendants
655
        $nodeDirectDescendants = $tree->getDescendants($nodeId, false, false, true);
656
        if (
657
            count(
658
                array_diff(
659
                    $nodeDirectDescendants,
660
                    array_merge(
661
                        $session_groupes_visibles,
662
                        array_keys($session_list_restricted_folders_for_items)
663
                    )
664
                )
665
            ) !== count($nodeDirectDescendants)
666
        ) {
667
            // show it but block it
668
            return [
669
                'html' => '',
670
                'title' => '',
671
                'restricted' => 1,
672
                'folderClass' => 'folder_not_droppable',
673
                'show_but_block' => true,
674
                'hide_node' => false,
675
                'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
676
            ];
677
        }
678
        
679
        // hide it
680
        return [
681
            'html' => '',
682
            'title' => '',
683
            'restricted' => 1,
684
            'folderClass' => 'folder_not_droppable',
685
            'show_but_block' => false,
686
            'hide_node' => true,
687
            'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
688
        ];
689
    }
690
691
    return [
692
        'html' => '',
693
        'title' => isset($title) === true ? $title : '',
694
        'restricted' => 1,
695
        'folderClass' => 'folder_not_droppable',
696
        'show_but_block' => true,
697
        'hide_node' => false,
698
        'is_pf' => in_array($nodeId, $session_personal_folder) === true ? 1 : 0,
699
    ];
700
}
701
702
703
/**
704
 * Permits to check if we can user a cache instead of loading from DB
705
 *
706
 * @param integer $lastTreeChange
707
 * @param integer $userTreeLastRefresh
708
 * @param array $userSessionTreeStructure
709
 * @param integer $userId
710
 * @param integer $forceRefresh
711
 * @param array $SETTINGS
712
 * @return array
713
 */
714
function loadTreeStrategy(
715
    int $lastTreeChange,
716
    int $userTreeLastRefresh,
717
    array $userSessionTreeStructure,
718
    int $userId,
719
    int $forceRefresh
720
): array
721
{
722
    // Case when refresh is EXPECTED / MANDATORY
723
    if ((int) $forceRefresh === 1) {
724
        return [
725
            'state' => true,
726
            'data' => [],
727
        ];
728
    }
729
730
    // Case when an update in the tree has been done
731
    // Refresh is then mandatory
732
    if ((int) $lastTreeChange > (int) $userTreeLastRefresh) {
733
        return [
734
            'state' => true,
735
            'data' => [],
736
        ];
737
    }
738
739
    // Does this user has the tree structure in session?
740
    // If yes then use it
741
    if (count($userSessionTreeStructure) > 0) {
742
        return [
743
            'state' => false,
744
            'data' => json_encode($userSessionTreeStructure),
745
        ];
746
    }
747
748
    // Does this user has a tree cache
749
    $userCacheTree = DB::queryfirstrow(
750
        'SELECT data
751
        FROM ' . prefixTable('cache_tree') . '
752
        WHERE user_id = %i',
753
        $userId
754
    );
755
    if (empty($userCacheTree['data']) === false && $userCacheTree['data'] !== '[]') {
756
        return [
757
            'state' => false,
758
            'data' => $userCacheTree['data'],
759
        ];
760
    }
761
762
    return [
763
        'state' => true,
764
        'data' => [],
765
    ];
766
}