MakeRepositoryCommand   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 77
c 2
b 0
f 0
dl 0
loc 219
rs 10
wmc 27

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getDefaultNamespace() 0 3 1
A resolveStubPath() 0 5 2
A areOptionsPresent() 0 18 6
A buildClass() 0 46 5
A getOptions() 0 8 1
A alreadyExists() 0 4 2
B handle() 0 36 8
A getStub() 0 7 2
1
<?php
2
3
namespace Ikechukwukalu\Makeservice\Console\Commands;
4
5
use Illuminate\Console\GeneratorCommand;
6
use Illuminate\Console\Concerns\CreatesMatchingTest;
7
use Illuminate\Support\Str;
8
use Symfony\Component\Console\Attribute\AsCommand;
9
use Symfony\Component\Console\Input\InputOption;
10
11
#[AsCommand(name: 'make:repository')]
12
class MakeRepositoryCommand extends GeneratorCommand
13
{
14
    /**
15
     * The console command name.
16
     *
17
     * @var string
18
     */
19
    protected $name = 'make:repository';
20
21
    /**
22
     * The name of the console command.
23
     *
24
     * This name is used to identify the command during lazy loading.
25
     *
26
     * @var string|null
27
     *
28
     * @deprecated
29
     */
30
    protected static $defaultName = 'make:repository';
31
32
    /**
33
     * The console command description.
34
     *
35
     * @var string
36
     */
37
    protected $description = 'Create a new repository class';
38
39
    /**
40
     * The type of class being generated.
41
     *
42
     * @var string
43
     */
44
    protected $type = 'Respository';
45
46
    /**
47
     * Build the class with the given name.
48
     *
49
     * @param  string  $name
50
     * @return string
51
     */
52
    protected function buildClass($name)
53
    {
54
        $model = $this->option('model');
55
56
        if ($this->option('contract')) {
57
            $interface = $model . "RepositoryInterface";
58
59
            if ($this->option('user')) {
60
                $this->call('make:interfaceclass', ['name' => $interface, '--model' => $model, '--user' => null]);
61
            } else {
62
                $this->call('make:interfaceclass', ['name' => $interface, '--model' => $model]);
63
            }
64
        } else {
65
            $interface = $this->option('interface');
66
        }
67
68
        if (! Str::startsWith($model, [
0 ignored issues
show
Bug introduced by
It seems like $model can also be of type array; however, parameter $haystack of Illuminate\Support\Str::startsWith() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
        if (! Str::startsWith(/** @scrutinizer ignore-type */ $model, [
Loading history...
69
            $this->laravel->getNamespace(),
70
            'Illuminate',
71
            '\\',
72
        ])) {
73
            $model = $this->laravel->getNamespace().'Models\\'.str_replace('/', '\\', $model);
74
        }
75
76
        if (! Str::startsWith($interface, [
77
            $this->laravel->getNamespace(),
78
            'Illuminate',
79
            '\\',
80
        ])) {
81
            $interface = $this->laravel->getNamespace().'Contracts\\'.str_replace('/', '\\', $interface);
82
        }
83
84
        $stub = str_replace(
85
            ['DummyModel', '{{ model }}'], class_basename($model), parent::buildClass($name)
0 ignored issues
show
Bug introduced by
It seems like $model can also be of type array; however, parameter $class of class_basename() does only seem to accept object|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

85
            ['DummyModel', '{{ model }}'], class_basename(/** @scrutinizer ignore-type */ $model), parent::buildClass($name)
Loading history...
86
        );
87
88
        $stub = str_replace(
89
            ['DummyFullModel', '{{ modelNamespace }}'], trim($model, '\\'), $stub
90
        );
91
92
        $stub = str_replace(
93
            ['DummyInterface', '{{ interface }}'], class_basename($interface), $stub
94
        );
95
96
        return str_replace(
97
            ['DummyFullInterface', '{{ interfaceNamespace }}'], trim($interface, '\\'), $stub
98
        );
99
    }
100
101
    /**
102
     * Determine if the class already exists.
103
     *
104
     * @param  string  $rawName
105
     * @return bool
106
     */
107
    protected function alreadyExists($rawName)
108
    {
109
        return class_exists($rawName) ||
110
               $this->files->exists($this->getPath($this->qualifyClass($rawName)));
111
    }
112
113
    /**
114
     * Get the stub file for the generator.
115
     *
116
     * @return string
117
     */
118
    protected function getStub()
119
    {
120
        if ($this->option('user')) {
121
            return __DIR__.'/stubs/repository-user.stub';
122
        }
123
124
        return __DIR__.'/stubs/repository.stub';
125
    }
126
127
    /**
128
     * Resolve the fully-qualified path to the stub.
129
     *
130
     * @param  string  $stub
131
     * @return string
132
     */
133
    protected function resolveStubPath($stub)
134
    {
135
        return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
136
                        ? $customPath
137
                        : __DIR__.$stub;
138
    }
139
140
    /**
141
     * Get the default namespace for the class.
142
     *
143
     * @param  string  $rootNamespace
144
     * @return string
145
     */
146
    protected function getDefaultNamespace($rootNamespace)
147
    {
148
        return $rootNamespace.'\Repositories';
149
    }
150
151
    /**
152
     * Get the console command options.
153
     *
154
     * @return array
155
     */
156
    protected function getOptions()
157
    {
158
        return [
159
            ['contract', 'c', InputOption::VALUE_NONE, 'Create an interface class for this repository'],
160
            ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the repository already exists'],
161
            ['interface', 'i', InputOption::VALUE_OPTIONAL, 'Create an interface namespace for this repository'],
162
            ['model', 'm', InputOption::VALUE_REQUIRED, 'Create a model namespace for this repository'],
163
            ['user', 'u', InputOption::VALUE_NONE, 'Create extra fetch by user id functions for this repository'],
164
        ];
165
    }
166
167
    /**
168
     * Execute the console command.
169
     *
170
     * @return bool|null
171
     *
172
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
173
     */
174
    public function handle()
175
    {
176
        if ($this->isReservedName($this->getNameInput())) {
177
            $this->components->error('The name "'.$this->getNameInput().'" is reserved by PHP.');
0 ignored issues
show
Bug Best Practice introduced by
The property components does not exist on Ikechukwukalu\Makeservic...s\MakeRepositoryCommand. Did you maybe forget to declare it?
Loading history...
178
            return false;
179
        }
180
181
        if (!$this->areOptionsPresent()) {
182
            return false;
183
        }
184
185
        $name = $this->qualifyClass($this->getNameInput());
186
187
        $path = $this->getPath($name);
188
189
        if ((! $this->hasOption('force') ||
190
             ! $this->option('force')) &&
191
             $this->alreadyExists($this->getNameInput())) {
192
            $this->components->error($this->type.' already exists.');
193
194
            return false;
195
        }
196
197
        $this->makeDirectory($path);
198
199
        $this->files->put($path, $this->sortImports($this->buildClass($name)));
200
201
        $info = $this->type;
202
203
        if (in_array(CreatesMatchingTest::class, class_uses_recursive($this))) {
204
            if ($this->handleTestCreation($path)) {
0 ignored issues
show
Bug introduced by
The method handleTestCreation() does not exist on Ikechukwukalu\Makeservic...s\MakeRepositoryCommand. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

204
            if ($this->/** @scrutinizer ignore-call */ handleTestCreation($path)) {
Loading history...
205
                $info .= ' and test';
206
            }
207
        }
208
209
        $this->components->info(sprintf('%s [%s] created successfully.', $info, $path));
210
    }
211
212
    private function areOptionsPresent():bool
213
    {
214
        if (!$this->option('model')) {
215
            if (!($this->option('contract') || $this->option('interface'))) {
216
                $this->components->error('Expected options "model" and "contract or interface"!');
0 ignored issues
show
Bug Best Practice introduced by
The property components does not exist on Ikechukwukalu\Makeservic...s\MakeRepositoryCommand. Did you maybe forget to declare it?
Loading history...
217
                return false;
218
            }
219
220
            $this->components->error('Expected option "model"!');
221
            return false;
222
        }
223
224
        if (!($this->option('contract') || $this->option('interface'))) {
225
            $this->components->error('Expected option "interface or contract"!');
226
            return false;
227
        }
228
229
        return true;
230
    }
231
}
232