michael-rubel /
laravel-enhanced-container
| 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
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 |