Issues (61)

src/di/NewInstance.php (4 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ray\Di;
6
7
use Ray\Aop\Bind as AopBind;
8
use ReflectionClass;
9
use ReflectionException;
10
11
use function assert;
12
13
final class NewInstance
14
{
15
    /** @var class-string */
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
16
    private $class;
17
18
    /** @var SetterMethods */
19
    private $setterMethods;
20
21
    /** @var ?Arguments */
22
    private $arguments;
23
24
    /** @var ?AspectBind */
25
    private $bind;
26
27
    /**
28
     * @phpstan-param ReflectionClass<object> $class
29
     */
30
    public function __construct(
31
        ReflectionClass $class,
32
        SetterMethods $setterMethods,
33
        ?Name $constructorName = null
34
    ) {
35
        $constructorName = $constructorName ?: new Name(Name::ANY);
36
        $this->class = $class->getName();
37
        $constructor = $class->getConstructor();
38
        if ($constructor) {
39
            $this->arguments = new Arguments($constructor, $constructorName);
40
        }
41
42
        $this->setterMethods = $setterMethods;
43
    }
44
45
    /**
46
     * @throws ReflectionException
47
     */
48
    public function __invoke(Container $container): object
49
    {
50
        /** @psalm-suppress MixedMethodCall */
51
        $instance = $this->arguments instanceof Arguments ? (new ReflectionClass($this->class))->newInstanceArgs($this->arguments->inject($container)) : new $this->class();
52
53
        return $this->postNewInstance($container, $instance);
54
    }
55
56
    /**
57
     * @return class-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
58
     */
59
    public function __toString()
60
    {
61
        return $this->class;
62
    }
63
64
    /**
65
     * @param array<int, mixed> $params
66
     *
67
     * @throws ReflectionException
68
     */
69
    public function newInstanceArgs(Container $container, array $params): object
70
    {
71
        $instance = (new ReflectionClass($this->class))->newInstanceArgs($params);
72
73
        return $this->postNewInstance($container, $instance);
74
    }
75
76
    /**
77
     * @param class-string $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
78
     */
79
    public function weaveAspects(string $class, AopBind $bind): void
80
    {
81
        $this->class = $class;
82
        $this->bind = new AspectBind($bind);
83
    }
84
85
    public function accept(VisitorInterface $visitor): void
86
    {
87
        $visitor->visitNewInstance(
88
            $this->class,
89
            $this->setterMethods,
90
            $this->arguments,
91
            $this->bind
92
        );
93
    }
94
95
    private function postNewInstance(Container $container, object $instance): object
96
    {
97
        // bind dependency injected interceptors
98
        if ($this->bind instanceof AspectBind) {
99
            assert(isset($instance->bindings));
100
            $instance->bindings = $this->bind->inject($container);
101
        }
102
103
        // setter injection
104
        ($this->setterMethods)($instance, $container);
105
106
        return $instance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $instance could return the type object which is incompatible with the type-hinted return object. Consider adding an additional type-check to rule them out.
Loading history...
107
    }
108
}
109