GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

FactoryHelperTrait   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 254
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 33
lcom 1
cbo 4
dl 0
loc 254
rs 9.3999
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getDefinition() 0 19 4
A constructObject() 0 17 2
A matchArguments() 0 17 4
A isTypeMatched() 0 10 3
A isRequiredClass() 0 11 3
A getCallableParameters() 0 19 3
A isInvocable() 0 6 3
A getObjectByClass() 0 11 2
A getObjectMethod() 0 13 4
A mergeMethods() 0 14 4
A getCommonMethods() 0 9 1
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Di
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Di\Factory;
16
17
use Phossa2\Di\Message\Message;
18
use Phossa2\Di\Resolver\ObjectResolver;
19
use Phossa2\Di\Exception\LogicException;
20
use Phossa2\Di\Traits\ResolverAwareTrait;
21
22
/**
23
 * FactoryHelperTrait
24
 *
25
 * Create service instance here
26
 *
27
 * @package Phossa2\Di
28
 * @author  Hong Zhang <[email protected]>
29
 * @version 2.0.0
30
 * @since   2.0.0 added
31
 */
32
trait FactoryHelperTrait
33
{
34
    use ResolverAwareTrait;
35
36
    /**
37
     * Get service definition
38
     *
39
     * @param  string $rawId
40
     * @param  array $args
41
     * @return array
42
     * @access protected
43
     */
44
    protected function getDefinition(
45
        /*# string */ $rawId,
46
        array $args
47
    )/*# : array */ {
48
        // get the definition
49
        $def = $this->getResolver()->getService($rawId);
50
51
        // fix class
52
        if (!is_array($def) || !isset($def['class'])) {
53
            $def = ['class' => $def];
54
        }
55
56
        // add arguments
57
        if (!empty($args)) {
58
            $def['args'] = $args;
59
        }
60
61
        return (array) $def;
62
    }
63
64
    /**
65
     * Instantiate service object from classname
66
     *
67
     * @param  string $class
68
     * @param  array $args
69
     * @return object
70
     * @throws LogicException if something goes wrong
71
     * @access protected
72
     */
73
    protected function constructObject(/*# string */ $class, array $args)
74
    {
75
        $reflector = new \ReflectionClass($class);
76
        $constructor = $reflector->getConstructor();
77
78
        // not constructor defined
79
        if (is_null($constructor)) {
80
            $obj = $reflector->newInstanceWithoutConstructor();
81
82
        // normal class with constructor
83
        } else {
84
            $args = $this->matchArguments($constructor->getParameters(), $args);
85
            $obj = $reflector->newInstanceArgs($args);
86
        }
87
88
        return $obj;
89
    }
90
91
    /**
92
     * Match provided arguments with a method/function's reflection parameters
93
     *
94
     * @param  \ReflectionParameter[] $reflectionParameters
95
     * @param  array $providedArguments
96
     * @return array the resolved arguments
97
     * @throws LogicException
98
     * @access protected
99
     */
100
    protected function matchArguments(
101
        array $reflectionParameters,
102
        array $providedArguments
103
    )/*# : array */ {
104
        // result
105
        $resolvedArguments = [];
106
        foreach ($reflectionParameters as $i => $param) {
107
            $class = $param->getClass();
108
109
            if ($this->isTypeMatched($class, $providedArguments)) {
110
                $resolvedArguments[$i] = array_shift($providedArguments);
111
            } elseif ($this->isRequiredClass($param, $providedArguments)) {
112
                $resolvedArguments[$i] = $this->getObjectByClass($class->getName());
113
            }
114
        }
115
        return array_merge($resolvedArguments, $providedArguments);
116
    }
117
118
    /**
119
     * Try best to guess parameter and argument are the same type
120
     *
121
     * @param  null|\ReflectionClass $class
122
     * @param  array $arguments
123
     * @return bool
124
     * @access protected
125
     */
126
    protected function isTypeMatched($class, array $arguments)/*# : bool */
127
    {
128
        if (empty($arguments)) {
129
            return false;
130
        } elseif (null !== $class) {
131
            return is_a($arguments[0], $class->getName());
132
        } else {
133
            return true;
134
        }
135
    }
136
137
    /**
138
     * Is $param required and is a class/interface
139
     *
140
     * @param  \ReflectionParameter $param
141
     * @param  array $arguments
142
     * @return bool
143
     * @throws LogicException if mismatched arguments
144
     * @access protected
145
     */
146
    protected function isRequiredClass(
147
        \ReflectionParameter $param,
148
        array $arguments
149
    )/*# : bool */ {
150
        $optional = $param->isOptional();
151
        if ($param->getClass()) {
152
            return !$optional || !empty($arguments);
153
        } else {
154
            return false;
155
        }
156
    }
157
158
    /**
159
     * Get callable parameters
160
     *
161
     * @param  callable $callable
162
     * @return \ReflectionParameter[]
163
     * @throws LogicException if something goes wrong
164
     * @access protected
165
     */
166
    protected function getCallableParameters(callable $callable)/*# : array */
167
    {
168
        // array type
169
        if (is_array($callable)) {
170
            $reflector = new \ReflectionClass($callable[0]);
171
            $method = $reflector->getMethod($callable[1]);
172
173
        // object with __invoke() defined
174
        } elseif ($this->isInvocable($callable)) {
175
            $reflector = new \ReflectionClass($callable);
176
            $method = $reflector->getMethod('__invoke');
177
178
        // simple function
179
        } else {
180
            $method = new \ReflectionFunction($callable);
181
        }
182
183
        return $method->getParameters();
184
    }
185
186
    /**
187
     * Is $var a non-closure object with '__invoke()' defined ?
188
     *
189
     * @param  mixed $var
190
     * @return bool
191
     * @access protected
192
     */
193
    protected function isInvocable($var)/*# : bool */
194
    {
195
        return is_object($var) &&
196
            !$var instanceof \Closure &&
197
            method_exists($var, '__invoke');
198
    }
199
200
    /**
201
     * Get an object base on provided classname or interface name
202
     *
203
     * @param  string $classname class or interface name
204
     * @return object
205
     * @throws \Exception if something goes wrong
206
     * @access protected
207
     */
208
    protected function getObjectByClass(/*# string */ $classname)
209
    {
210
        if ($this->getResolver()->hasService($classname)) {
211
            $serviceId = ObjectResolver::getServiceId($classname);
212
            return $this->getResolver()->get($serviceId);
213
        }
214
        throw new LogicException(
215
            Message::get(Message::DI_CLASS_UNKNOWN, $classname),
216
            Message::DI_CLASS_UNKNOWN
217
        );
218
    }
219
220
    /**
221
     * Returns [$object, $method] if it is a callable, otherwise returns $method
222
     *
223
     * @param  mixed $object
224
     * @param  mixed $method
225
     * @return bool
226
     * @access protected
227
     */
228
    protected function getObjectMethod($object, $method)/*# : bool */
229
    {
230
        if (is_string($method) && method_exists($object, $method)) {
231
            return [$object, $method];
232
        } elseif (is_callable($method)) {
233
            return $method;
234
        } else {
235
            throw new LogicException(
236
                Message::get(Message::DI_CALLABLE_BAD, $method),
237
                Message::DI_CALLABLE_BAD
238
            );
239
        }
240
    }
241
242
    /**
243
     * Merge different sections of a node
244
     *
245
     * convert
246
     *   `['section1' => [[1], [2]], 'section2' => [[3], [4]]]`
247
     *
248
     * to
249
     *   `[[1], [2], [3], [4]]`
250
     *
251
     * @param  array|null $nodeData
252
     * @return array
253
     * @access protected
254
     */
255
    protected function mergeMethods($nodeData)/*# : array */
256
    {
257
        // no merge
258
        if (empty($nodeData) || isset($nodeData[0])) {
259
            return (array) $nodeData;
260
        }
261
262
        // in sections
263
        $result = [];
264
        foreach ($nodeData as $data) {
265
            $result = array_merge($result, $data);
266
        }
267
        return $result;
268
    }
269
270
    /**
271
     * Get common methods
272
     *
273
     * @return array
274
     * @access protected
275
     */
276
    protected function getCommonMethods()/*# : array */
277
    {
278
        // di.common node
279
        $commNode = $this->getResolver()->getSectionId('', 'common');
280
281
        return $this->mergeMethods(
282
            $this->getResolver()->get($commNode)
283
        );
284
    }
285
}
286