Passed
Pull Request — main (#1)
by Michael
05:27 queued 02:14
created

BindsToContainer   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 44
c 4
b 0
f 0
dl 0
loc 158
ccs 53
cts 53
cp 1
rs 10
wmc 14

10 Methods

Rating   Name   Duplication   Size   Complexity  
A concreteFrom() 0 5 1
A prepareFilename() 0 5 1
A namespaceFrom() 0 5 1
A getFolderFiles() 0 6 1
A scan() 0 23 3
A guessInterfaceBy() 0 5 2
A buildInterfaceFromClassBy() 0 7 1
A prepareNamingFor() 0 3 1
A buildInterfaceBy() 0 5 1
A interfaceFrom() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\AutoBinder\Traits;
6
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Facades\File;
9
use Illuminate\Support\LazyCollection;
10
use Illuminate\Support\Str;
11
use Symfony\Component\Finder\SplFileInfo;
12
13
trait BindsToContainer
14
{
15
    /**
16
     * Run the directory scanning & bind the results.
17
     *
18
     * @return void
19
     */
20 12
    protected function scan(): void
21
    {
22 12
        $this->getFolderFiles()->each(function (SplFileInfo $file) {
23 11
            $relativePath             = $file->getRelativePathname();
24 11
            $filenameWithoutExtension = $file->getFilenameWithoutExtension();
25 11
            $filenameWithRelativePath = $this->prepareFilename($relativePath);
26
27 11
            $interface = $this->interfaceFrom($filenameWithoutExtension);
28 11
            $concrete  = $this->concreteFrom($filenameWithRelativePath);
29
30 11
            if (! interface_exists($interface) || ! class_exists($concrete)) {
31 9
                return;
32
            }
33
34 11
            $dependencies = collect($this->dependencies);
35
36 11
            $concrete = match (true) {
37 11
                $dependencies->has($interface) => $dependencies->get($interface),
38 10
                $dependencies->has($concrete)  => $dependencies->get($concrete),
39 9
                default                        => $concrete,
40
            };
41
42 11
            app()->{$this->bindingType}($interface, $concrete);
43
        });
44
    }
45
46
    /**
47
     * Get the folder files except for ignored ones.
48
     *
49
     * @return LazyCollection
50
     */
51 12
    protected function getFolderFiles(): LazyCollection
52
    {
53 12
        return LazyCollection::make(File::directories(base_path($this->basePath . DIRECTORY_SEPARATOR . $this->classFolder)))
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

53
        return LazyCollection::make(/** @scrutinizer ignore-type */ File::directories(base_path($this->basePath . DIRECTORY_SEPARATOR . $this->classFolder)))
Loading history...
54 11
            ->reject(fn ($folder) => in_array(basename($folder), $this->excludesFolders))
55 11
            ->map(fn ($folder) => File::allFiles($folder))
56 11
            ->flatten();
57
    }
58
59
    /**
60
     * Prepare the filename.
61
     *
62
     * @param string $filename
63
     *
64
     * @return string
65
     */
66 11
    protected function prepareFilename(string $filename): string
67
    {
68 11
        return (string) Str::of($filename)
69 11
            ->replace('/', '\\')
70 11
            ->substr(0, (int) strrpos($filename, '.'));
71
    }
72
73
    /**
74
     * Get the namespace from a given path.
75
     *
76
     * @param string $path
77
     *
78
     * @return string
79
     */
80 11
    protected function namespaceFrom(string $path): string
81
    {
82 11
        return (string) Str::of($path)
83 11
            ->replace('/', '\\')
84 11
            ->ucfirst();
85
    }
86
87
    /**
88
     * Get the concrete from filename.
89
     *
90
     * @param string $filenameWithRelativePath
91
     *
92
     * @return string
93
     */
94 11
    protected function concreteFrom(string $filenameWithRelativePath): string
95
    {
96 11
        return $this->classNamespace . '\\'
97 11
            . $this->classFolder . '\\'
98 11
            . $this->prepareNamingFor($filenameWithRelativePath);
99
    }
100
101
    /**
102
     * Get the interface from filename.
103
     *
104
     * @param string $filenameWithoutExtension
105
     *
106
     * @return string
107
     */
108 11
    protected function interfaceFrom(string $filenameWithoutExtension): string
109
    {
110 11
        $guessedInterface = $this->guessInterfaceBy($filenameWithoutExtension);
111
112 11
        return ! is_null($guessedInterface)
113 7
            ? $guessedInterface
114 11
            : $this->buildInterfaceBy($filenameWithoutExtension);
115
    }
116
117
    /**
118
     * Guess the interface with a given filename.
119
     *
120
     * @param string $filenameWithoutExtension
121
     *
122
     * @return string|null
123
     */
124 11
    protected function guessInterfaceBy(string $filenameWithoutExtension): ?string
125
    {
126 11
        return ! Str::contains($this->interfaceNamespace, '\\')
127 7
            ? $this->buildInterfaceFromClassBy($filenameWithoutExtension)
128 11
            : null;
129
    }
130
131
    /**
132
     * Build the interface class-string.
133
     *
134
     * @param string $filename
135
     *
136
     * @return string
137
     */
138 4
    protected function buildInterfaceBy(string $filename): string
139
    {
140 4
        return $this->interfaceNamespace . '\\'
141 4
            . $this->prepareNamingFor($filename)
142 4
            . ($this->interfaceNaming);
143
    }
144
145
    /**
146
     * Build the interface class-string based on the class folder.
147
     *
148
     * @param string $filename
149
     *
150
     * @return string
151
     */
152 7
    protected function buildInterfaceFromClassBy(string $filename): string
153
    {
154 7
        return $this->classNamespace . '\\'
155 7
            . $this->classFolder . '\\'
156 7
            . $this->interfaceNamespace . '\\'
157 7
            . $this->prepareNamingFor($filename)
158 7
            . ($this->interfaceNaming);
159
    }
160
161
    /**
162
     * Cleans up filename to append the desired interface name.
163
     *
164
     * @param string $filename
165
     *
166
     * @return string
167
     */
168 11
    protected function prepareNamingFor(string $filename): string
169
    {
170 11
        return Str::replace($this->interfaceNaming, '', $filename);
171
    }
172
}
173