Passed
Pull Request — master (#35)
by Akmal
01:51
created

CreateObjectTrait::createMethodDepends()   B

Complexity

Conditions 10
Paths 9

Size

Total Lines 44
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 25
nc 9
nop 3
dl 0
loc 44
rs 7.6666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php declare(strict_types=1);
2
3
namespace OpenEngine\Mika\Core\Components\Di\Traits;
4
5
use OpenEngine\Mika\Core\Components\Di\Exceptions\ClassNotFoundException;
6
use OpenEngine\Mika\Core\Components\Di\Exceptions\MethodNotFoundException;
7
use OpenEngine\Mika\Core\Components\Di\Exceptions\MissingMethodArgumentException;
8
use OpenEngine\Mika\Core\Helpers\VarHelper;
9
use ReflectionClass;
10
use ReflectionNamedType;
11
12
trait CreateObjectTrait
13
{
14
    /**
15
     * @param string $className
16
     * @return object
17
     * @throws ClassNotFoundException
18
     * @throws MethodNotFoundException
19
     * @throws MissingMethodArgumentException
20
     */
21
    public function createObject(string $className): object
22
    {
23
        $params = $this->createMethodDepends($className, '__construct');
24
25
        try {
26
            $reflector = new ReflectionClass($className);
27
        } catch (\ReflectionException $e) {
28
            throw new ClassNotFoundException('Class ' . $className . ' is not found');
29
        }
30
31
        return $reflector->newInstanceArgs($params);
32
    }
33
34
    /**
35
     * Create method depends
36
     *
37
     * Method returns list of params with initialized depends.
38
     * All services for method will be initialized automatically.
39
     * Other params you must specify on parameter $knownParams.
40
     *
41
     * For example:
42
     * ```
43
     * class Foo {
44
     *      public method bar(BazInterface $baz, Baz2Interface $baz2, string $baz3, int $param4): void
45
     *      {
46
     *          // ... code ...
47
     *      }
48
     * }
49
     *
50
     * // $baz and $baz2 will initialized by automatically.
51
     * // $baz3 and $param4 you must specify
52
     * App::getContainer()->createMethodDepends(Foo::class, "bar", ['baz3' => 'Test', 'param4' => 13])
53
     *
54
     * ```
55
     *
56
     * @param string $className
57
     * @param string $methodName
58
     * @param array $knownParams You can specify some parameter values if you already know what method needs
59
     * @return array
60
     * @throws MethodNotFoundException
61
     * @throws MissingMethodArgumentException
62
     */
63
    public function createMethodDepends(string $className, string $methodName, array $knownParams = []): array
64
    {
65
        $result = [];
66
67
        /**
68
         * @var ReflectionNamedType $type
69
         */
70
        foreach ($this->getMethodParams($className, $methodName) as $name => $type) {
71
            if ($type !== null && !VarHelper::isScalar($type->getName())) {
72
                $result[$name] = $this->get($type->getName());
0 ignored issues
show
Bug introduced by
It seems like get() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

72
                /** @scrutinizer ignore-call */ 
73
                $result[$name] = $this->get($type->getName());
Loading history...
73
                continue;
74
            }
75
76
            if (!isset($knownParams[$name])) {
77
                throw new MissingMethodArgumentException('Missing argument ' . $name . ' for method ' . $methodName);
78
            }
79
80
            if ($type === null) {
81
                $result[$name] = $knownParams[$name];
82
                continue;
83
            }
84
85
            switch ($type->getName()) {
86
                case 'int':
87
                    $result[$name] = (int)$knownParams[$name];
88
                    break;
89
90
                case 'float':
91
                    $result[$name] = (float)$knownParams[$name];
92
                    break;
93
94
                case 'bool':
95
                    $result[$name] = (bool)$knownParams[$name];
96
                    break;
97
98
                case 'string':
99
                default:
100
                    $result[$name] = (string)$knownParams[$name];
101
                    break;
102
            }
103
        }
104
105
106
        return $result;
107
    }
108
109
    /**
110
     * @param string $className
111
     * @param string $methodName
112
     * @return array
113
     * @throws MethodNotFoundException
114
     */
115
    private function getMethodParams(string $className, string $methodName): array
116
    {
117
        $result = [];
118
119
        try {
120
            $method = new \ReflectionMethod($className, $methodName);
121
        } catch (\ReflectionException $e) {
122
            if ($methodName === '__construct') {
123
                return $result;
124
            }
125
126
            throw new MethodNotFoundException($e->getMessage());
127
        }
128
129
        foreach ($method->getParameters() as $parameter) {
130
            $result [$parameter->name] = $parameter->getType();
131
        }
132
133
        return $result;
134
    }
135
}
136