InteractsWithContainer   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 117
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 18
eloc 34
c 3
b 0
f 0
dl 0
loc 117
ccs 45
cts 45
cp 1
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A convertToNamespace() 0 3 2
A getInstance() 0 10 2
A getClassForResolution() 0 5 2
A makeContainerParameters() 0 6 1
A getDependencies() 0 19 5
A getContextualConcrete() 0 3 1
A sliceParameters() 0 3 1
A getBindingConcrete() 0 7 1
A getParameters() 0 9 3
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
     * Get the class instance.
13
     */
14 60
    protected function getInstance(string|object $class, array $dependencies = [], ?string $context = null): object
15
    {
16 60
        if (is_object($class)) {
17 13
            return $class;
18
        }
19
20 47
        $class        = $this->getClassForResolution($class, $context);
21 47
        $dependencies = $this->getDependencies($class, $dependencies);
22
23 47
        return app($class, $dependencies);
24
    }
25
26
    /**
27
     * Get the class for resolution.
28
     */
29 47
    protected function getClassForResolution(string $class, ?string $context = null): string
30
    {
31 47
        return isset(app()->contextual[$context])
32 1
            ? $this->getContextualConcrete($class, $context)
33 47
            : $class;
34
    }
35
36
    /**
37
     * Try to get the contextual concrete.
38
     */
39 1
    protected function getContextualConcrete(string $class, ?string $context = null): string
40
    {
41 1
        return app()->contextual[$context][$class] ?? $class;
42
    }
43
44
    /**
45
     * Try to get binding concrete.
46
     *
47
     *
48
     * @throws \ReflectionException
49
     */
50 1
    protected function getBindingConcrete(string $class): string
51
    {
52 1
        return (
53 1
           new \ReflectionFunction(
54 1
               app()->getBindings()[$class]['concrete']
55 1
           )
56 1
        )->getStaticVariables()['concrete'];
57
    }
58
59
    /**
60
     * Resolve class dependencies.
61
     *
62
     *
63
     * @throws \ReflectionException
64
     */
65 47
    protected function getDependencies(string $class, array $dependencies = []): array
66
    {
67 47
        if (! Arr::isAssoc($dependencies)) {
68 44
            if (! class_exists($class) && ! interface_exists($class)) {
69 1
                $class = $this->getBindingConcrete($class);
70
            }
71
72
            /** @var class-string $class */
73 44
            $constructor = (new \ReflectionClass($class))->getConstructor();
74
75 44
            if ($constructor) {
76 26
                $dependencies = $this->makeContainerParameters(
77 26
                    $constructor->getParameters(),
78 26
                    $dependencies
79 26
                );
80
            }
81
        }
82
83 47
        return $dependencies;
84
    }
85
86
    /**
87
     * @throws \ReflectionException
88
     */
89 46
    protected function getParameters(object $class, string $method, array $parameters): array
90
    {
91 46
        if (empty($parameters) || Arr::isAssoc($parameters)) {
92 21
            return $parameters;
93
        }
94
95 27
        return $this->makeContainerParameters(
96 27
            (new \ReflectionMethod($class, $method))->getParameters(),
97 27
            $parameters
98 27
        );
99
    }
100
101
    /**
102
     * Combine parameters to make it container-readable.
103
     */
104 50
    protected function makeContainerParameters(array $reflectionParameters, array $methodParameters): array
105
    {
106 50
        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

106
        return collect(/** @scrutinizer ignore-type */ $this->sliceParameters($reflectionParameters, $methodParameters))
Loading history...
107 50
            ->map->getName()
108 50
            ->combine($this->sliceParameters($methodParameters, $reflectionParameters))
109 50
            ->all();
110
    }
111
112
    /**
113
     * Slice an array to align the parameters.
114
     */
115 50
    protected function sliceParameters(array $parameters, array $countable): array
116
    {
117 50
        return array_slice($parameters, 0, count($countable));
118
    }
119
120
    /**
121
     * Convert the object to its namespace.
122
     */
123 15
    protected function convertToNamespace(object|string $object): string
124
    {
125 15
        return is_string($object) ? $object : $object::class;
126
    }
127
}
128