Completed
Branch dev (bc6e47)
by Raffael
02:23
created

Filesystem::findNodesByPath()   C

Complexity

Conditions 8
Paths 17

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 16
nc 17
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Balloon
7
 *
8
 * @author      Raffael Sahli <[email protected]>
9
 * @copyright   Copryright (c) 2012-2017 gyselroth GmbH (https://gyselroth.com)
10
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
11
 */
12
13
namespace Balloon;
14
15
use Balloon\Filesystem\Acl;
16
use Balloon\Filesystem\Acl\Exception\Forbidden as ForbiddenException;
17
use Balloon\Filesystem\Delta;
18
use Balloon\Filesystem\Node\AttributeDecorator;
19
use Balloon\Filesystem\Node\Collection;
20
use Balloon\Filesystem\Node\File;
21
use Balloon\Filesystem\Node\NodeInterface;
22
use Balloon\Filesystem\Storage;
23
use Balloon\Server\User;
24
use Generator;
25
use MongoDB\BSON\ObjectId;
26
use MongoDB\BSON\UTCDateTime;
27
use MongoDB\Database;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Balloon\Database.

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...
28
use Psr\Log\LoggerInterface;
29
30
class Filesystem
31
{
32
    /**
33
     * Database.
34
     *
35
     * @var Database
36
     */
37
    protected $db;
38
39
    /**
40
     * LoggerInterface.
41
     *
42
     * @var LoggerInterface
43
     */
44
    protected $logger;
45
46
    /**
47
     * Hook.
48
     *
49
     * @var Hook
50
     */
51
    protected $hook;
52
53
    /**
54
     * Server.
55
     *
56
     * @var Server
57
     */
58
    protected $server;
59
60
    /**
61
     * Root collection.
62
     *
63
     * @var Collection
64
     */
65
    protected $root;
66
67
    /**
68
     * User.
69
     *
70
     * @var Delta
71
     */
72
    protected $delta;
73
74
    /**
75
     * Get user.
76
     *
77
     * @var User
78
     */
79
    protected $user;
80
81
    /**
82
     * Storage.
83
     *
84
     * @var Storage
85
     */
86
    protected $storage;
87
88
    /**
89
     * Acl.
90
     *
91
     * @var Acl
92
     */
93
    protected $acl;
94
95
    /**
96
     * Initialize.
97
     *
98
     * @param Server          $server
99
     * @param LoggerInterface $logger
100
     * @param User            $user
101
     */
102
    public function __construct(Server $server, Database $db, Hook $hook, LoggerInterface $logger, Storage $storage, Acl $acl, ?User $user = null)
103
    {
104
        $this->user = $user;
105
        $this->server = $server;
106
        $this->db = $db;
107
        $this->logger = $logger;
108
        $this->hook = $hook;
109
        $this->storage = $storage;
110
        $this->acl = $acl;
111
    }
112
113
    /**
114
     * Get user.
115
     *
116
     * @return User
117
     */
118
    public function getUser(): ?User
119
    {
120
        return $this->user;
121
    }
122
123
    /**
124
     * Get server.
125
     *
126
     * @return Server
127
     */
128
    public function getServer(): Server
129
    {
130
        return $this->server;
131
    }
132
133
    /**
134
     * Get database.
135
     *
136
     * @return Database
137
     */
138
    public function getDatabase(): Database
139
    {
140
        return $this->db;
141
    }
142
143
    /**
144
     * Get root.
145
     *
146
     * @return Collection
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
     * @return Delta
165
     */
166
    public function getDelta(): Delta
167
    {
168
        if ($this->delta instanceof Delta) {
169
            return $this->delta;
170
        }
171
172
        return $this->delta = new Delta($this, $this->db, new AttributeDecorator(
173
            $this->server,
174
            $this->acl
175
        ));
176
    }
177
178
    /**
179
     * Find raw node.
180
     *
181
     * @param ObjectId $id
182
     *
183
     * @return array
184
     */
185
    public function findRawNode(ObjectId $id): array
186
    {
187
        $node = $this->db->storage->findOne(['_id' => $id]);
188
        if (null === $node) {
189
            throw new Exception\NotFound(
190
                'node '.$id.' not found',
191
                Exception\NotFound::NODE_NOT_FOUND
192
            );
193
        }
194
195
        return $node;
196
    }
197
198
    /**
199
     * Factory loader.
200
     *
201
     * @param ObjectId|string $id
202
     * @param string          $class   Fore check node type
203
     * @param int             $deleted
204
     *
205
     * @return NodeInterface
206
     */
207
    public function findNodeById($id, ?string $class = null, int $deleted = NodeInterface::DELETED_INCLUDE): NodeInterface
208
    {
209
        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...
210
            throw new Exception\InvalidArgument($id.' node id has to be a string or instance of \MongoDB\BSON\ObjectId');
211
        }
212
213
        try {
214
            if (is_string($id)) {
215
                $id = new ObjectId($id);
216
            }
217
        } catch (\Exception $e) {
218
            throw new Exception\InvalidArgument('invalid node id specified');
219
        }
220
221
        $filter = [
222
            '_id' => $id,
223
        ];
224
225
        switch ($deleted) {
226
            case NodeInterface::DELETED_INCLUDE:
227
                break;
228
            case NodeInterface::DELETED_EXCLUDE:
229
                $filter['deleted'] = false;
230
231
                break;
232
            case NodeInterface::DELETED_ONLY:
233
                $filter['deleted'] = ['$type' => 9];
234
235
                break;
236
        }
237
238
        $node = $this->db->storage->findOne($filter);
239
240
        if (null === $node) {
241
            throw new Exception\NotFound(
242
                'node ['.$id.'] not found',
243
                Exception\NotFound::NODE_NOT_FOUND
244
            );
245
        }
246
247
        $return = $this->initNode($node);
248
249
        if (null !== $class && !($return instanceof $class)) {
250
            throw new Exception('node '.get_class($return).' is not instance of '.$class);
251
        }
252
253
        return $return;
254
    }
255
256
    /**
257
     * Load node with path.
258
     *
259
     * @param string $path
260
     * @param string $class Fore check node type
261
     *
262
     * @return NodeInterface
263
     */
264
    public function findNodeByPath(string $path = '', ?string $class = null): NodeInterface
265
    {
266
        if (empty($path) || '/' !== $path[0]) {
267
            $path = '/'.$path;
268
        }
269
270
        $last = strlen($path) - 1;
271
        if ('/' === $path[$last]) {
272
            $path = substr($path, 0, -1);
273
        }
274
275
        $parts = explode('/', $path);
276
        $parent = $this->getRoot();
277
        array_shift($parts);
278
        foreach ($parts as $node) {
279
            $parent = $parent->getChild($node, NodeInterface::DELETED_EXCLUDE);
280
        }
281
282
        if (null !== $class && !($parent instanceof $class)) {
283
            throw new Exception('node is not instance of '.$class);
284
        }
285
286
        return $parent;
287
    }
288
289
    /**
290
     * Load nodes by id.
291
     *
292
     * @param array  $id
293
     * @param string $class   Force check node type
294
     * @param bool   $deleted
295
     *
296
     * @return Generator
297
     */
298
    public function findNodesById(array $id = [], ?string $class = null, int $deleted = NodeInterface::DELETED_INCLUDE): Generator
299
    {
300
        $find = [];
301
        foreach ($id as $i) {
302
            $find[] = new ObjectId($i);
303
        }
304
305
        $filter = [
306
            '_id' => ['$in' => $find],
307
        ];
308
309
        switch ($deleted) {
310
            case NodeInterface::DELETED_INCLUDE:
311
                break;
312
            case NodeInterface::DELETED_EXCLUDE:
313
                $filter['deleted'] = false;
314
315
                break;
316
            case NodeInterface::DELETED_ONLY:
317
                $filter['deleted'] = ['$type' => 9];
318
319
                break;
320
        }
321
322
        $result = $this->db->storage->find($filter);
323
324
        $nodes = [];
0 ignored issues
show
Unused Code introduced by
$nodes 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...
325
        foreach ($result as $node) {
326
            $return = $this->initNode($node);
327
328
            if (null !== $class && !($return instanceof $class)) {
329
                throw new Exception('node is not an instance of '.$class);
330
            }
331
332
            yield $return;
333
        }
334
    }
335
336
    /**
337
     * Load nodes by id.
338
     *
339
     * @param array  $path
340
     * @param string $class Force check node type
341
     *
342
     * @return Generator
343
     */
344
    public function findNodesByPath(array $path = [], ?string $class = null): Generator
345
    {
346
        $find = [];
0 ignored issues
show
Unused Code introduced by
$find 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...
347
        foreach ($path as $p) {
0 ignored issues
show
Bug introduced by
The expression $path of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
348
            if (empty($path) || '/' !== $path[0]) {
349
                $path = '/'.$path;
350
            }
351
352
            $last = strlen($path) - 1;
353
            if ('/' === $path[$last]) {
354
                $path = substr($path, 0, -1);
355
            }
356
357
            $parts = explode('/', $path);
358
            $parent = $this->getRoot();
359
            array_shift($parts);
360
            foreach ($parts as $node) {
361
                $parent = $parent->getChild($node, NodeInterface::DELETED_EXCLUDE);
362
            }
363
364
            if (null !== $class && !($parent instanceof $class)) {
365
                throw new Exception('node is not an instance of '.$class);
366
            }
367
368
            yield $parent;
369
        }
370
    }
371
372
    /**
373
     * Load nodes by id.
374
     *
375
     * @param array  $id
376
     * @param array  $path
377
     * @param string $class   Force set node type
378
     * @param int    $deleted
379
     *
380
     * @return Generator
381
     */
382
    public function getNodes(?array $id = null, ?array $path = null, $class = null, int $deleted = NodeInterface::DELETED_EXCLUDE): Generator
383
    {
384
        if (null === $id && null === $path) {
385
            throw new Exception\InvalidArgument('neither parameter id nor p (path) was given');
386
        }
387
        if (null !== $id && null !== $path) {
388
            throw new Exception\InvalidArgument('parameter id and p (path) can not be used at the same time');
389
        }
390
        if (null !== $id) {
391
            if (null === $deleted) {
392
                $deleted = NodeInterface::DELETED_INCLUDE;
393
            }
394
395
            return $this->findNodesById($id, $class, $deleted);
396
        }
397
        if (null !== $path) {
398
            if (null === $deleted) {
399
                $deleted = NodeInterface::DELETED_EXCLUDE;
0 ignored issues
show
Unused Code introduced by
$deleted 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...
400
            }
401
402
            return $this->findNodesByPath($path, $class);
403
        }
404
    }
405
406
    /**
407
     * Load node.
408
     *
409
     * @param string $id
410
     * @param string $path
411
     * @param string $class      Force set node type
412
     * @param bool   $multiple   Allow $id to be an array
413
     * @param bool   $allow_root Allow instance of root collection
414
     * @param bool   $deleted    How to handle deleted node
415
     *
416
     * @return NodeInterface
417
     */
418
    public function getNode($id = null, $path = null, $class = null, bool $multiple = false, bool $allow_root = false, int $deleted = NodeInterface::DELETED_EXCLUDE): NodeInterface
419
    {
420
        if (empty($id) && empty($path)) {
421
            if (true === $allow_root) {
422
                return $this->getRoot();
423
            }
424
425
            throw new Exception\InvalidArgument('neither parameter id nor p (path) was given');
426
        }
427
        if (null !== $id && null !== $path) {
428
            throw new Exception\InvalidArgument('parameter id and p (path) can not be used at the same time');
429
        }
430
        if (null !== $id) {
431
            if (null === $deleted) {
432
                $deleted = NodeInterface::DELETED_INCLUDE;
433
            }
434
435
            if (true === $multiple && is_array($id)) {
436
                return $this->findNodesById($id, $class, $deleted);
437
            }
438
439
            return $this->findNodeById($id, $class, $deleted);
440
        }
441
        if (null !== $path) {
442
            if (null === $deleted) {
443
                $deleted = NodeInterface::DELETED_EXCLUDE;
0 ignored issues
show
Unused Code introduced by
$deleted 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...
444
            }
445
446
            return $this->findNodeByPath($path, $class);
447
        }
448
    }
449
450
    /**
451
     * Find node with custom filter.
452
     *
453
     * @param array $filter
454
     *
455
     * @return NodeInterface
456
     */
457
    public function findNodeByFilter(array $filter): NodeInterface
458
    {
459
        $result = $this->db->storage->findOne($filter);
460
        if (null === $result) {
461
            throw new Exception\NotFound(
462
                'node with custom filter was not found',
463
                Exception\NotFound::NODE_NOT_FOUND
464
            );
465
        }
466
467
        return $this->initNode($result);
468
    }
469
470
    /**
471
     * Find nodes with custom filters.
472
     *
473
     * @param array $filter
474
     *
475
     * @return Generator
476
     */
477
    public function findNodesByFilter(array $filter): Generator
478
    {
479
        $result = $this->db->storage->find($filter);
480
        $list = [];
0 ignored issues
show
Unused Code introduced by
$list 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...
481
482
        foreach ($result as $node) {
483
            try {
484
                yield $this->initNode($node);
485
            } catch (\Exception $e) {
486
                $this->logger->info('remove node from result list, failed load node', [
487
                    'category' => get_class($this),
488
                    'exception' => $e,
489
                ]);
490
            }
491
        }
492
    }
493
494
    /**
495
     * Get custom filtered children.
496
     *
497
     * @param int   $deleted
498
     * @param array $filter
499
     *
500
     * @return Generator
501
     */
502
    public function findNodesByFilterUser(int $deleted, array $filter): Generator
503
    {
504
        if ($this->user instanceof User) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
505
//            $this->user->findNewShares();
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
506
        }
507
508
        $shares = $this->user->getShares();
509
        $stored_filter = ['$and' => [
510
            [],
511
            ['$or' => [
512
                ['owner' => $this->user->getId()],
513
                ['shared' => ['$in' => $shares]],
514
            ]],
515
        ]];
516
517
        if (NodeInterface::DELETED_EXCLUDE === $deleted) {
518
            $stored_filter['$and'][0]['deleted'] = false;
519
        } elseif (NodeInterface::DELETED_ONLY === $deleted) {
520
            $stored_filter['$and'][0]['deleted'] = ['$type' => 9];
521
        }
522
523
        $stored_filter['$and'][0] = array_merge($filter, $stored_filter['$and'][0]);
524
        $result = $this->db->storage->find($stored_filter);
525
526
        foreach ($result as $node) {
527
            try {
528
                yield $this->initNode($node);
529
            } catch (\Exception $e) {
530
                $this->logger->info('remove node from result list, failed load node', [
531
                    'category' => get_class($this),
532
                    'exception' => $e,
533
                ]);
534
            }
535
        }
536
    }
537
538
    /**
539
     * Init node.
540
     *
541
     * @param array $node
542
     *
543
     * @return NodeInterface
544
     */
545
    public function initNode(array $node): NodeInterface
546
    {
547
        if (isset($node['shared']) && true === $node['shared'] && null !== $this->user && $node['owner'] != $this->user->getId()) {
548
            $node = $this->findReferenceNode($node);
549
        }
550
551
        //this would result in a recursiv call until the top level node
552
        /*if (isset($node['parent'])) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
553
            try {
554
                $this->findNodeById($node['parent']);
555
            } catch (Exception\InvalidArgument $e) {
556
                throw new Exception\InvalidArgument('invalid parent node specified: '.$e->getMessage());
557
            } catch (Exception\NotFound $e) {
558
                throw new Exception\InvalidArgument('invalid parent node specified: '.$e->getMessage());
559
            }
560
        }*/
561
562
        if (!array_key_exists('directory', $node)) {
563
            throw new Exception('invalid node ['.$node['_id'].'] found, directory attribute does not exists');
564
        }
565
        if (true === $node['directory']) {
566
            $instance = new Collection($node, $this, $this->logger, $this->hook, $this->acl);
567
        } else {
568
            $instance = new File($node, $this, $this->logger, $this->hook, $this->acl, $this->storage);
569
        }
570
571
        if (!$this->acl->isAllowed($instance, 'r')) {
572
            throw new ForbiddenException(
573
                'not allowed to access node',
574
                ForbiddenException::NOT_ALLOWED_TO_ACCESS
575
            );
576
        }
577
578
        if (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...
579
            $this->logger->info('node ['.$node['_id'].'] is not accessible anmyore, destroy node cause of expired destroy flag', [
580
                'category' => get_class($this),
581
            ]);
582
583
            $instance->delete(true);
584
585
            throw new Exception\Conflict('node is not available anymore');
586
        }
587
588
        return $instance;
589
    }
590
591
    /**
592
     * Resolve shared node to reference or share depending who requested.
593
     *
594
     * @param array $node
595
     *
596
     * @return array
597
     */
598
    protected function findReferenceNode(array $node): array
599
    {
600
        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...
601
            $this->logger->debug('reference node ['.$node['_id'].'] requested from share owner, trying to find the shared node', [
602
                'category' => get_class($this),
603
            ]);
604
605
            $node = $this->db->storage->findOne([
606
                'owner' => $this->user->getId(),
607
                'shared' => true,
608
                '_id' => $node['reference'],
609
            ]);
610
611
            if (null === $node) {
612
                throw new Exception\NotFound(
613
                    'no share node for reference node '.$node['reference'].' found',
614
                    Exception\NotFound::SHARE_NOT_FOUND
615
                );
616
            }
617
        } else {
618
            $this->logger->debug('share node ['.$node['_id'].'] requested from member, trying to find the reference node', [
619
                'category' => get_class($this),
620
            ]);
621
622
            $node = $this->db->storage->findOne([
623
                'owner' => $this->user->getId(),
624
                'shared' => true,
625
                'reference' => $node['_id'],
626
            ]);
627
628
            if (null === $node) {
629
                throw new Exception\NotFound(
630
                    'no share reference for node '.$node['_id'].' found',
631
                    Exception\NotFound::REFERENCE_NOT_FOUND
632
                );
633
            }
634
        }
635
636
        return $node;
637
    }
638
}
639