michael-rubel /
laravel-auto-binder
| 1 | <?php |
||||||
| 2 | |||||||
| 3 | declare(strict_types=1); |
||||||
| 4 | |||||||
| 5 | namespace MichaelRubel\AutoBinder\Traits; |
||||||
| 6 | |||||||
| 7 | use Illuminate\Support\Facades\File; |
||||||
| 8 | use Illuminate\Support\LazyCollection; |
||||||
| 9 | use Illuminate\Support\Str; |
||||||
| 10 | use Psr\Container\ContainerExceptionInterface; |
||||||
| 11 | use Psr\Container\NotFoundExceptionInterface; |
||||||
| 12 | use Symfony\Component\Finder\SplFileInfo; |
||||||
| 13 | |||||||
| 14 | trait BindsToContainer |
||||||
| 15 | { |
||||||
| 16 | private ?bool $providesCache = null; |
||||||
| 17 | |||||||
| 18 | /** |
||||||
| 19 | * Run the directory scanning & bind the results. |
||||||
| 20 | * |
||||||
| 21 | * @throws ContainerExceptionInterface |
||||||
| 22 | * @throws NotFoundExceptionInterface |
||||||
| 23 | */ |
||||||
| 24 | 23 | protected function scan(): void |
|||||
| 25 | { |
||||||
| 26 | 23 | $this->getFolderFiles()->each( |
|||||
| 27 | 23 | fn (array $files, string $actualFolder) => LazyCollection::make($files)->each( |
|||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||
| 28 | 23 | function (SplFileInfo $file) use ($actualFolder) { |
|||||
| 29 | 22 | $relativePath = $file->getRelativePathname(); |
|||||
| 30 | 22 | $filenameWithoutExtension = $file->getFilenameWithoutExtension(); |
|||||
| 31 | 22 | $filenameWithRelativePath = $this->prepareFilename($relativePath); |
|||||
| 32 | |||||||
| 33 | 22 | $interface = $this->interfaceFrom($filenameWithoutExtension); |
|||||
| 34 | 22 | $concrete = $this->concreteFrom($actualFolder, $filenameWithRelativePath); |
|||||
| 35 | |||||||
| 36 | 22 | if (! interface_exists($interface) || ! class_exists($concrete)) { |
|||||
| 37 | 21 | return; |
|||||
| 38 | } |
||||||
| 39 | |||||||
| 40 | 21 | $dependencies = collect($this->dependencies); |
|||||
| 41 | |||||||
| 42 | 21 | $concrete = match (true) { |
|||||
| 43 | 21 | $dependencies->has($interface) => $dependencies->get($interface), |
|||||
| 44 | 21 | $dependencies->has($concrete) => $dependencies->get($concrete), |
|||||
| 45 | 21 | default => $concrete, |
|||||
| 46 | 21 | }; |
|||||
| 47 | |||||||
| 48 | 21 | if ($this->providesCache() && $this->cacheEnabled()) { |
|||||
|
0 ignored issues
–
show
It seems like
cacheEnabled() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 49 | 19 | $this->cacheBindingFor($interface, $concrete); |
|||||
|
0 ignored issues
–
show
It seems like
cacheBindingFor() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 50 | } |
||||||
| 51 | |||||||
| 52 | 21 | app()->{$this->bindingType}($interface, $concrete); |
|||||
| 53 | 23 | } |
|||||
| 54 | 23 | ) |
|||||
| 55 | 23 | ); |
|||||
| 56 | } |
||||||
| 57 | |||||||
| 58 | /** |
||||||
| 59 | * Get the folder files except for ignored ones. |
||||||
| 60 | * |
||||||
| 61 | * @return LazyCollection<string, array<SplFileInfo>> |
||||||
| 62 | */ |
||||||
| 63 | 23 | protected function getFolderFiles(): LazyCollection |
|||||
| 64 | { |
||||||
| 65 | 23 | return LazyCollection::make(File::directories(base_path($this->basePath . DIRECTORY_SEPARATOR . $this->classFolder))) |
|||||
|
0 ignored issues
–
show
Illuminate\Support\Facad... . $this->classFolder)) of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\LazyCollection::make().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 66 | 23 | ->reject(fn (string $folder) => in_array(basename($folder), $this->excludesFolders)) |
|||||
| 67 | 23 | ->mapWithKeys(fn (string $folder) => [basename($folder) => File::allFiles($folder)]); |
|||||
| 68 | } |
||||||
| 69 | |||||||
| 70 | /** |
||||||
| 71 | * Prepare the filename. |
||||||
| 72 | */ |
||||||
| 73 | 22 | protected function prepareFilename(string $filename): string |
|||||
| 74 | { |
||||||
| 75 | 22 | return str($filename) |
|||||
| 76 | 22 | ->replace('/', '\\') |
|||||
| 77 | 22 | ->substr(0, strrpos($filename, '.') ?: null) |
|||||
| 78 | 22 | ->value(); |
|||||
| 79 | } |
||||||
| 80 | |||||||
| 81 | /** |
||||||
| 82 | * Get the namespace from a given path. |
||||||
| 83 | */ |
||||||
| 84 | 22 | protected function namespaceFrom(string $path): string |
|||||
| 85 | { |
||||||
| 86 | 22 | return str($path) |
|||||
| 87 | 22 | ->replace('/', '\\') |
|||||
| 88 | 22 | ->ucfirst() |
|||||
| 89 | 22 | ->value(); |
|||||
| 90 | } |
||||||
| 91 | |||||||
| 92 | /** |
||||||
| 93 | * Get the concrete from filename. |
||||||
| 94 | */ |
||||||
| 95 | 22 | protected function concreteFrom(string $folder, string $filenameWithRelativePath): string |
|||||
| 96 | { |
||||||
| 97 | 22 | return $this->classNamespace . '\\' |
|||||
| 98 | 22 | . $this->classFolder . '\\' |
|||||
| 99 | 22 | . $this->prepareActual($folder . '\\') |
|||||
| 100 | 22 | . $this->prepareNamingFor($filenameWithRelativePath); |
|||||
| 101 | } |
||||||
| 102 | |||||||
| 103 | /** |
||||||
| 104 | * Get the interface from filename. |
||||||
| 105 | */ |
||||||
| 106 | 22 | protected function interfaceFrom(string $filenameWithoutExtension): string |
|||||
| 107 | { |
||||||
| 108 | 22 | $guessedInterface = $this->guessInterfaceBy($filenameWithoutExtension); |
|||||
| 109 | |||||||
| 110 | 22 | return ! is_null($guessedInterface) |
|||||
| 111 | 15 | ? $guessedInterface |
|||||
| 112 | 22 | : $this->buildInterfaceBy($filenameWithoutExtension); |
|||||
| 113 | } |
||||||
| 114 | |||||||
| 115 | /** |
||||||
| 116 | * Guess the interface with a given filename. |
||||||
| 117 | */ |
||||||
| 118 | 22 | protected function guessInterfaceBy(string $filenameWithoutExtension): ?string |
|||||
| 119 | { |
||||||
| 120 | 22 | return ! Str::contains($this->interfaceNamespace, '\\') |
|||||
| 121 | 14 | ? $this->buildInterfaceFromClassBy($filenameWithoutExtension) |
|||||
| 122 | 22 | : null; |
|||||
| 123 | } |
||||||
| 124 | |||||||
| 125 | /** |
||||||
| 126 | * Build the interface class-string. |
||||||
| 127 | */ |
||||||
| 128 | 8 | protected function buildInterfaceBy(string $filename): string |
|||||
| 129 | { |
||||||
| 130 | 8 | return $this->interfaceNamespace . '\\' |
|||||
| 131 | 8 | . $this->prepareNamingFor($filename) |
|||||
| 132 | 8 | . $this->interfaceNaming; |
|||||
| 133 | } |
||||||
| 134 | |||||||
| 135 | /** |
||||||
| 136 | * Build the interface class-string based on the class folder. |
||||||
| 137 | */ |
||||||
| 138 | 15 | protected function buildInterfaceFromClassBy(string $filename): string |
|||||
| 139 | { |
||||||
| 140 | 15 | return $this->classNamespace . '\\' |
|||||
| 141 | 15 | . $this->classFolder . '\\' |
|||||
| 142 | 15 | . $this->interfaceNamespace . '\\' |
|||||
| 143 | 15 | . $this->prepareNamingFor($filename) |
|||||
| 144 | 15 | . $this->interfaceNaming; |
|||||
| 145 | } |
||||||
| 146 | |||||||
| 147 | /** |
||||||
| 148 | * Cleans up filename to append the desired interface name. |
||||||
| 149 | */ |
||||||
| 150 | 22 | protected function prepareNamingFor(string $filename): string |
|||||
| 151 | { |
||||||
| 152 | 22 | return Str::replace($this->interfaceNaming, '', $filename); |
|||||
| 153 | } |
||||||
| 154 | |||||||
| 155 | /** |
||||||
| 156 | * prepares an actual folder. |
||||||
| 157 | */ |
||||||
| 158 | 22 | protected function prepareActual(string $folder): string |
|||||
| 159 | { |
||||||
| 160 | 22 | return Str::replace(Str::plural($this->interfaceNaming) . '\\', '', $folder); |
|||||
| 161 | } |
||||||
| 162 | |||||||
| 163 | /** |
||||||
| 164 | * Check if the class use `CachesBindings` trait. |
||||||
| 165 | */ |
||||||
| 166 | 22 | protected function providesCache(): bool |
|||||
| 167 | { |
||||||
| 168 | 22 | if ($this->providesCache) { |
|||||
| 169 | 20 | return true; |
|||||
| 170 | } |
||||||
| 171 | |||||||
| 172 | 22 | $uses = class_uses_recursive(static::class); |
|||||
| 173 | |||||||
| 174 | 22 | return $this->providesCache = in_array(CachesBindings::class, $uses); |
|||||
| 175 | } |
||||||
| 176 | } |
||||||
| 177 |