Passed
Pull Request — main (#4)
by Michael
03:20
created

InteractsWithContainer::getPassedParameters()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 2
nop 3
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\EnhancedContainer\Traits;
6
7
use Illuminate\Support\Arr;
8
9
trait InteractsWithContainer
10
{
11
    /**
12
     * @param  string|object  $class
13
     * @param  array  $dependencies
14
     * @param  string|null  $context
15
     *
16
     * @return object
17
     */
18 59
    public function resolvePassedClass(string|object $class, array $dependencies = [], ?string $context = null): object
19
    {
20 59
        if (is_object($class)) {
21 16
            return $class;
22
        }
23
24 46
        $class = $this->getClassForResolution($class, $context);
25 46
        $dependencies = $this->getDependencies($class, $dependencies);
26
27 46
        return resolve($class, $dependencies);
28
    }
29
30
    /**
31
     * Get the class for resolution.
32
     *
33
     * @param  string  $class
34
     * @param  string|null  $context
35
     *
36
     * @return string
37
     */
38 46
    public function getClassForResolution(string $class, ?string $context = null): string
39
    {
40 46
        return ! is_null($context) && isset(app()->contextual[$context])
41 1
            ? $this->getContextualConcrete($class, $context)
42 46
            : $class;
43
    }
44
45
    /**
46
     * Try to get the contextual concrete.
47
     *
48
     * @param  string  $class
49
     * @param  string|null  $context
50
     *
51
     * @return string
52
     */
53 1
    public function getContextualConcrete(string $class, ?string $context = null): string
54
    {
55 1
        return app()->contextual[$context][$class] ?? $class;
56
    }
57
58
    /**
59
     * Try to get binding concrete.
60
     *
61
     * @param  string  $class
62
     *
63
     * @return string
64
     * @throws \ReflectionException
65
     */
66 1
    public function getBindingConcrete(string $class): string
67
    {
68
        return (
69 1
           new \ReflectionFunction(
70 1
               app()->getBindings()[$class]['concrete']
71
           )
72 1
        )->getStaticVariables()['concrete'];
73
    }
74
75
    /**
76
     * Resolve class dependencies.
77
     *
78
     * @param  string  $class
79
     * @param  array  $dependencies
80
     *
81
     * @return array
82
     * @throws \ReflectionException
83
     */
84 46
    public function getDependencies(string $class, array $dependencies = []): array
85
    {
86 46
        if (! empty($dependencies) && ! Arr::isAssoc($dependencies)) {
87 3
            if (! class_exists($class)) {
88 1
                $class = $this->getBindingConcrete($class);
89
            }
90
91
            /** @var class-string $class */
92 3
            $constructor = (new \ReflectionClass($class))->getConstructor();
93
94 3
            if ($constructor) {
95 2
                $dependencies = $this->makeContainerParameters(
96 2
                    $constructor->getParameters(),
97
                    $dependencies
98
                );
99
            }
100
        }
101
102 46
        return $dependencies;
103
    }
104
105
    /**
106
     * @param  object  $class
107
     * @param  string  $method
108
     * @param  array  $parameters
109
     *
110
     * @return array
111
     * @throws \ReflectionException
112
     */
113 51
    public function getPassedParameters(object $class, string $method, array $parameters): array
114
    {
115 51
        if (empty($parameters) || Arr::isAssoc($parameters)) {
116 26
            return $parameters;
117
        }
118
119 28
        return $this->makeContainerParameters(
120 28
            (new \ReflectionMethod($class, $method))->getParameters(),
121
            $parameters
122
        );
123
    }
124
125
    /**
126
     * Combine parameters to make it container-readable.
127
     *
128
     * @param  array  $reflectionParameters
129
     * @param  array  $methodParameters
130
     *
131
     * @return array
132
     */
133 26
    public function makeContainerParameters(array $reflectionParameters, array $methodParameters): array
134
    {
135 26
        return collect($this->sliceParameters($reflectionParameters, $methodParameters))
0 ignored issues
show
Bug introduced by
$this->sliceParameters($...ers, $methodParameters) of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

135
        return collect(/** @scrutinizer ignore-type */ $this->sliceParameters($reflectionParameters, $methodParameters))
Loading history...
136 26
            ->map->getName()
137 26
            ->combine($this->sliceParameters($methodParameters, $reflectionParameters))
138 26
            ->all();
139
    }
140
141
    /**
142
     * Slice an array to align the parameters.
143
     *
144
     * @param  array  $parameters
145
     * @param  array  $countable
146
     *
147
     * @return array
148
     */
149 26
    public function sliceParameters(array $parameters, array $countable): array
150
    {
151 26
        return array_slice($parameters, 0, count($countable));
152
    }
153
154
    /**
155
     * Convert the object to its namespace.
156
     *
157
     * @param  object|string  $object
158
     *
159
     * @return string
160
     */
161 37
    public function convertToNamespace(object|string $object): string
162
    {
163 37
        return is_string($object) ? $object : $object::class;
164
    }
165
}
166