Test Setup Failed
Push — master ( 5a8c02...b263db )
by Php Easy Api
04:16
created

ContainerResolve::checkParameterForContainer()   B

Complexity

Conditions 9
Paths 16

Size

Total Lines 48
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 19
nc 16
nop 2
dl 0
loc 48
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
namespace Resta\Container;
4
5
use Resta\Support\Utils;
6
use Resta\Support\ReflectionProcess;
7
use Resta\Foundation\ApplicationProvider;
8
9
class ContainerResolve extends ApplicationProvider
10
{
11
    /**
12
     * @var null|object
13
     */
14
    private static $reflectionInstance;
15
16
    /**
17
     * container call process with pipeline
18
     *
19
     * @param $class
20
     * @param $param
21
     * @param callable $callback
22
     * @return mixed
23
     *
24
     * @throws \ReflectionException
25
     */
26
    public function call($class,$param,callable $callback)
27
    {
28
        // We use the reflection class to solve
29
        // the parameters of the class's methods.
30
        $param = $this->reflectionMethodParameters($class,$param);
31
32
        // the results of a number of processes will be given
33
        // before the container pipeline method is given.
34
        return $this->app->resolve(ContainerPipelineResolve::class)->handle(
35
            function() use($class,$param,$callback)
36
            {
37
                // as a result
38
                // we return the resolved class to the callback class
39
                $params = (object)['class'=>$class,'param'=>$param];
40
                return call_user_func_array($callback,[$params]);
41
            });
42
43
    }
44
45
    /**
46
     * check parameter for container
47
     *
48
     * @param $containers
49
     * @param $parameter
50
     * @return array
51
     */
52
    private function checkParameterForContainer($containers,$parameter)
53
    {
54
        $containerParameterNameValue = false;
55
56
        if(isset($containers[$parameter->getType()->getName()])){
57
            $parameterNameResolve = $parameter->getType()->getName();
58
            $containerParameterNameValue = true;
59
        }
60
61
        if(!$containerParameterNameValue && isset($containers[$parameter->getName()])){
62
            $parameterNameResolve = $parameter->getName();
63
            $containerParameterNameValue = true;
64
        }
65
66
        // if the parameter is an object and
67
        // this object is a service container object
68
        // then the parameter will bind.
69
        if($parameter->getType()!==null && $containerParameterNameValue){
70
71
            // Unpack the container object and
72
            // bind it to the param variable.
73
            $parameterName = $parameter->getName();
74
75
            //get container object
76
            $resolveObject = $containers[$parameterNameResolve];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $parameterNameResolve does not seem to be defined for all execution paths leading up to this point.
Loading history...
77
78
            // if the container object is an object,
79
            // it is served directly without resolving it.
80
            $parameterResolve = (is_object($resolveObject))
81
                ? $resolveObject
82
                : app()->resolve($resolveObject);
83
84
            //return result for parameter of the container
85
            return [$parameterName=>$parameterResolve];
86
        }
87
88
        if($parameter->getType()!== NULL && Utils::isNamespaceExists($parameterNameResolve)){
89
90
            // Unpack the container object and
91
            // bind it to the param variable.
92
            $parameterName = $parameter->getName();
93
            $parameterResolve = app()->resolve($parameterNameResolve);
94
95
            //return result for parameter of the container
96
            return [$parameterName=>$parameterResolve];
97
        }
98
99
        return [];
100
101
    }
102
103
    /**
104
     * get reflection method
105
     *
106
     * @param $class
107
     * @return mixed
108
     */
109
    private function getReflectionMethod($class)
110
    {
111
        if(!isset($class[0],$class[1])){
112
            exception('containerResolvingMissing')
113
                ->runtime('Container class resolving is missing');
114
        }
115
116
        [$class,$method] = [$class[0],$class[1]];
117
118
        return $this->instanceReflection($this->app['reflection']($class))
119
            ->reflectionMethodParams($method);
120
    }
121
122
    /**
123
     * get instance reflection
124
     *
125
     * @param $instance
126
     * @return object|null
127
     */
128
    public function instanceReflection($instance=null)
129
    {
130
        if(is_object($instance) && is_null(static::$reflectionInstance)){
0 ignored issues
show
Bug introduced by
Since $reflectionInstance is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $reflectionInstance to at least protected.
Loading history...
131
            static::$reflectionInstance = $instance;
132
        }
133
134
        return static::$reflectionInstance;
135
    }
136
137
    /**
138
     * reflection method parameters
139
     *
140
     * @param $class
141
     * @param $param
142
     * @return mixed
143
     *
144
     * @throws \ReflectionException
145
     */
146
    private function reflectionMethodParameters($class,$param)
147
    {
148
        $containers = [];
149
150
        //get service container objects.
151
        if(isset($this->app['serviceContainer'])){
152
            $containers = $this->app['serviceContainer'];
153
        }
154
155
        // With the reflection class we get the method.
156
        // and then we get the parameters in array.
157
        $reflection = $this->getReflectionMethod($class);
158
        $parameters = $reflection->parameters;
159
160
161
        // we provide the user with the container method document and take action.
162
        // thus, we help the methods to have a cleaner code structure.
163
        $this->app->resolve(ContainerMethodDocumentResolver::class,
164
            ['reflection'=>$this->instanceReflection(),'class'=>$class]);
165
166
        // we group the parameters into type and
167
        // name and bind them with the necessary logic.
168
        foreach ($parameters as $parameter){
169
170
            // if the parameter is an object and
171
            // this object is a service container object
172
            // then the parameter will bind.
173
            $checkParameterForContainer = $this->checkParameterForContainer($containers,$parameter);
174
175
            $paramMerge = array_merge($param,$checkParameterForContainer);
176
177
            // we do some useful logic bind for user benefit.
178
            $param = app()->resolve(GraceContainer::class,[
179
                'reflection' => $reflection->reflection
180
            ])->graceContainerBuilder($parameter,$paramMerge);
181
182
        }
183
184
        return $param;
185
    }
186
}