SetterInjector::shouldBeInjected()   B
last analyzed

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