Completed
Push — master ( b97427...e235cc )
by Raffael
30:35 queued 26:08
created

Filesystem::findNodeByPath()   B

Complexity

Conditions 11
Paths 48

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
dl 0
loc 39
ccs 0
cts 24
cp 0
rs 7.3166
c 0
b 0
f 0
cc 11
nc 48
nop 2
crap 132

How to fix   Complexity   

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:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * balloon
7
 *
8
 * @copyright   Copryright (c) 2012-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Balloon;
13
14
use Balloon\Filesystem\Acl;
15
use Balloon\Filesystem\Acl\Exception\Forbidden as ForbiddenException;
16
use Balloon\Filesystem\Delta;
17
use Balloon\Filesystem\Exception;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Balloon\Exception.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
18
use Balloon\Filesystem\Node\Collection;
19
use Balloon\Filesystem\Node\Factory as NodeFactory;
20
use Balloon\Filesystem\Node\NodeInterface;
21
use Balloon\Server\User;
22
use Generator;
23
use MongoDB\BSON\ObjectId;
24
use MongoDB\BSON\UTCDateTime;
25
use MongoDB\Database;
26
use Psr\Log\LoggerInterface;
27
28
class Filesystem
29
{
30
    /**
31
     * Database.
32
     *
33
     * @var Database
34
     */
35
    protected $db;
36
37
    /**
38
     * LoggerInterface.
39
     *
40
     * @var LoggerInterface
41
     */
42
    protected $logger;
43
44
    /**
45
     * Hook.
46
     *
47
     * @var Hook
48
     */
49
    protected $hook;
50
51
    /**
52
     * Server.
53
     *
54
     * @var Server
55
     */
56
    protected $server;
57
58
    /**
59
     * Root collection.
60
     *
61
     * @var Collection
62
     */
63
    protected $root;
64
65
    /**
66
     * User.
67
     *
68
     * @var Delta
69
     */
70
    protected $delta;
71
72
    /**
73
     * Get user.
74
     *
75
     * @var User
76
     */
77
    protected $user;
78
79
    /**
80
     * Node factory.
81
     *
82
     * @var NodeFactory
83
     */
84
    protected $node_factory;
85
86
    /**
87
     * Acl.
88
     *
89
     * @var Acl
90
     */
91
    protected $acl;
92
93
    /**
94
     * Cache.
95
     *
96
     * @var array
97
     */
98
    protected $cache = [];
99
100
    /**
101
     * RAW Cache.
102
     *
103
     * @var array
104
     */
105
    protected $raw_cache = [];
106
107
    /**
108
     * Initialize.
109
     */
110
    public function __construct(Server $server, Database $db, Hook $hook, LoggerInterface $logger, NodeFactory $node_factory, Acl $acl, ?User $user = null)
111
    {
112
        $this->user = $user;
113
        $this->server = $server;
114
        $this->db = $db;
115
        $this->logger = $logger;
116
        $this->hook = $hook;
117
        $this->node_factory = $node_factory;
118
        $this->acl = $acl;
119
    }
120
121
    /**
122
     * Get user.
123
     */
124
    public function getUser(): ?User
125
    {
126
        return $this->user;
127
    }
128
129
    /**
130
     * Get server.
131
     */
132
    public function getServer(): Server
133
    {
134
        return $this->server;
135
    }
136
137
    /**
138
     * Get database.
139
     */
140
    public function getDatabase(): Database
141
    {
142
        return $this->db;
143
    }
144
145
    /**
146
     * Get root.
147
     */
148
    public function getRoot(): Collection
149
    {
150
        if ($this->root instanceof Collection) {
151
            return $this->root;
152
        }
153
154
        return $this->root = $this->initNode([
155
            'directory' => true,
156
            '_id' => null,
157
            'owner' => $this->user ? $this->user->getId() : null,
158
        ]);
159
    }
160
161
    /**
162
     * Get delta.
163
     */
164
    public function getDelta(): Delta
165
    {
166
        if ($this->delta instanceof Delta) {
167
            return $this->delta;
168
        }
169
170
        return $this->delta = new Delta($this, $this->db, $this->acl);
171
    }
172
173
    /**
174
     * Find raw node.
175
     */
176
    public function findRawNode(ObjectId $id): array
177
    {
178
        if (isset($this->raw_cache[(string) $id])) {
179
            return $this->raw_cache[(string) $id];
180
        }
181
182
        $node = $this->db->storage->findOne(['_id' => $id]);
183
        if (null === $node) {
184
            throw new Exception\NotFound(
185
                'node '.$id.' not found',
186
                Exception\NotFound::NODE_NOT_FOUND
187
            );
188
        }
189
190
        $this->raw_cache[(string) $id] = $node;
191
192
        return $node;
193
    }
194
195
    /**
196
     * Factory loader.
197
     */
198
    public function findNodeById($id, ?string $class = null, int $deleted = NodeInterface::DELETED_INCLUDE): NodeInterface
199
    {
200
        if (isset($this->cache[(string) $id])) {
201
            return $this->cache[(string) $id];
202
        }
203
204
        if (!is_string($id) && !($id instanceof ObjectId)) {
0 ignored issues
show
Bug introduced by
The class MongoDB\BSON\ObjectId does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
205
            throw new Exception\InvalidArgument($id.' node id has to be a string or instance of \MongoDB\BSON\ObjectId');
206
        }
207
208
        try {
209
            if (is_string($id)) {
210
                $id = new ObjectId($id);
211
            }
212
        } catch (\Exception $e) {
213
            throw new Exception\InvalidArgument('invalid node id specified');
214
        }
215
216
        $filter = [
217
            '_id' => $id,
218
        ];
219
220
        switch ($deleted) {
221
            case NodeInterface::DELETED_INCLUDE:
222
                break;
223
            case NodeInterface::DELETED_EXCLUDE:
224
                $filter['deleted'] = false;
225
226
                break;
227
            case NodeInterface::DELETED_ONLY:
228
                $filter['deleted'] = ['$type' => 9];
229
230
                break;
231
        }
232
233
        $node = $this->db->storage->findOne($filter);
234
235
        if (null === $node) {
236
            throw new Exception\NotFound(
237
                'node ['.$id.'] not found',
238
                Exception\NotFound::NODE_NOT_FOUND
239
            );
240
        }
241
242
        $return = $this->initNode($node);
243
244
        if (null !== $class && !($return instanceof $class)) {
245
            throw new Exception('node '.get_class($return).' is not instance of '.$class);
246
        }
247
248
        return $return;
249
    }
250
251
    /**
252
     * Load nodes by id.
253
     */
254
    public function findNodesById(array $id = [], ?string $class = null, int $deleted = NodeInterface::DELETED_INCLUDE): Generator
255
    {
256
        $find = [];
257
        foreach ($id as $i) {
258
            $find[] = new ObjectId($i);
259
        }
260
261
        $filter = [
262
            '_id' => ['$in' => $find],
263
        ];
264
265
        switch ($deleted) {
266
            case NodeInterface::DELETED_INCLUDE:
267
                break;
268
            case NodeInterface::DELETED_EXCLUDE:
269
                $filter['deleted'] = false;
270
271
                break;
272
            case NodeInterface::DELETED_ONLY:
273
                $filter['deleted'] = ['$type' => 9];
274
275
                break;
276
        }
277
278
        $result = $this->db->storage->find($filter);
279
280
        $nodes = [];
281
        foreach ($result as $node) {
282
            try {
283
                $return = $this->initNode($node);
284
285
                if (in_array($return->getId(), $nodes)) {
286
                    continue;
287
                }
288
289
                $nodes[] = $return->getId();
290
            } catch (\Exception $e) {
291
                $this->logger->error('remove node from result list, failed load node', [
292
                    'category' => get_class($this),
293
                    'exception' => $e,
294
                ]);
295
296
                continue;
297
            }
298
299
            if (null !== $class && !($return instanceof $class)) {
300
                throw new Exception('node is not an instance of '.$class);
301
            }
302
303
            yield $return;
304
        }
305
    }
306
307
    /**
308
     * Load nodes by id.
309
     *
310
     * @param null|mixed $class
311
     */
312
    public function getNodes(?array $id = null, $class = null, int $deleted = NodeInterface::DELETED_EXCLUDE): Generator
313
    {
314
        return $this->findNodesById($id, $class, $deleted);
315
    }
316
317
    /**
318
     * Load node.
319
     *
320
     * @param null|mixed $id
321
     * @param null|mixed $class
322
     */
323
    public function getNode($id = null, $class = null, bool $multiple = false, bool $allow_root = false, ?int $deleted = null): NodeInterface
324
    {
325
        if (empty($id)) {
326
            if (true === $allow_root) {
327
                return $this->getRoot();
328
            }
329
330
            throw new Exception\InvalidArgument('invalid id given');
331
        }
332
333
        if (null === $deleted) {
334
            $deleted = NodeInterface::DELETED_INCLUDE;
335
        }
336
337
        if (true === $multiple && is_array($id)) {
338
            return $this->findNodesById($id, $class, $deleted);
339
        }
340
341
        return $this->findNodeById($id, $class, $deleted);
342
    }
343
344
    /**
345
     * Find node with custom filter.
346
     */
347
    public function findNodeByFilter(array $filter): NodeInterface
348
    {
349
        $result = $this->db->storage->findOne($filter);
350
        if (null === $result) {
351
            throw new Exception\NotFound(
352
                'node with custom filter was not found',
353
                Exception\NotFound::NODE_NOT_FOUND
354
            );
355
        }
356
357
        return $this->initNode($result);
358
    }
359
360
    /**
361
     * Count.
362
     */
363
    public function countNodes(array $filter = []): int
364
    {
365
        return $this->db->storage->count($filter);
366
    }
367
368
    /**
369
     * Find nodes with custom filters.
370
     */
371
    public function findNodesByFilter(array $filter, ?int $offset = null, ?int $limit = null): Generator
372
    {
373
        $result = $this->db->storage->find($filter, [
374
            'skip' => $offset,
375
            'limit' => $limit,
376
        ]);
377
378
        $count = $this->countNodes($filter);
379
380
        foreach ($result as $node) {
381
            try {
382
                yield $this->initNode($node);
383
            } catch (\Exception $e) {
384
                $this->logger->error('remove node from result list, failed load node', [
385
                    'category' => get_class($this),
386
                    'exception' => $e,
387
                ]);
388
            }
389
        }
390
391
        return $count;
392
    }
393
394
    /**
395
     * Find nodes with custom filter recursive.
396
     */
397
    public function findNodesByFilterRecursiveToArray(Collection $collection, array $filter = []): array
398
    {
399
        $graph = [
400
            'from' => 'storage',
401
            'startWith' => '$pointer',
402
            'connectFromField' => 'pointer',
403
            'connectToField' => 'parent',
404
            'as' => 'children',
405
        ];
406
407
        if (count($filter) > 0) {
408
            $graph['restrictSearchWithMatch'] = $filter;
409
        }
410
411
        $query = [
412
            ['$match' => ['_id' => $collection->getId()]],
413
            ['$graphLookup' => $graph],
414
            ['$unwind' => '$children'],
415
            ['$project' => ['id' => '$children._id']],
416
        ];
417
418
        $result = $this->db->storage->aggregate($query);
419
420
        return array_column(iterator_to_array($result), 'id');
421
    }
422
423
    /**
424
     * Find nodes with custom filter recursive.
425
     */
426
    public function findNodesByFilterRecursiveChildren(array $parent_filter, int $deleted, ?int $offset = null, ?int $limit = null): Generator
427
    {
428
        $deleted_filter = [];
429
        if (NodeInterface::DELETED_EXCLUDE === $deleted) {
430
            $deleted_filter['deleted'] = false;
431
        } elseif (NodeInterface::DELETED_ONLY === $deleted) {
432
            $deleted_filter['deleted'] = ['$type' => 9];
433
        }
434
435
        $query = [
436
            '$or' => [
437
                [
438
                    'acl' => ['$exists' => false],
439
                ], [
440
                    'acl.id' => (string) $this->user->getId(),
441
                ],
442
            ],
443
        ];
444
445
        if (count($deleted_filter) > 0) {
446
            $query = ['$and' => [$deleted_filter, $query]];
447
        }
448
449
        $query = [
450
            ['$match' => $parent_filter],
451
            ['$graphLookup' => [
452
                'from' => 'storage',
453
                'startWith' => '$pointer',
454
                'connectFromField' => 'pointer',
455
                'connectToField' => 'parent',
456
                'as' => 'children',
457
                'maxDepth' => 0,
458
                'restrictSearchWithMatch' => $query,
459
            ]],
460
            ['$addFields' => [
461
                'size' => [
462
                    '$cond' => [
463
                        'if' => ['$eq' => ['$directory', true]],
464
                        'then' => ['$size' => '$children'],
465
                        'else' => '$size',
466
                    ],
467
                ],
468
            ]],
469
            ['$project' => ['children' => 0]],
470
            ['$group' => ['_id' => null, 'total' => ['$sum' => 1]]],
471
        ];
472
473
        $result = $this->db->storage->aggregate($query);
474
475
        $total = 0;
476
        $result = iterator_to_array($result);
477
        if (count($result) > 0) {
478
            $total = $result[0]['total'];
479
        }
480
481
        array_pop($query);
482
483
        $offset !== null ? $query[] = ['$skip' => $offset] : false;
484
        $limit !== null ? $query[] = ['$limit' => $limit] : false;
485
        $result = $this->db->storage->aggregate($query);
486
487
        foreach ($result as $node) {
488
            try {
489
                yield $this->initNode($node);
490
            } catch (\Exception $e) {
491
                $this->logger->error('remove node from result list, failed load node', [
492
                    'category' => get_class($this),
493
                    'exception' => $e,
494
                ]);
495
            }
496
        }
497
498
        return $total;
499
    }
500
501
    /**
502
     * Find nodes with custom filter recursive.
503
     */
504
    public function findNodesByFilterRecursive(Collection $collection, array $filter = [], ?int $offset = null, ?int $limit = null): Generator
505
    {
506
        $graph = [
507
            'from' => 'storage',
508
            'startWith' => '$pointer',
509
            'connectFromField' => 'pointer',
510
            'connectToField' => 'parent',
511
            'as' => 'children',
512
        ];
513
514
        if (count($filter) > 0) {
515
            $graph['restrictSearchWithMatch'] = $filter;
516
        }
517
518
        $query = [
519
            ['$match' => ['_id' => $collection->getId()]],
520
            ['$graphLookup' => $graph],
521
            ['$unwind' => '$children'],
522
            ['$group' => ['_id' => null, 'total' => ['$sum' => 1]]],
523
        ];
524
525
        $result = $this->db->storage->aggregate($query);
526
527
        $total = 0;
528
        $result = iterator_to_array($result);
529
        if (count($result) > 0) {
530
            $total = $result[0]['total'];
531
        }
532
533
        array_pop($query);
534
535
        $offset !== null ? $query[] = ['$skip' => $offset] : false;
536
        $limit !== null ? $query[] = ['$limit' => $limit] : false;
537
        $result = $this->db->storage->aggregate($query);
538
539
        foreach ($result as $node) {
540
            try {
541
                if (isset($node['children'])) {
542
                    $node = $node['children'];
543
                }
544
545
                yield $this->initNode($node);
546
            } catch (\Exception $e) {
547
                $this->logger->error('remove node from result list, failed load node', [
548
                    'category' => get_class($this),
549
                    'exception' => $e,
550
                ]);
551
            }
552
        }
553
554
        return $total;
555
    }
556
557
    /**
558
     * Get custom filtered children.
559
     */
560
    public function findNodesByFilterUser(int $deleted, array $filter, ?int $offset = null, ?int $limit = null): Generator
561
    {
562
        $shares = $this->user->getShares();
563
        $stored_filter = ['$and' => [
564
            [],
565
            ['$or' => [
566
                ['owner' => $this->user->getId()],
567
                ['shared' => ['$in' => $shares]],
568
            ]],
569
        ]];
570
571
        if (NodeInterface::DELETED_EXCLUDE === $deleted) {
572
            $stored_filter['$and'][0]['deleted'] = false;
573
        } elseif (NodeInterface::DELETED_ONLY === $deleted) {
574
            $stored_filter['$and'][0]['deleted'] = ['$type' => 9];
575
        }
576
577
        $stored_filter['$and'][0] = array_merge($filter, $stored_filter['$and'][0]);
578
579
        return $this->findNodesByFilterRecursiveChildren($stored_filter, $deleted, $offset, $limit);
580
    }
581
582
    /**
583
     * Init node.
584
     */
585
    public function initNode(array $node): NodeInterface
586
    {
587
        $id = $node['_id'];
0 ignored issues
show
Unused Code introduced by
$id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
588
589
        if (isset($node['shared']) && true === $node['shared'] && null !== $this->user && $node['owner'] != $this->user->getId()) {
590
            $node = $this->findReferenceNode($node);
591
        }
592
593
        if (isset($node['parent'])) {
594
            $parent = $this->findNodeById($node['parent']);
595
        } elseif ($node['_id'] !== null) {
596
            $parent = $this->getRoot();
597
        } else {
598
            $parent = null;
599
        }
600
601
        if (!array_key_exists('directory', $node)) {
602
            throw new Exception('invalid node ['.$node['_id'].'] found, directory attribute does not exists');
603
        }
604
605
        $instance = $this->node_factory->build($this, $node, $parent);
606
607
        if (!$this->acl->isAllowed($instance, 'r')) {
608
            if ($instance->isReference()) {
609
                $instance->delete(true);
610
            }
611
612
            throw new ForbiddenException(
613
                'not allowed to access node',
614
                ForbiddenException::NOT_ALLOWED_TO_ACCESS
615
            );
616
        }
617
618
        $loaded = isset($this->cache[(string) $node['_id']]);
619
620
        if ($loaded === false) {
621
            $this->cache[(string) $node['_id']] = $instance;
622
        }
623
624
        if ($loaded === false && isset($node['destroy']) && $node['destroy'] instanceof UTCDateTime && $node['destroy']->toDateTime()->format('U') <= time()) {
0 ignored issues
show
Bug introduced by
The class MongoDB\BSON\UTCDateTime does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
625
            $this->logger->info('node ['.$node['_id'].'] is not accessible anmyore, destroy node cause of expired destroy flag', [
626
                'category' => get_class($this),
627
            ]);
628
629
            $instance->delete(true);
630
631
            throw new Exception\Conflict('node is not available anymore');
632
        }
633
634
        if (PHP_SAPI === 'cli') {
635
            unset($this->cache[(string) $node['_id']]);
636
        }
637
638
        return $instance;
639
    }
640
641
    /**
642
     * Find node with path.
643
     */
644
    public function findNodeByPath(string $path = '', ?string $class = null): NodeInterface
645
    {
646
        if (empty($path) || '/' !== $path[0]) {
647
            $path = '/'.$path;
648
        }
649
        $last = strlen($path) - 1;
650
        if ('/' === $path[$last]) {
651
            $path = substr($path, 0, -1);
652
        }
653
        $parts = explode('/', $path);
654
        $parent = $this->getRoot();
655
        array_shift($parts);
656
        $count = count($parts);
657
        $i = 0;
658
        $filter = [];
659
        foreach ($parts as $node) {
660
            ++$i;
661
            if ($count === $i && $class !== null) {
662
                $filter = [
663
                    'directory' => ($class === Collection::class),
664
                ];
665
            }
666
667
            try {
668
                $parent = $parent->getChild($node, NodeInterface::DELETED_EXCLUDE, $filter);
669
            } catch (Exception\NotFound $e) {
670
                if ($count == $i) {
671
                    $parent = $parent->getChild($node, NodeInterface::DELETED_INCLUDE, $filter);
672
                } else {
673
                    throw $e;
674
                }
675
            }
676
        }
677
        if (null !== $class && !($parent instanceof $class)) {
678
            throw new Exception('node is not instance of '.$class);
679
        }
680
681
        return $parent;
682
    }
683
684
    /**
685
     * Resolve shared node to reference or share depending who requested.
686
     */
687
    protected function findReferenceNode(array $node): array
688
    {
689
        if (isset($node['reference']) && ($node['reference'] instanceof ObjectId)) {
0 ignored issues
show
Bug introduced by
The class MongoDB\BSON\ObjectId does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
690
            $this->logger->debug('reference node ['.$node['_id'].'] requested from share owner, trying to find the shared node', [
691
                'category' => get_class($this),
692
            ]);
693
694
            $result = $this->db->storage->findOne([
695
                'owner' => $this->user->getId(),
696
                'shared' => true,
697
                '_id' => $node['reference'],
698
            ]);
699
700
            if (null === $result) {
701
                throw new Exception\NotFound(
702
                    'no share node for reference node '.$node['reference'].' found',
703
                    Exception\NotFound::SHARE_NOT_FOUND
704
                );
705
            }
706
        } else {
707
            $this->logger->debug('share node ['.$node['_id'].'] requested from member, trying to find the reference node', [
708
                'category' => get_class($this),
709
            ]);
710
711
            $result = $this->db->storage->findOne([
712
                'owner' => $this->user->getId(),
713
                'shared' => true,
714
                'reference' => $node['_id'],
715
            ]);
716
717
            if (null === $result) {
718
                throw new Exception\NotFound(
719
                    'no share reference for node '.$node['_id'].' found',
720
                    Exception\NotFound::REFERENCE_NOT_FOUND
721
                );
722
            }
723
        }
724
725
        return $result;
726
    }
727
}
728