Passed
Push — main ( 98bf96...fae6b8 )
by ikechukwu
03:07
created

MakeRepositoryCommand::areOptionsPresent()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 18
rs 9.9332
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
        $interface = $this->option('interface');
56
57
        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

57
        if (! Str::startsWith(/** @scrutinizer ignore-type */ $model, [
Loading history...
58
            $this->laravel->getNamespace(),
59
            'Illuminate',
60
            '\\',
61
        ])) {
62
            $model = $this->laravel->getNamespace().'Models\\'.str_replace('/', '\\', $model);
63
        }
64
65
        if (! Str::startsWith($interface, [
66
            $this->laravel->getNamespace(),
67
            'Illuminate',
68
            '\\',
69
        ])) {
70
            $interface = $this->laravel->getNamespace().'Contracts\\'.str_replace('/', '\\', $interface);
71
        }
72
73
        $stub = str_replace(
74
            ['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

74
            ['DummyModel', '{{ model }}'], class_basename(/** @scrutinizer ignore-type */ $model), parent::buildClass($name)
Loading history...
75
        );
76
77
        $stub = str_replace(
78
            ['DummyFullModel', '{{ modelNamespace }}'], trim($model, '\\'), $stub
79
        );
80
81
        $stub = str_replace(
82
            ['DummyInterface', '{{ interface }}'], class_basename($interface), $stub
83
        );
84
85
        return str_replace(
86
            ['DummyFullInterface', '{{ interfaceNamespace }}'], trim($interface, '\\'), $stub
87
        );
88
    }
89
90
    /**
91
     * Determine if the class already exists.
92
     *
93
     * @param  string  $rawName
94
     * @return bool
95
     */
96
    protected function alreadyExists($rawName)
97
    {
98
        return class_exists($rawName) ||
99
               $this->files->exists($this->getPath($this->qualifyClass($rawName)));
100
    }
101
102
    /**
103
     * Get the stub file for the generator.
104
     *
105
     * @return string
106
     */
107
    protected function getStub()
108
    {
109
        return __DIR__.'/stubs/repository.stub';
110
    }
111
112
    /**
113
     * Resolve the fully-qualified path to the stub.
114
     *
115
     * @param  string  $stub
116
     * @return string
117
     */
118
    protected function resolveStubPath($stub)
119
    {
120
        return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
121
                        ? $customPath
122
                        : __DIR__.$stub;
123
    }
124
125
    /**
126
     * Get the default namespace for the class.
127
     *
128
     * @param  string  $rootNamespace
129
     * @return string
130
     */
131
    protected function getDefaultNamespace($rootNamespace)
132
    {
133
        return $rootNamespace.'\Repositories';
134
    }
135
136
    /**
137
     * Get the console command options.
138
     *
139
     * @return array
140
     */
141
    protected function getOptions()
142
    {
143
        return [
144
            ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the repository already exists'],
145
            ['model', 'm', InputOption::VALUE_REQUIRED, 'Create a model namespace for this repository'],
146
            ['interface', 'i', InputOption::VALUE_REQUIRED, 'Create an interface namespace for this repository'],
147
        ];
148
    }
149
150
    /**
151
     * Execute the console command.
152
     *
153
     * @return bool|null
154
     *
155
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
156
     */
157
    public function handle()
158
    {
159
        if ($this->isReservedName($this->getNameInput())) {
160
            $this->components->error('The name "'.$this->getNameInput().'" is reserved by PHP.');
161
162
            return false;
163
        }
164
165
        if (!$this->areOptionsPresent()) {
166
            return false;
167
        }
168
169
        $name = $this->qualifyClass($this->getNameInput());
170
171
        $path = $this->getPath($name);
172
173
        if ((! $this->hasOption('force') ||
174
             ! $this->option('force')) &&
175
             $this->alreadyExists($this->getNameInput())) {
176
            $this->components->error($this->type.' already exists.');
177
178
            return false;
179
        }
180
181
        $this->makeDirectory($path);
182
183
        $this->files->put($path, $this->sortImports($this->buildClass($name)));
184
185
        $info = $this->type;
186
187
        if (in_array(CreatesMatchingTest::class, class_uses_recursive($this))) {
188
            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

188
            if ($this->/** @scrutinizer ignore-call */ handleTestCreation($path)) {
Loading history...
189
                $info .= ' and test';
190
            }
191
        }
192
193
        $this->components->info(sprintf('%s [%s] created successfully.', $info, $path));
194
    }
195
196
    private function areOptionsPresent():bool
197
    {
198
        if (!$this->option('model')) {
199
            if (!$this->option('interface')) {
200
                $this->components->error('Expected options "model" and "interface"!');
201
                return false;
202
            }
203
204
            $this->components->error('Expected option "model"!');
205
            return false;
206
        }
207
208
        if (!$this->option('interface')) {
209
            $this->components->error('Expected option "interface"!');
210
            return false;
211
        }
212
213
        return true;
214
    }
215
}
216