Passed
Push — main ( 84fe19...8f2905 )
by Michael
03:44
created

HelpsProxies::throwPropertyNotFoundException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 6
rs 10
c 1
b 0
f 0
ccs 4
cts 4
cp 1
crap 1
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;
0 ignored issues
show
Bug introduced by
The type MichaelRubel\EnhancedCon...opertyNotFoundException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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 54
    public function resolvePassedClass(string $class, array $dependencies = [], ?string $context = null): object
20
    {
21 54
        $class        = $this->getClassForResolution($class, $context);
22 54
        $dependencies = $this->getDependencies($class, $dependencies);
23
24 54
        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 54
    public function getClassForResolution(string $class, ?string $context = null): string
36
    {
37 54
        return ! is_null($context) && isset(app()->contextual[$context])
38 1
            ? $this->getContextualConcrete($class, $context)
39 54
            : $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 54
    public function getDependencies(string $class, array $dependencies = []): array
65
    {
66 54
        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 54
        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 56
    public function getPassedParameters(object $class, string $method, array $parameters): array
90
    {
91 56
        if (empty($parameters)) {
92 31
            return $parameters;
93
        }
94
95 28
        return $this->makeContainerParameters(
96 28
            (new \ReflectionMethod($class, $method))->getParameters(),
97
            $parameters
98
        );
99
    }
100
101
    /**
102
     * Combine parameters to make it container-readable.
103
     *
104
     * @param array $reflectionParameters
105
     * @param array $methodParameters
106
     *
107
     * @return array
108
     */
109 27
    public function makeContainerParameters(array $reflectionParameters, array $methodParameters): array
110
    {
111 27
        $base = current($methodParameters);
112
113 27
        if ($this->isOrderable($base, $reflectionParameters, $methodParameters)) {
114 1
            return $base;
115
        }
116
117 27
        $reflectionParameters = $this->sliceParameters($reflectionParameters, $methodParameters);
118 27
        $methodParameters     = $this->sliceParameters($methodParameters, $reflectionParameters);
119
120 27
        return collect($reflectionParameters)
0 ignored issues
show
Bug introduced by
$reflectionParameters 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

120
        return collect(/** @scrutinizer ignore-type */ $reflectionParameters)
Loading history...
121 27
            ->map
122 27
            ->getName()
123 27
            ->combine($methodParameters)
124 27
            ->all();
125
    }
126
127
    /**
128
     * Determine if the container can handle parameter order.
129
     *
130
     * @param array $base
131
     * @param array $reflectionParameters
132
     * @param array $methodParameters
133
     *
134
     * @return bool
135
     */
136 27
    public function isOrderable(mixed $base, array $reflectionParameters, array $methodParameters): bool
137
    {
138 27
        return is_array($base) && Arr::isAssoc($base) && single($methodParameters) <=> single($reflectionParameters);
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 27
    public function sliceParameters(array $parameters, array $countable): array
150
    {
151 27
        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 52
    public function convertToNamespace(object|string $object): string
162
    {
163 52
        return is_string($object)
164 45
            ? $object
165 52
            : $object::class;
166
    }
167
}
168