Completed
Push — sam-rework ( a5f68e...28559d )
by Andrii
10:44
created

ArrayDefinition   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 19
eloc 46
dl 0
loc 123
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getArray() 0 3 1
A getDependencies() 0 10 2
A resolve() 0 21 5
A buildFromArray() 0 26 5
A __construct() 0 3 1
A fromClassName() 0 3 1
A configure() 0 16 4
1
<?php
2
3
namespace yii\di\definitions;
4
5
use Psr\Container\ContainerInterface;
6
use yii\di\contracts\DefinitionInterface;
7
use yii\di\definitions\ValueDefinition;
8
use yii\di\resolvers\ClassNameResolver;
9
use yii\di\Reference;
10
11
/**
12
 * Class Resolver builds object by array config.
13
 * @package yii\di
14
 */
15
class ArrayDefinition implements DefinitionInterface
16
{
17
    private $config;
18
19
    private static $dependencies = [];
20
21
    /**
22
     * Injector constructor.
23
     * @param $container
24
     */
25
    public function __construct(array $config)
26
    {
27
        $this->config = $config;
28
    }
29
30
    public function getArray(): array
31
    {
32
        return $this->config;
33
    }
34
35
    public static function fromClassName(string $class)
36
    {
37
        return new static(['__class' => $class]);
38
    }
39
40
    /**
41
     * @param array $config
42
     * @param array $params
43
     */
44
    public function resolve(ContainerInterface $container, array $params = [])
45
    {
46
        $config = $this->config;
47
48
        if (empty($config['__class'])) {
49
            throw new NotInstantiableException(var_export($config, true));
0 ignored issues
show
Bug introduced by
The type yii\di\definitions\NotInstantiableException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
50
        }
51
52
        $class = $config['__class'];
53
        if ($container->has($class) && !$container->alreadyBuilding($class)) {
0 ignored issues
show
Bug introduced by
The method alreadyBuilding() does not exist on Psr\Container\ContainerInterface. It seems like you code against a sub-type of Psr\Container\ContainerInterface such as yii\di\Container. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
        if ($container->has($class) && !$container->/** @scrutinizer ignore-call */ alreadyBuilding($class)) {
Loading history...
54
            var_dump($class);die;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
Security Debugging Code introduced by
var_dump($class) looks like debug code. Are you sure you do not want to remove it?
Loading history...
55
            $this->already[$class] = 1;
0 ignored issues
show
Unused Code introduced by
$this->already[$class] = 1 is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
56
            $container->getDefinition($class)->merge($config)->resolve($container, $params);
57
            unset($this->already[$class]);
58
        }
59
60
        if (!empty($params)) {
61
            $config['__construct()'] = array_merge($config['__construct()'] ?? [], $params);
62
        }
63
64
        return $this->buildFromArray($container, $config);
65
    }
66
67
    private function buildFromArray(ContainerInterface $container, array $config)
68
    {
69
        if (empty($config['__class'])) {
70
            throw new NotInstantiableException(var_export($config, true));
71
        }
72
        $class = $config['__class'];
73
        unset($config['__class']);
74
75
        $dependencies = $this->getDependencies($class);
76
77
        if (isset($config['__construct()'])) {
78
            foreach (array_values($config['__construct()']) as $index => $param) {
79
                if ($param instanceof Reference) {
80
                    $dependencies[$index] = $param;
81
                } else {
82
                    $dependencies[$index] = new ValueDefinition($param);
83
                }
84
            }
85
            unset($config['__construct()']);
86
        }
87
88
        $resolved = $container->resolveDependencies($dependencies);
0 ignored issues
show
Bug introduced by
The method resolveDependencies() does not exist on Psr\Container\ContainerInterface. It seems like you code against a sub-type of Psr\Container\ContainerInterface such as yii\di\Container or yii\di\AbstractContainer. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
        /** @scrutinizer ignore-call */ 
89
        $resolved = $container->resolveDependencies($dependencies);
Loading history...
89
        $object = new $class(...$resolved);
90
        $this->configure($container, $object, $config);
0 ignored issues
show
Deprecated Code introduced by
The function yii\di\definitions\ArrayDefinition::configure() has been deprecated: Not recommended for explicit use. Added only to support Yii 2.0 behavior. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

90
        /** @scrutinizer ignore-deprecated */ $this->configure($container, $object, $config);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
91
92
        return $object;
93
    }
94
95
    /**
96
     * Returns the dependencies of the specified class.
97
     * @param string $class class name, interface name or alias name
98
     * @return DefinitionInterface[] the dependencies of the specified class.
99
     * @throws InvalidConfigException
100
     * @throws NotInstantiableException
101
     * @internal
102
     */
103
    private function getDependencies(string $class): array
104
    {
105
        if (!isset($this->dependencies[$class])) {
106
            // For now use hard coded resolver.
107
            $resolver = new ClassNameResolver();
108
109
            self::$dependencies[$class] = $resolver->resolveConstructor($class);
110
        }
111
112
        return self::$dependencies[$class];
113
    }
114
115
    /**
116
     * Configures an object with the given configuration.
117
     * @deprecated Not recommended for explicit use. Added only to support Yii 2.0 behavior.
118
     * @param object $object the object to be configured
119
     * @param iterable $config property values and methods to call
120
     * @return object the object itself
121
     */
122
    private function configure(ContainerInterface $container, $object, iterable $config)
123
    {
124
        foreach ($config as $action => $arguments) {
125
            if (substr($action, -2) === '()') {
126
                // method call
127
                \call_user_func_array([$object, substr($action, 0, -2)], $arguments);
128
            } else {
129
                // property
130
                if ($arguments instanceof DefinitionInterface) {
131
                    $arguments = $arguments->resolve($container);
132
                }
133
                $object->$action = $arguments;
134
            }
135
        }
136
137
        return $object;
138
    }
139
}
140