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.
Passed
Push — master ( 3c5463...84f915 )
by Hong
16:33
created

FactoryHelperTrait::constructObject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 17
rs 9.4285
cc 2
eloc 9
nc 2
nop 2
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
21
/**
22
 * FactoryHelperTrait
23
 *
24
 * Create service instance here
25
 *
26
 * @package Phossa2\Di
27
 * @author  Hong Zhang <[email protected]>
28
 * @version 2.0.0
29
 * @since   2.0.0 added
30
 */
31
trait FactoryHelperTrait
32
{
33
    /**
34
     * Get service definition
35
     *
36
     * @param  string $rawId
37
     * @param  array $args
38
     * @return array
39
     * @access protected
40
     */
41
    protected function getDefinition(
42
        /*# string */ $rawId,
43
        array $args
44
    )/*# : array */ {
45
        // get the definition
46
        $def = $this->getResolver()->getService($rawId);
0 ignored issues
show
Bug introduced by
It seems like getResolver() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
47
48
        // fix class
49
        if (!is_array($def) || !isset($def['class'])) {
50
            $def = ['class' => $def];
51
        }
52
53
        // add arguments
54
        if (!empty($args)) {
55
            $def['args'] = $args;
56
        }
57
58
        return (array) $def;
59
    }
60
61
    /**
62
     * Instantiate service object from classname
63
     *
64
     * @param  string $class
65
     * @param  array $args
66
     * @return object
67
     * @throws LogicException if something goes wrong
68
     * @access protected
69
     */
70
    protected function constructObject(/*# string */ $class, array $args)
71
    {
72
        $reflector = new \ReflectionClass($class);
73
        $constructor = $reflector->getConstructor();
74
75
        // not constructor defined
76
        if (is_null($constructor)) {
77
            $obj = $reflector->newInstanceWithoutConstructor();
78
79
        // normal class with constructor
80
        } else {
81
            $args = $this->matchArguments($constructor->getParameters(), $args);
82
            $obj = $reflector->newInstanceArgs($args);
83
        }
84
85
        return $obj;
86
    }
87
88
    /**
89
     * Match provided arguments with a method/function's reflection parameters
90
     *
91
     * @param  \ReflectionParameter[] $reflectionParameters
92
     * @param  array $providedArguments
93
     * @return array the resolved arguments
94
     * @throws LogicException
95
     * @access protected
96
     */
97
    protected function matchArguments(
98
        array $reflectionParameters,
99
        array $providedArguments
100
    )/*# : array */ {
101
        // result
102
        $resolvedArguments = [];
103
        foreach ($reflectionParameters as $i => $param) {
104
            $class = $param->getClass();
105
106
            if ($this->isTypeMatched($class, $providedArguments)) {
107
                $resolvedArguments[$i] = array_shift($providedArguments);
108
109
            } elseif ($this->isRequiredClass($param, $providedArguments)) {
110
                $resolvedArguments[$i] = $this->getObjectByClass($class->getName());
111
            }
112
        }
113
        return array_merge($resolvedArguments, $providedArguments);
114
    }
115
116
    /**
117
     * Try best to guess parameter and argument are the same type
118
     *
119
     * @param  null|\ReflectionClass $class
120
     * @param  array $arguments
121
     * @return bool
122
     * @access protected
123
     */
124
    protected function isTypeMatched($class, array $arguments)/*# : bool */
125
    {
126
        if (empty($arguments)) {
127
            return false;
128
        } elseif (null !== $class) {
129
            return is_a($arguments[0], $class->getName());
130
        } else {
131
            return true;
132
        }
133
    }
134
135
    /**
136
     * Is $param required and is a class/interface
137
     *
138
     * @param  \ReflectionParameter $param
139
     * @param  array $arguments
140
     * @return bool
141
     * @throws LogicException if mismatched arguments
142
     * @access protected
143
     */
144
    protected function isRequiredClass(
145
        \ReflectionParameter $param,
146
        array $arguments
147
    )/*# : bool */ {
148
        $optional = $param->isOptional();
149
        if ($param->getClass()) {
150
            return !$optional || !empty($arguments);
151
        } else {
152
            return false;
153
        }
154
    }
155
156
    /**
157
     * Get an object base on provided classname or interface name
158
     *
159
     * @param  string $classname class or interface name
160
     * @return object
161
     * @throws \Exception if something goes wrong
162
     * @access protected
163
     */
164
    protected function getObjectByClass(/*# string */ $classname)
165
    {
166
        if ($this->getResolver()->hasService($classname)) {
0 ignored issues
show
Bug introduced by
It seems like getResolver() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
167
            $serviceId = ObjectResolver::getServiceId($classname);
168
            return $this->getResolver()->get($serviceId);
0 ignored issues
show
Bug introduced by
It seems like getResolver() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
169
        } else {
170
            throw new LogicException(
171
                Message::get(Message::DI_CLASS_UNKNOWN, $classname),
172
                Message::DI_CLASS_UNKNOWN
173
            );
174
        }
175
    }
176
177
    /**
178
     * Get callable parameters
179
     *
180
     * @param  callable $callable
181
     * @return \ReflectionParameter[]
182
     * @throws LogicException if something goes wrong
183
     * @access protected
184
     */
185
    protected function getCallableParameters(callable $callable)/*# : array */
186
    {
187
        // array type
188
        if (is_array($callable)) {
189
            $reflector = new \ReflectionClass($callable[0]);
190
            $method = $reflector->getMethod($callable[1]);
191
192
        // object with __invoke() defined
193
        } elseif ($this->isInvocable($callable)) {
194
            $reflector = new \ReflectionClass($callable);
195
            $method = $reflector->getMethod('__invoke');
196
197
        // simple function
198
        } else {
199
            $method = new \ReflectionFunction($callable);
200
        }
201
202
        return $method->getParameters();
203
    }
204
205
    /**
206
     * Is $var a non-closure object with '__invoke()' defined ?
207
     *
208
     * @param  mixed $var
209
     * @return bool
210
     * @access protected
211
     */
212
    protected function isInvocable($var)/*# : bool */
213
    {
214
        return is_object($var) &&
215
            !$var instanceof \Closure &&
216
            method_exists($var, '__invoke');
217
    }
218
}
219