Passed
Push — master ( 02eddd...2aa0cc )
by mcfog
02:49 queued 18s
created

SetterInjector::shouldBeInjected()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 7

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 18
ccs 10
cts 10
cp 1
rs 8.8333
cc 7
nc 5
nop 1
crap 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Lit\Air\Injection;
6
7
use Lit\Air\Factory;
8
use ReflectionMethod;
9
10
/**
11
 * SetterInjector inject dependencies into an object by it's setter method.
12
 * By default only method with name injectXXX and with single parameter will be considered.
13
 */
14
class SetterInjector implements InjectorInterface
15
{
16
    protected $prefixes = ['inject'];
17
18
    /**
19
     * SetterInjector constructor.
20
     *
21
     * @param array|string[] $prefixes Method prefix(es) to scan.
22
     */
23 1
    public function __construct(array $prefixes = ['inject'])
24
    {
25 1
        $this->prefixes = $prefixes;
26 1
    }
27
28 1
    public function inject(Factory $factory, $obj, array $extra = []): void
29
    {
30 1
        $class = new \ReflectionClass($obj);
31 1
        foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
32 1
            if (!$this->shouldBeInjected($method)) {
33 1
                continue;
34
            }
35 1
            $parameter = $method->getParameters()[0];
36 1
            $paramClassName = null;
37 1
            $keys = [$parameter->name];
38 1
            $paramClass = $parameter->getClass();
39 1
            if (!empty($paramClass)) {
40 1
                $keys[] = $paramClassName = $paramClass->name;
41
            }
42
43 1
            $value = $factory->resolveDependency($class->name, $keys, $paramClassName, $extra);
44 1
            $method->invoke($obj, $value);
45
        }
46 1
    }
47
48 1
    public function isTarget($obj): bool
49
    {
50 1
        $class = get_class($obj);
51 1
        return defined("$class::SETTER_INJECTOR") && $class::SETTER_INJECTOR === static::class;
52
    }
53
54
    public function setPrefixes(array $prefixes): self
55
    {
56
        $this->prefixes = $prefixes;
57
        return $this;
58
    }
59
60 1
    protected function shouldBeInjected(ReflectionMethod $method)
61
    {
62 1
        if ($method->isStatic() || $method->isAbstract()) {
63 1
            return false;
64
        }
65 1
        $parameter = $method->getParameters();
66
        if (
67 1
            count($parameter) !== 1 || $parameter[0]->isOptional()
68
        ) {
69 1
            return false;
70
        }
71
72 1
        foreach ($this->prefixes as $prefix) {
73 1
            if (substr($method->name, 0, strlen($prefix)) === $prefix) {
74 1
                return true;
75
            }
76
        }
77 1
        return false;
78
    }
79
80
    /**
81
     * Configuration method of setter injector.
82
     *
83
     * @return array
84
     */
85
    public static function configuration()
86
    {
87
        return [
88
            Factory::KEY_INJECTORS => [
89
                new SetterInjector(),
90
            ],
91
        ];
92
    }
93
}
94