AttributesInjection::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Habemus\Autowiring\Attributes;
5
6
use Habemus\Autowiring\Reflector;
7
use Habemus\Exception\ContainerException;
8
use Habemus\Exception\InjectionException;
9
use Psr\Container\ContainerInterface;
10
use ReflectionClass;
11
use ReflectionParameter;
12
use ReflectionProperty;
13
14
class AttributesInjection
15
{
16
    /**
17
     * @var ContainerInterface
18
     */
19
    protected $container;
20
21
    /**
22
     * @var Reflector
23
     */
24
    protected $reflector;
25
26
    public function __construct(ContainerInterface $container, Reflector $reflector)
27
    {
28
        $this->reflector = $reflector;
29
        $this->container = $container;
30
    }
31
32
    public function inject($object)
33
    {
34
        if (!is_object($object)) {
35
            throw InjectionException::notAnObject($object);
36
        }
37
38
        $reflectionClass = new ReflectionClass($object);
39
        foreach ($reflectionClass->getProperties() as $property) {
40
            $injection = $this->getInjection($property);
41
            if (empty($injection)) {
42
                continue;
43
            }
44
45
            if (!$property->isPublic()) {
46
                $property->setAccessible(true);
47
            }
48
49
            if (!$this->container->has($injection)) {
50
                throw InjectionException::unresolvablePropertyInjection($property, $object);
51
            }
52
53
            $value = $this->container->get($injection);
54
            $property->setValue($object, $value);
55
        }
56
    }
57
58
    /**
59
     * @param ReflectionProperty|ReflectionParameter $subject
60
     * @return string|null
61
     * @throws InjectionException|ContainerException
62
     */
63
    public function getInjection($subject): ?string
64
    {
65
        /** @var Inject|null $inject */
66
        $inject = $this->reflector->getFirstAttribute($subject, Inject::class);
67
        if (! $inject instanceof Inject) {
68
            return null;
69
        }
70
71
        if (!empty($inject->getId())) {
72
            return $inject->getId();
73
        }
74
75
        $typeHint = $this->reflector->getTypeHint($subject, false);
76
        if (empty($typeHint)) {
77
            throw InjectionException::invalidInjection($subject);
78
        }
79
80
        return $typeHint;
81
    }
82
}
83