Passed
Pull Request — 2.4 (#2714)
by Maxime
03:44
created

ResourceClassResolver::getResourceClass()   F

Complexity

Conditions 21
Paths 164

Size

Total Lines 45
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 26
nc 164
nop 3
dl 0
loc 45
rs 3.6333
c 0
b 0
f 0

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
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Api;
15
16
use ApiPlatform\Core\Exception\InvalidArgumentException;
17
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
18
use ApiPlatform\Core\Util\ClassInfoTrait;
19
20
/**
21
 * {@inheritdoc}
22
 *
23
 * @author Kévin Dunglas <[email protected]>
24
 * @author Samuel ROZE <[email protected]>
25
 */
26
final class ResourceClassResolver implements ResourceClassResolverInterface
27
{
28
    use ClassInfoTrait;
29
30
    private $resourceNameCollectionFactory;
31
32
    public function __construct(ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory)
33
    {
34
        $this->resourceNameCollectionFactory = $resourceNameCollectionFactory;
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40
    public function getResourceClass($value, string $resourceClass = null, bool $strict = false): string
41
    {
42
        $type = \is_object($value) && !$value instanceof \Traversable ? $this->getObjectClass($value) : $resourceClass;
43
        $resourceClass = $resourceClass ?? $type;
44
45
        if (null === $resourceClass) {
46
            throw new InvalidArgumentException(sprintf('No resource class found.'));
47
        }
48
49
        $resolvedResourceClass = null;
50
        foreach ($this->resourceNameCollectionFactory->create() as $currentResourceClass) {
51
            if ($resourceClass === $currentResourceClass) {
52
                $resolvedResourceClass = $currentResourceClass;
53
            }
54
            if (null === $resolvedResourceClass && is_subclass_of($type, $currentResourceClass)) {
55
                $resolvedResourceClass = $currentResourceClass;
56
            }
57
        }
58
59
        if (null !== $resolvedResourceClass) {
0 ignored issues
show
introduced by
The condition null !== $resolvedResourceClass is always false.
Loading history...
60
            $resourceClass = $resolvedResourceClass;
61
        }
62
63
        $typeIsStrictResourceClass = $this->isStrictResourceClass($type);
0 ignored issues
show
Bug introduced by
It seems like $type can also be of type null; however, parameter $type of ApiPlatform\Core\Api\Res...isStrictResourceClass() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
        $typeIsStrictResourceClass = $this->isStrictResourceClass(/** @scrutinizer ignore-type */ $type);
Loading history...
64
        if ($strict && $typeIsStrictResourceClass) {
65
            return $type;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $type could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
66
        }
67
68
        $typeIsResourceClass = $this->isResourceClass($type);
0 ignored issues
show
Bug introduced by
It seems like $type can also be of type null; however, parameter $type of ApiPlatform\Core\Api\Res...lver::isResourceClass() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
        $typeIsResourceClass = $this->isResourceClass(/** @scrutinizer ignore-type */ $type);
Loading history...
69
        if (
70
            null === $type
71
            || (((!$strict || $resourceClass === $type)) && $typeIsResourceClass)
72
            || null !== $resolvedResourceClass && (interface_exists($resourceClass) || !$typeIsStrictResourceClass)
73
        ) {
74
            return $resourceClass;
75
        }
76
77
        if (
78
            $typeIsResourceClass
79
            || (is_subclass_of($type, $resourceClass) && $this->isResourceClass($resourceClass))
80
        ) {
81
            return $type;
82
        }
83
84
        throw new InvalidArgumentException(sprintf('No resource class found for object of type "%s".', $type));
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function isResourceClass(string $type): bool
91
    {
92
        foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
93
            if ($type === $resourceClass || is_subclass_of($type, $resourceClass)) {
94
                return true;
95
            }
96
        }
97
98
        return false;
99
    }
100
101
    /**
102
     * Same of isResourceClass but stricter: it ignores inheritance.
103
     *
104
     * @param string $type FQCN of an object
105
     */
106
    private function isStrictResourceClass(string $type): bool
107
    {
108
        foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
109
            if ($type === $resourceClass) {
110
                return true;
111
            }
112
        }
113
114
        return false;
115
    }
116
}
117