Passed
Push — main ( 25da7b...211f6f )
by Michael
13:47
created

HelpsProxies::getClassForResolution()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\EnhancedContainer\Traits;
6
7
use Illuminate\Support\Arr;
8
use MichaelRubel\EnhancedContainer\Exceptions\PropertyNotFoundException;
9
10
trait HelpsProxies
11
{
12
    /**
13
     * @param string      $class
14
     * @param array       $dependencies
15
     * @param string|null $context
16
     *
17
     * @return object
18
     */
19 57
    public function resolvePassedClass(string $class, array $dependencies = [], ?string $context = null): object
20
    {
21 57
        $class        = $this->getClassForResolution($class, $context);
22 57
        $dependencies = $this->getDependencies($class, $dependencies);
23
24 57
        return resolve($class, $dependencies);
25
    }
26
27
    /**
28
     * Get the class for resolution.
29
     *
30
     * @param string      $class
31
     * @param string|null $context
32
     *
33
     * @return string
34
     */
35 57
    public function getClassForResolution(string $class, ?string $context = null): string
36
    {
37 57
        return ! is_null($context) && isset(app()->contextual[$context])
38 1
            ? $this->getContextualConcrete($class, $context)
39 57
            : $class;
40
    }
41
42
    /**
43
     * Try to get the contextual concrete.
44
     *
45
     * @param string      $class
46
     * @param string|null $context
47
     *
48
     * @return string
49
     */
50 1
    public function getContextualConcrete(string $class, ?string $context = null): string
51
    {
52 1
        return app()->contextual[$context][$class] ?? $class;
53
    }
54
55
    /**
56
     * Resolve class dependencies.
57
     *
58
     * @param string $class
59
     * @param array  $dependencies
60
     *
61
     * @return array
62
     * @throws \ReflectionException
63
     */
64 57
    public function getDependencies(string $class, array $dependencies = []): array
65
    {
66 57
        if (! empty($dependencies) && ! Arr::isAssoc($dependencies)) {
67
            /** @var class-string $class */
68 2
            $constructor = (new \ReflectionClass($class))->getConstructor();
69
70 2
            if ($constructor) {
71 2
                $dependencies = $this->makeContainerParameters(
72 2
                    $constructor->getParameters(),
73
                    $dependencies
74
                );
75
            }
76
        }
77
78 57
        return $dependencies;
79
    }
80
81
    /**
82
     * @param object       $class
83
     * @param string       $method
84
     * @param array $parameters
85
     *
86
     * @return array
87
     * @throws \ReflectionException
88
     */
89 47
    public function getPassedParameters(object $class, string $method, array $parameters): array
90
    {
91 47
        if (empty($parameters)) {
92 24
            return $parameters;
93
        }
94
95 25
        $reflectionMethod = new \ReflectionMethod($class, $method);
96
97 25
        return $this->makeContainerParameters(
98 25
            $reflectionMethod->getParameters(),
99
            $parameters
100
        );
101
    }
102
103
    /**
104
     * Combine parameters to make it container-readable.
105
     *
106
     * @param array $parameters
107
     * @param array $toCombine
108
     *
109
     * @return array
110
     */
111 26
    public function makeContainerParameters(array $parameters, array $toCombine): array
112
    {
113 26
        return collect($parameters)
114 26
            ->slice(0, count($toCombine))
115 26
            ->map(fn ($param) => $param->getName())
116 26
            ->combine(array_slice($toCombine, 0, count($parameters)))
117 26
            ->all();
118
    }
119
120
    /**
121
     * Convert the object to its namespace.
122
     *
123
     * @param object|string $object
124
     *
125
     * @return string
126
     */
127 66
    public function convertToNamespace(object|string $object): string
128
    {
129 66
        return is_string($object)
130 53
            ? $object
131 66
            : $object::class;
132
    }
133
134
    /**
135
     * Handle property error.
136
     *
137
     * @param string $name
138
     * @param object $instance
139
     *
140
     * @throws PropertyNotFoundException
141
     */
142 3
    public function throwPropertyNotFoundException(string $name, object $instance): self
143
    {
144 3
        throw new PropertyNotFoundException(sprintf(
145 3
            'Call to undefined property %s::%s()',
146
            $name,
147 3
            $instance::class
148
        ));
149
    }
150
}
151