Test Failed
Push — master ( aa1bc5...0967fb )
by Raffael
01:34
created

Filesystem::findOne()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 0
cts 7
cp 0
rs 9.8333
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
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
        $result = iterator_to_array($this->findNodesByFilterRecursiveChildren($filter, $deleted, 0, 1));
221
222
        if (count($result) === 0) {
223
            throw new Exception\NotFound(
224
                'node ['.$id.'] not found',
225
                Exception\NotFound::NODE_NOT_FOUND
226
            );
227
        }
228
229
        $node = array_shift($result);
230
        if (null !== $class && !($node instanceof $class)) {
231
            throw new Exception('node '.get_class($node).' is not instance of '.$class);
232
        }
233
234
        return $node;
235
    }
236
237
    /**
238
     * Find one.
239
     */
240
    public function findOne(array $filter, int $deleted = NodeInterface::DELETED_INCLUDE): NodeInterface
241
    {
242
        $result = iterator_to_array($this->findNodesByFilterRecursiveChildren($filter, $deleted, 0, 1));
243
244
        if (count($result) === 0) {
245
            throw new Exception\NotFound(
246
                'requested node not found',
247
                Exception\NotFound::NODE_NOT_FOUND
248
            );
249
        }
250
251
        return array_shift($result);
252
    }
253
254
    /**
255
     * Load nodes by id.
256
     */
257
    public function findNodesById(array $id = [], ?string $class = null, int $deleted = NodeInterface::DELETED_INCLUDE): Generator
258
    {
259
        $find = [];
260
        foreach ($id as $i) {
261
            $find[] = new ObjectId($i);
262
        }
263
264
        $filter = [
265
            '_id' => ['$in' => $find],
266
        ];
267
268
        switch ($deleted) {
269
            case NodeInterface::DELETED_INCLUDE:
270
                break;
271
            case NodeInterface::DELETED_EXCLUDE:
272
                $filter['deleted'] = false;
273
274
                break;
275
            case NodeInterface::DELETED_ONLY:
276
                $filter['deleted'] = ['$type' => 9];
277
278
                break;
279
        }
280
281
        $result = $this->db->storage->find($filter);
282
283
        $nodes = [];
284
        foreach ($result as $node) {
285
            try {
286
                $return = $this->initNode($node);
287
288
                if (in_array($return->getId(), $nodes)) {
289
                    continue;
290
                }
291
292
                $nodes[] = $return->getId();
293
            } catch (\Exception $e) {
294
                $this->logger->error('remove node from result list, failed load node', [
295
                    'category' => get_class($this),
296
                    'exception' => $e,
297
                ]);
298
299
                continue;
300
            }
301
302
            if (null !== $class && !($return instanceof $class)) {
303
                throw new Exception('node is not an instance of '.$class);
304
            }
305
306
            yield $return;
307
        }
308
    }
309
310
    /**
311
     * Load nodes by id.
312
     *
313
     * @param null|mixed $class
314
     */
315
    public function getNodes(?array $id = null, $class = null, int $deleted = NodeInterface::DELETED_EXCLUDE): Generator
316
    {
317
        return $this->findNodesById($id, $class, $deleted);
318
    }
319
320
    /**
321
     * Load node.
322
     *
323
     * @param null|mixed $id
324
     * @param null|mixed $class
325
     */
326
    public function getNode($id = null, $class = null, bool $multiple = false, bool $allow_root = false, ?int $deleted = null): NodeInterface
327
    {
328
        if (empty($id)) {
329
            if (true === $allow_root) {
330
                return $this->getRoot();
331
            }
332
333
            throw new Exception\InvalidArgument('invalid id given');
334
        }
335
336
        if (null === $deleted) {
337
            $deleted = NodeInterface::DELETED_INCLUDE;
338
        }
339
340
        if (true === $multiple && is_array($id)) {
341
            return $this->findNodesById($id, $class, $deleted);
342
        }
343
344
        return $this->findNodeById($id, $class, $deleted);
345
    }
346
347
    /**
348
     * Find node with custom filter.
349
     */
350
    public function findNodeByFilter(array $filter): NodeInterface
351
    {
352
        $result = $this->db->storage->findOne($filter);
353
        if (null === $result) {
354
            throw new Exception\NotFound(
355
                'node with custom filter was not found',
356
                Exception\NotFound::NODE_NOT_FOUND
357
            );
358
        }
359
360
        return $this->initNode($result);
361
    }
362
363
    /**
364
     * Count.
365
     */
366
    public function countNodes(array $filter = []): int
367
    {
368
        return $this->db->storage->count($filter);
369
    }
370
371
    /**
372
     * Find nodes with custom filters.
373
     */
374
    public function findNodesByFilter(array $filter, ?int $offset = null, ?int $limit = null): Generator
375
    {
376
        $result = $this->db->storage->find($filter, [
377
            'skip' => $offset,
378
            'limit' => $limit,
379
        ]);
380
381
        $count = $this->countNodes($filter);
382
383
        foreach ($result as $node) {
384
            try {
385
                yield $this->initNode($node);
386
            } catch (\Exception $e) {
387
                $this->logger->error('remove node from result list, failed load node', [
388
                    'category' => get_class($this),
389
                    'exception' => $e,
390
                ]);
391
            }
392
        }
393
394
        return $count;
395
    }
396
397
    /**
398
     * Find nodes with custom filter recursive.
399
     */
400
    public function findNodesByFilterRecursiveToArray(Collection $collection, array $filter = []): array
401
    {
402
        $graph = [
403
            'from' => 'storage',
404
            'startWith' => '$pointer',
405
            'connectFromField' => 'pointer',
406
            'connectToField' => 'parent',
407
            'as' => 'children',
408
        ];
409
410
        if (count($filter) > 0) {
411
            $graph['restrictSearchWithMatch'] = $filter;
412
        }
413
414
        $query = [
415
            ['$match' => ['_id' => $collection->getId()]],
416
            ['$graphLookup' => $graph],
417
            ['$unwind' => '$children'],
418
            ['$project' => ['id' => '$children._id']],
419
        ];
420
421
        $result = $this->db->storage->aggregate($query);
422
423
        return array_column(iterator_to_array($result), 'id');
424
    }
425
426
    /**
427
     * Find nodes with custom filter recursive.
428
     */
429
    public function findNodesByFilterRecursiveChildren(array $parent_filter, int $deleted, ?int $offset = null, ?int $limit = null): Generator
430
    {
431
        $deleted_filter = [];
432
        if (NodeInterface::DELETED_EXCLUDE === $deleted) {
433
            $deleted_filter['deleted'] = false;
434
        } elseif (NodeInterface::DELETED_ONLY === $deleted) {
435
            $deleted_filter['deleted'] = ['$type' => 9];
436
        }
437
438
        $query = ['_id' => ['$exists' => true]];
439
440
        if ($this->user !== null) {
441
            $query = [
442
                '$or' => [
443
                    [
444
                        'acl' => ['$exists' => false],
445
                    ], [
446
                        'acl.id' => (string) $this->user->getId(),
447
                    ],
448
                ],
449
            ];
450
        }
451
452
        if (count($deleted_filter) > 0) {
453
            $query = ['$and' => [$deleted_filter, $query]];
454
        }
455
456
        $query = [
457
            ['$match' => $parent_filter],
458
            ['$graphLookup' => [
459
                'from' => 'storage',
460
                'startWith' => '$pointer',
461
                'connectFromField' => 'pointer',
462
                'connectToField' => 'parent',
463
                'as' => 'children',
464
                'maxDepth' => 0,
465
                'restrictSearchWithMatch' => $query,
466
            ]],
467
            ['$addFields' => [
468
                'size' => [
469
                    '$cond' => [
470
                        'if' => ['$eq' => ['$directory', true]],
471
                        'then' => ['$size' => '$children'],
472
                        'else' => '$size',
473
                    ],
474
                ],
475
            ]],
476
            ['$project' => ['children' => 0]],
477
            ['$group' => ['_id' => null, 'total' => ['$sum' => 1]]],
478
        ];
479
480
        $result = $this->db->storage->aggregate($query);
481
482
        $total = 0;
483
        $result = iterator_to_array($result);
484
        if (count($result) > 0) {
485
            $total = $result[0]['total'];
486
        }
487
488
        array_pop($query);
489
490
        $offset !== null ? $query[] = ['$skip' => $offset] : false;
491
        $limit !== null ? $query[] = ['$limit' => $limit] : false;
492
        $result = $this->db->storage->aggregate($query);
493
494
        foreach ($result as $node) {
495
            try {
496
                yield $this->initNode($node);
497
            } catch (\Exception $e) {
498
                $this->logger->error('remove node from result list, failed load node', [
499
                    'category' => get_class($this),
500
                    'exception' => $e,
501
                ]);
502
            }
503
        }
504
505
        return $total;
506
    }
507
508
    /**
509
     * Find nodes with custom filter recursive.
510
     */
511
    public function findNodesByFilterRecursive(Collection $collection, array $filter = [], ?int $offset = null, ?int $limit = null): Generator
512
    {
513
        $graph = [
514
            'from' => 'storage',
515
            'startWith' => '$pointer',
516
            'connectFromField' => 'pointer',
517
            'connectToField' => 'parent',
518
            'as' => 'children',
519
        ];
520
521
        if (count($filter) > 0) {
522
            $graph['restrictSearchWithMatch'] = $filter;
523
        }
524
525
        $query = [
526
            ['$match' => ['_id' => $collection->getId()]],
527
            ['$graphLookup' => $graph],
528
            ['$unwind' => '$children'],
529
            ['$group' => ['_id' => null, 'total' => ['$sum' => 1]]],
530
        ];
531
532
        $result = $this->db->storage->aggregate($query);
533
534
        $total = 0;
535
        $result = iterator_to_array($result);
536
        if (count($result) > 0) {
537
            $total = $result[0]['total'];
538
        }
539
540
        array_pop($query);
541
542
        $offset !== null ? $query[] = ['$skip' => $offset] : false;
543
        $limit !== null ? $query[] = ['$limit' => $limit] : false;
544
        $result = $this->db->storage->aggregate($query);
545
546
        foreach ($result as $node) {
547
            try {
548
                if (isset($node['children'])) {
549
                    $node = $node['children'];
550
                }
551
552
                yield $this->initNode($node);
553
            } catch (\Exception $e) {
554
                $this->logger->error('remove node from result list, failed load node', [
555
                    'category' => get_class($this),
556
                    'exception' => $e,
557
                ]);
558
            }
559
        }
560
561
        return $total;
562
    }
563
564
    /**
565
     * Get custom filtered children.
566
     */
567
    public function findNodesByFilterUser(int $deleted, array $filter, ?int $offset = null, ?int $limit = null): Generator
568
    {
569
        $shares = $this->user->getShares();
570
        $stored_filter = ['$and' => [
571
            [],
572
            ['$or' => [
573
                ['owner' => $this->user->getId()],
574
                ['shared' => ['$in' => $shares]],
575
            ]],
576
        ]];
577
578
        if (NodeInterface::DELETED_EXCLUDE === $deleted) {
579
            $stored_filter['$and'][0]['deleted'] = false;
580
        } elseif (NodeInterface::DELETED_ONLY === $deleted) {
581
            $stored_filter['$and'][0]['deleted'] = ['$type' => 9];
582
        }
583
584
        $stored_filter['$and'][0] = array_merge($filter, $stored_filter['$and'][0]);
585
586
        return $this->findNodesByFilterRecursiveChildren($stored_filter, $deleted, $offset, $limit);
587
    }
588
589
    /**
590
     * Init node.
591
     */
592
    public function initNode(array $node): NodeInterface
593
    {
594
        $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...
595
596
        if (isset($node['shared']) && true === $node['shared'] && null !== $this->user && $node['owner'] != $this->user->getId()) {
597
            $node = $this->findReferenceNode($node);
598
        }
599
600
        if (isset($node['parent'])) {
601
            $parent = $this->findNodeById($node['parent']);
602
        } elseif ($node['_id'] !== null) {
603
            $parent = $this->getRoot();
604
        } else {
605
            $parent = null;
606
        }
607
608
        if (!array_key_exists('directory', $node)) {
609
            throw new Exception('invalid node ['.$node['_id'].'] found, directory attribute does not exists');
610
        }
611
612
        $instance = $this->node_factory->build($this, $node, $parent);
613
614
        if (!$this->acl->isAllowed($instance, 'r')) {
615
            if ($instance->isReference()) {
616
                $instance->delete(true);
617
            }
618
619
            throw new ForbiddenException(
620
                'not allowed to access node',
621
                ForbiddenException::NOT_ALLOWED_TO_ACCESS
622
            );
623
        }
624
625
        $loaded = isset($this->cache[(string) $node['_id']]);
626
627
        if ($loaded === false) {
628
            $this->cache[(string) $node['_id']] = $instance;
629
        }
630
631
        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...
632
            $this->logger->info('node ['.$node['_id'].'] is not accessible anmyore, destroy node cause of expired destroy flag', [
633
                'category' => get_class($this),
634
            ]);
635
636
            $instance->delete(true);
637
638
            throw new Exception\Conflict('node is not available anymore');
639
        }
640
641
        if (PHP_SAPI === 'cli') {
642
            unset($this->cache[(string) $node['_id']]);
643
        }
644
645
        return $instance;
646
    }
647
648
    /**
649
     * Find node with path.
650
     */
651
    public function findNodeByPath(string $path = '', ?string $class = null): NodeInterface
652
    {
653
        if (empty($path) || '/' !== $path[0]) {
654
            $path = '/'.$path;
655
        }
656
        $last = strlen($path) - 1;
657
        if ('/' === $path[$last]) {
658
            $path = substr($path, 0, -1);
659
        }
660
        $parts = explode('/', $path);
661
        $parent = $this->getRoot();
662
        array_shift($parts);
663
        $count = count($parts);
664
        $i = 0;
665
        $filter = [];
666
        foreach ($parts as $node) {
667
            ++$i;
668
            if ($count === $i && $class !== null) {
669
                $filter = [
670
                    'directory' => ($class === Collection::class),
671
                ];
672
            }
673
674
            try {
675
                $parent = $parent->getChild($node, NodeInterface::DELETED_EXCLUDE, $filter);
676
            } catch (Exception\NotFound $e) {
677
                if ($count == $i) {
678
                    $parent = $parent->getChild($node, NodeInterface::DELETED_INCLUDE, $filter);
679
                } else {
680
                    throw $e;
681
                }
682
            }
683
        }
684
        if (null !== $class && !($parent instanceof $class)) {
685
            throw new Exception('node is not instance of '.$class);
686
        }
687
688
        return $parent;
689
    }
690
691
    /**
692
     * Resolve shared node to reference or share depending who requested.
693
     */
694
    protected function findReferenceNode(array $node): array
695
    {
696
        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...
697
            $this->logger->debug('reference node ['.$node['_id'].'] requested from share owner, trying to find the shared node', [
698
                'category' => get_class($this),
699
            ]);
700
701
            $result = $this->db->storage->findOne([
702
                'owner' => $this->user->getId(),
703
                'shared' => true,
704
                '_id' => $node['reference'],
705
            ]);
706
707
            if (null === $result) {
708
                throw new Exception\NotFound(
709
                    'no share node for reference node '.$node['reference'].' found',
710
                    Exception\NotFound::SHARE_NOT_FOUND
711
                );
712
            }
713
        } else {
714
            $this->logger->debug('share node ['.$node['_id'].'] requested from member, trying to find the reference node', [
715
                'category' => get_class($this),
716
            ]);
717
718
            $result = $this->db->storage->findOne([
719
                'owner' => $this->user->getId(),
720
                'shared' => true,
721
                'reference' => $node['_id'],
722
            ]);
723
724
            if (null === $result) {
725
                throw new Exception\NotFound(
726
                    'no share reference for node '.$node['_id'].' found',
727
                    Exception\NotFound::REFERENCE_NOT_FOUND
728
                );
729
            }
730
        }
731
732
        return $result;
733
    }
734
}
735