Completed
Push — master ( c89067...3b0f09 )
by Hong
04:25
created

AutowiringTrait::getObjectByClass()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
cc 4
nc 3
nop 1
1
<?php
2
3
/**
4
 * Phoole (PHP7.2+)
5
 *
6
 * @category  Library
7
 * @package   Phoole\Di
8
 * @copyright Copyright (c) 2019 Hong Zhang
9
 */
10
declare(strict_types=1);
11
12
namespace Phoole\Di\Util;
13
14
use Phoole\Di\Container;
15
use Phoole\Base\Reflect\ParameterTrait;
16
use Phoole\Di\Exception\UnresolvedClassException;
17
18
/**
19
 * AutowiringTrait
20
 *
21
 * @package Phoole\Di
22
 */
23
trait AutowiringTrait
24
{
25
    use ClassmapTrait;
26
    use ParameterTrait;
27
28
    /**
29
     * @var bool
30
     */
31
    protected $autoLoad = FALSE;
32
33
    /**
34
     * match provided arguments with defined parameters
35
     *
36
     * @param  array                  $providedArguments
37
     * @param  \ReflectionParameter[] $reflectionParameters
38
     * @return array
39
     * @throws UnresolvedClassException
40
     */
41
    protected function matchArguments(
42
        array $providedArguments,
43
        array $reflectionParameters
44
    ): array {
45
        $resolvedArguments = [];
46
        foreach ($reflectionParameters as $i => $param) {
47
            if ($this->isTypeMatched($param->getClass(), $providedArguments)) {
48
                $resolvedArguments[$i] = array_shift($providedArguments);
49
            } elseif ($this->isRequiredClass($param, $providedArguments)) {
50
                $resolvedArguments[$i] = $this->getObjectByClass($param->getClass()->getName());
0 ignored issues
show
Bug introduced by
Consider using $param->getClass()->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
51
            }
52
        }
53
        return array_merge($resolvedArguments, $providedArguments);
54
    }
55
56
    /**
57
     * Try best to guess parameter and argument are the same type
58
     *
59
     * @param  null|\ReflectionClass $class
60
     * @param  array                 $arguments
61
     * @return bool
62
     */
63
    protected function isTypeMatched($class, array $arguments): bool
64
    {
65
        if (empty($arguments)) {
66
            return FALSE;
67
        } elseif (NULL !== $class) {
68
            return is_a($arguments[0], $class->getName());
0 ignored issues
show
Bug introduced by
Consider using $class->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
69
        } else {
70
            return TRUE;
71
        }
72
    }
73
74
    /**
75
     * Is $param required and is a class/interface
76
     *
77
     * @param  \ReflectionParameter $param
78
     * @param  array                $arguments
79
     * @return bool
80
     */
81
    protected function isRequiredClass(\ReflectionParameter $param, array $arguments): bool
82
    {
83
        $optional = $param->isOptional();
84
        if ($param->getClass()) {
85
            return !$optional || !empty($arguments);
86
        } else {
87
            return FALSE;
88
        }
89
    }
90
91
    /**
92
     * @param  string $classname
93
     * @return object
94
     * @throws UnresolvedClassException
95
     */
96
    protected function getObjectByClass(string $classname): object
97
    {
98
        // try classmap
99
        $object = $this->matchClass($classname);
100
        if (is_object($object)) {
101
            return $object;
102
        }
103
104
        // try autoload
105
        if ($this->autoLoad && class_exists($classname)) {
106
            return Container::create($classname);
107
        }
108
109
        throw new UnresolvedClassException($classname);
110
    }
111
}