Issues (125)

src/ClassResolver.php (3 issues)

1
<?php
2
3
/**
4
 * It's free open-source software released under the MIT License.
5
 *
6
 * @author Anatoly Nekhay <[email protected]>
7
 * @copyright Copyright (c) 2018, Anatoly Nekhay
8
 * @license https://github.com/sunrise-php/http-router/blob/master/LICENSE
9
 * @link https://github.com/sunrise-php/http-router
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sunrise\Http\Router;
15
16
use InvalidArgumentException;
17
use Psr\Container\ContainerExceptionInterface;
18
use Psr\Container\ContainerInterface;
19
use ReflectionClass;
20
use ReflectionException;
21
22
use function class_exists;
23
use function sprintf;
24
25
/**
26
 * @since 3.0.0
27
 */
28
final class ClassResolver implements ClassResolverInterface
29
{
30
    /**
31
     * @var array<class-string, object>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string, object> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string, object>.
Loading history...
32
     */
33
    private array $resolvedClasses = [];
34
35 10
    public function __construct(
36
        private readonly ParameterResolverChainInterface $parameterResolverChain,
37
        private readonly ?ContainerInterface $container = null,
38
    ) {
39 10
    }
40
41
    /**
42
     * {@inheritDoc}
43
     *
44
     * @param class-string<T> $className
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>.
Loading history...
45
     *
46
     * @return T
47
     *
48
     * @template T of object
49
     *
50
     * @throws ContainerExceptionInterface
51
     * @throws InvalidArgumentException
52
     * @throws ReflectionException
53
     */
54 7
    public function resolveClass(string $className): object
55
    {
56 7
        if ($this->container?->has($className) === true) {
57
            /** @var T */
58 2
            return $this->container->get($className);
0 ignored issues
show
The method get() does not exist on null. ( Ignorable by Annotation )

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

58
            return $this->container->/** @scrutinizer ignore-call */ get($className);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
59
        }
60
61 5
        if (isset($this->resolvedClasses[$className])) {
62
            /** @var T */
63 1
            return $this->resolvedClasses[$className];
64
        }
65
66 5
        if (!class_exists($className)) {
67 1
            throw new InvalidArgumentException(sprintf('The class "%s" does not exist.', $className));
68
        }
69
70
        /** @var ReflectionClass<T> $classReflection */
71 4
        $classReflection = new ReflectionClass($className);
72
73 4
        if (!$classReflection->isInstantiable()) {
74 1
            throw new InvalidArgumentException(sprintf('The class "%s" is not instantiable.', $className));
75
        }
76
77 3
        $this->resolvedClasses[$className] = $classReflection->newInstance(
78 3
            ...$this->parameterResolverChain->resolveParameters(
79 3
                ...($classReflection->getConstructor()?->getParameters() ?? [])
80 3
            )
81 3
        );
82
83 3
        return $this->resolvedClasses[$className];
84
    }
85
}
86