Issues (15)

src/AbstractParametersContainer.php (1 issue)

Labels
Severity
1
<?php
2
/*
3
 * @copyright (c) 2018 Mendel <[email protected]>
4
 * @license see license.txt
5
 */
6
namespace drycart\di;
7
8
/**
9
 * Prepare parameters for call, using reflection
10
 * @see: AbstractCoreContainer
11
 * @author Mendel <[email protected]>
12
 */
13
abstract class AbstractParametersContainer
14
{
15
    /**
16
     * Contain array of callable for try transform parameters
17
     * @var array 
18
     */
19
    protected $transformers = [];
20
    
21
    /**
22
     * Prepare parameters using parameters array
23
     * @param array $dependency
24
     * @param array $parameters
25
     * @return array
26
     */
27
    protected function prepareParameters(array $dependency, array $parameters) : array
28
    {
29
        $preparedParameters = [];
30
        foreach ($dependency as $paramReflector) {
31
            $name = $paramReflector->name;
32
            $type = $paramReflector->getType();
33
            if (isset($parameters[$name])) {
34
                $value = $parameters[$name];
35
                $preparedParameters[] = $this->prepareValue($type, $value);
36
            } else {
37
                $preparedParameters[] = $this->getParameter($paramReflector);
38
            }
39
        }
40
        return $preparedParameters;
41
    }
42
    
43
    private function prepareValue($type, $value)
44
    {
45
        if (empty($type) or $type->isBuiltIn() or is_a($value, $type->getName())) {
46
            return $value;
47
        } elseif (is_array($value)) {
48
            $className = $value['#class'] ?? $type->getName();
49
            return $this->make($className, $value);
50
        } else {
51
            return $this->tryTransformValue($type->getName(), $value);
52
        }
53
    }
54
55
    /**
56
     * Try get parameter - from container or default
57
     * @param \ReflectionParameter $param
58
     * @return mixed
59
     */
60
    private function getParameter(\ReflectionParameter $param)
61
    {
62
        $type = $param->getType();
63
        if (!empty($type) and !$type->isBuiltIn()) {
64
            return $this->get($type->getName());
0 ignored issues
show
The method getName() does not exist on ReflectionType. It seems like you code against a sub-type of ReflectionType such as ReflectionNamedType. ( Ignorable by Annotation )

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

64
            return $this->get($type->/** @scrutinizer ignore-call */ getName());
Loading history...
65
        } elseif ($param->isDefaultValueAvailable()) {
66
            return $param->getDefaultValue();
67
        }elseif ($type->allowsNull()) {
68
            return null;
69
        } else {
70
            throw new ContainerException('Unknown parameter '.$param->name);
71
        }
72
    }
73
74
    private function tryTransformValue(string $className, $value)
75
    {
76
        foreach ($this->transformers as $transformer) {
77
            $value = $transformer($value, $className, $this);
78
            if (is_a($value, $className)) {
79
                return $value;
80
            }
81
        }
82
        throw new ContainerException('Wrong type of value for parameter. Need: '.$className);
83
    }
84
    
85
    /**
86
     * Finds an entry of the container by its identifier and returns it.
87
     *
88
     * @param string $id class name
89
     *
90
     * @throws NotFoundException No entry was found for **this** identifier.
91
     * @throws ContainerException Error while retrieving the entry.
92
     *
93
     * @return mixed
94
     */
95
    abstract public function get($id);
96
    
97
    /**
98
     * Create new object
99
     * @param string $id class name
100
     * @param array $parameters parameters from request
101
     * @return mixed
102
     * @throws ContainerException
103
     */
104
    abstract public function make(string $id, array $parameters = []);
105
}