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.
Completed
Push — master ( 98ccbf...73e071 )
by Hong
03:32
created

FactoryTrait::getObjectByClass()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 24
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 1
Metric Value
c 4
b 0
f 1
dl 0
loc 24
rs 8.9713
cc 3
eloc 11
nc 4
nop 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\Traits;
16
17
use Phossa2\Di\Container;
18
use Phossa2\Di\Exception\LogicException;
19
use Phossa2\Di\Resolver\ObjectResolver;
20
use Phossa2\Di\Message\Message;
21
22
/**
23
 * FactoryTrait
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 FactoryTrait
33
{
34
    /**
35
     * @var    Container
36
     * @access protected
37
     */
38
    protected $master;
39
40
    /**
41
     * Get service definition (and fix it)
42
     *
43
     * @param  string $rawId
44
     * @param  array $args
45
     * @return array
46
     * @access protected
47
     */
48
    protected function getDefinition(
49
        /*# string */ $rawId,
50
        array $args
51
    )/*# : array */ {
52
        // get the definition
53
        $def = $this->master->getResolver()->getService($rawId);
54
55
        // fix class
56
        if (!is_array($def) || !isset($def['class'])) {
57
            $def = ['class' => $def];
58
        }
59
60
        // add resolved arguments
61
        if (!empty($args)) {
62
            $this->master->resolve($args);
63
            $def['args'] = $args;
64
        }
65
66
        return (array) $def;
67
    }
68
69
    /**
70
     * Instantiate service object from classname
71
     *
72
     * @param  string $class
73
     * @param  array $args
74
     * @return object
75
     * @throws LogicException if something goes wrong
76
     * @access protected
77
     */
78
    protected function constructObject(/*# string */ $class, array $args)
79
    {
80
        $reflector = new \ReflectionClass($class);
81
        $constructor = $reflector->getConstructor();
82
83
        // not constructor defined
84
        if (is_null($constructor)) {
85
            $obj = $reflector->newInstanceWithoutConstructor();
86
87
        // normal class with constructor
88
        } else {
89
            $args = $this->matchArguments(
90
                $constructor->getParameters(),
91
                $args
92
            );
93
            $obj = $reflector->newInstanceArgs($args);
94
        }
95
96
        return $obj;
97
    }
98
99
    /**
100
     * Match provided arguments with a method/function's reflection parameters
101
     *
102
     * @param  \ReflectionParameter[] $reflectionParameters
103
     * @param  array $providedArguments
104
     * @return array the resolved arguments
105
     * @throws LogicException
106
     * @access protected
107
     */
108
    protected function matchArguments(
109
        array $reflectionParameters,
110
        array $providedArguments
111
    )/*# : array */ {
112
        // result
113
        $resolvedArguments = [];
114
        foreach ($reflectionParameters as $i => $param) {
115
            $class = $param->getClass();
116
117
            if ($this->isTypeMatched($class, $providedArguments)) {
118
                $resolvedArguments[$i] = array_shift($providedArguments);
119
120
            } elseif ($this->isRequiredClass($param, $providedArguments)) {
121
                $resolvedArguments[$i] = $this->getObjectByClass($class->getName());
122
            }
123
        }
124
        return array_merge($resolvedArguments, $providedArguments);
125
    }
126
127
    /**
128
     * Try best to guess parameter and argument are the same type
129
     *
130
     * @param  null|\ReflectionClass $class
131
     * @param  array $arguments
132
     * @return bool
133
     * @access protected
134
     */
135
    protected function isTypeMatched($class, array $arguments)/*# : bool */
136
    {
137
        if (empty($arguments)) {
138
            return false;
139
        } elseif (null !== $class) {
140
            return is_a($arguments[0], $class->getName());
141
        } else {
142
            return true;
143
        }
144
    }
145
146
    /**
147
     * Is $param required and is a class/interface
148
     *
149
     * @param  \ReflectionParameter $param
150
     * @param  array $arguments
151
     * @return bool
152
     * @throws LogicException if mismatched arguments
153
     * @access protected
154
     */
155
    protected function isRequiredClass(
156
        \ReflectionParameter $param,
157
        array $arguments
158
    )/*# : bool */ {
159
        $optional = $param->isOptional();
160
        if ($param->getClass()) {
161
            return !$optional || !empty($arguments);
162
        } else {
163
            return false;
164
        }
165
    }
166
167
    /**
168
     * Get an object base on provided classname or interface name
169
     *
170
     * @param  string $classname class or interface name
171
     * @return object
172
     * @throws \Exception if something goes wrong
173
     * @access protected
174
     */
175
    protected function getObjectByClass(/*# string */ $classname)
176
    {
177
        $mapped = $classname;
178
179
        // resolve mapping
180
        if ($this->master->getResolver()->hasMapping($classname)) {
181
            $mapped = $this->master->getResolver()->getMapping($classname);
182
        }
183
184
        // get object by mapping or classname
185
        $obj = $this->getObjectByType($mapped, $classname);
186
187
        // found
188
        if (is_a($obj, $classname, false)) {
189
            return $obj;
190
191
        // failure
192
        } else {
193
            throw new LogicException(
194
                Message::get(Message::DI_CLASS_UNKNOWN, $classname),
195
                Message::DI_CLASS_UNKNOWN
196
            );
197
        }
198
    }
199
200
    /**
201
     * Get callable parameters
202
     *
203
     * @param  callable $callable
204
     * @return \ReflectionParameter[]
205
     * @throws LogicException if something goes wrong
206
     * @access protected
207
     */
208
    protected function getCallableParameters(callable $callable)/*# : array */
209
    {
210
        // array type
211
        if (is_array($callable)) {
212
            $reflector = new \ReflectionClass($callable[0]);
213
            $method = $reflector->getMethod($callable[1]);
214
215
        // object with __invoke() defined
216
        } elseif ($this->isInvocable($callable)) {
217
            $reflector = new \ReflectionClass($callable);
218
            $method = $reflector->getMethod('__invoke');
219
220
        // simple function
221
        } else {
222
            $method = new \ReflectionFunction($callable);
223
        }
224
225
        return $method->getParameters();
226
    }
227
228
    /**
229
     * Is $var a non-closure object with '__invoke()' defined ?
230
     *
231
     * @param  mixed $var
232
     * @return bool
233
     * @access protected
234
     */
235
    protected function isInvocable($var)/*# : bool */
236
    {
237
        return is_object($var) &&
238
            !$var instanceof \Closure &&
239
            method_exists($var, '__invoke');
240
    }
241
242
    /**
243
     * Get object by different mapped
244
     *
245
     * @param  mixed $mapped
246
     * @param  string $classname
247
     * @return object
248
     * @access protected
249
     */
250
    protected function getObjectByType($mapped, /*# string */ $classname)
251
    {
252
        // matched object
253
        if (is_a($mapped, $classname, false)) {
254
            return $mapped;
255
        }
256
257
        // callable
258
        if (is_callable($mapped)) {
259
            $mapped = call_user_func($mapped);
1 ignored issue
show
Coding Style introduced by
Consider using a different name than the parameter $mapped. This often makes code more readable.
Loading history...
260
        }
261
262
        // string
263
        if (is_string($mapped)) {
264
            $serviceId = ObjectResolver::getServiceId($mapped);
265
            $mapped = $this->master->getResolver()->get($serviceId);
1 ignored issue
show
Coding Style introduced by
Consider using a different name than the parameter $mapped. This often makes code more readable.
Loading history...
266
        }
267
268
        return $mapped;
269
    }
270
271
    /**
272
     * Merge different sections of a node
273
     *
274
     * convert
275
     *   `['section1' => [[1], [2]], 'section2' => [[3], [4]]]`
276
     *
277
     * to
278
     *   `[[1], [2], [3], [4]]`
279
     *
280
     * @param  array $nodeData
281
     * @return array
282
     * @access protected
283
     */
284
    protected function mergeMethods(array $nodeData)/*# : array */
285
    {
286
        // no merge
287
        if (empty($nodeData) || isset($nodeData[0])) {
288
            return $nodeData;
289
        }
290
291
        // in sections
292
        $result = [];
293
        foreach ($nodeData as $data) {
294
            $result = array_merge($result, $data);
295
        }
296
        return $result;
297
    }
298
}
299