Passed
Pull Request — main (#1)
by Michael
03:19
created

BindsToContainer::prepareNamingFor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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
        if (is_null($guessedInterface)) {
113 4
            return $this->buildInterfaceBy($filenameWithoutExtension);
114
        }
115
116 7
        return $guessedInterface;
117
    }
118
119
    /**
120
     * Guess the interface with a given filename.
121
     *
122
     * @param string $filenameWithoutExtension
123
     *
124
     * @return string|null
125
     */
126 11
    protected function guessInterfaceBy(string $filenameWithoutExtension): ?string
127
    {
128 11
        return ! Str::contains($this->interfaceNamespace, '\\')
129 7
            ? $this->buildInterfaceFromClassBy($filenameWithoutExtension)
130 11
            : null;
131
    }
132
133
    /**
134
     * Build the interface class-string.
135
     *
136
     * @param string $filename
137
     *
138
     * @return string
139
     */
140 4
    protected function buildInterfaceBy(string $filename): string
141
    {
142 4
        return $this->interfaceNamespace . '\\'
143 4
            . $this->prepareNamingFor($filename)
144 4
            . ($this->interfaceNaming);
145
    }
146
147
    /**
148
     * Build the interface class-string based on the class folder.
149
     *
150
     * @param string $filename
151
     *
152
     * @return string
153
     */
154 7
    protected function buildInterfaceFromClassBy(string $filename): string
155
    {
156 7
        return $this->classNamespace . '\\'
157 7
            . $this->classFolder . '\\'
158 7
            . $this->interfaceNamespace . '\\'
159 7
            . $this->prepareNamingFor($filename)
160 7
            . ($this->interfaceNaming);
161
    }
162
163
    /**
164
     * Cleans up filename to append the desired interface name.
165
     *
166
     * @param string $filename
167
     *
168
     * @return string
169
     */
170 11
    protected function prepareNamingFor(string $filename): string
171
    {
172 11
        return Str::replace($this->interfaceNaming, '', $filename);
173
    }
174
}
175