Test Setup Failed
Push — master ( d81ac1...e02663 )
by Php Easy Api
04:31 queued 12s
created

ContainerResolve::getReflectionMethod()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 11
rs 10
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
        // if the parameter is an object and
55
        // this object is a service container object
56
        // then the parameter will bind.
57
        if($parameter->getType()!==null && isset($containers[$parameter->getType()->getName()])){
58
59
            // Unpack the container object and
60
            // bind it to the param variable.
61
            $parameterName = $parameter->getName();
62
63
            //get container object
64
            $resolveObject = $containers[$parameter->getType()->getName()];
65
66
            // if the container object is an object,
67
            // it is served directly without resolving it.
68
            $parameterResolve = (is_object($resolveObject))
69
                ? $resolveObject
70
                : app()->resolve($resolveObject);
71
72
            //return result for parameter of the container
73
            return [$parameterName=>$parameterResolve];
74
        }
75
76
        if($parameter->getType()!== NULL && Utils::isNamespaceExists($parameter->getType()->getName())){
77
78
            // Unpack the container object and
79
            // bind it to the param variable.
80
            $parameterName = $parameter->getName();
81
            $parameterResolve = app()->resolve($parameter->getType()->getName());
82
83
            //return result for parameter of the container
84
            return [$parameterName=>$parameterResolve];
85
        }
86
87
        return [];
88
89
    }
90
91
    /**
92
     * get reflection method
93
     *
94
     * @param $class
95
     * @return mixed
96
     */
97
    private function getReflectionMethod($class)
98
    {
99
        if(!isset($class[0],$class[1])){
100
            exception('containerResolvingMissing')
101
                ->runtime('Container class resolving is missing');
102
        }
103
104
        [$class,$method] = [$class[0],$class[1]];
105
106
        return $this->instanceReflection($this->app['reflection']($class))
107
            ->reflectionMethodParams($method);
108
    }
109
110
    /**
111
     * get instance reflection
112
     *
113
     * @param $instance
114
     * @return object|null
115
     */
116
    public function instanceReflection($instance=null)
117
    {
118
        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...
119
            static::$reflectionInstance = $instance;
120
        }
121
122
        return static::$reflectionInstance;
123
    }
124
    
125
    /**
126
     * reflection method parameters
127
     *
128
     * @param $class
129
     * @param $param
130
     * @return mixed
131
     *
132
     * @throws \ReflectionException
133
     */
134
    private function reflectionMethodParameters($class,$param)
135
    {
136
        $containers = [];
137
138
        //get service container objects.
139
        if(isset($this->app['serviceContainer'])){
140
            $containers = $this->app['serviceContainer'];
141
        }
142
143
        // With the reflection class we get the method.
144
        // and then we get the parameters in array.
145
        $reflection = $this->getReflectionMethod($class);
146
        $parameters = $reflection->parameters;
147
148
        // we provide the user with the container method document and take action.
149
        // thus, we help the methods to have a cleaner code structure.
150
        $this->app->resolve(ContainerMethodDocumentResolver::class,
151
            ['reflection'=>$this->instanceReflection(),'class'=>$class]);
152
153
        // we group the parameters into type and
154
        // name and bind them with the necessary logic.
155
        foreach ($parameters as $parameter){
156
157
            // if the parameter is an object and
158
            // this object is a service container object
159
            // then the parameter will bind.
160
            $checkParameterForContainer = $this->checkParameterForContainer($containers,$parameter);
161
            $paramMerge = array_merge($param,$checkParameterForContainer);
162
163
            // we do some useful logic bind for user benefit.
164
            $param = app()->resolve(GraceContainer::class,[
165
                'reflection' => $reflection->reflection
166
            ])->graceContainerBuilder($parameter,$paramMerge);
167
168
        }
169
170
        return $param;
171
    }
172
}