ControllerMakeCommand   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 259
Duplicated Lines 18.15 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 47
loc 259
rs 9.84
c 0
b 0
f 0
wmc 32
lcom 1
cbo 4

9 Methods

Rating   Name   Duplication   Size   Complexity  
B getStub() 0 28 8
A getDefaultNamespace() 0 11 4
A buildClass() 0 24 4
A buildParentReplacements() 0 16 3
A parseModel() 0 14 3
A buildModelReplacements() 0 33 3
A appendModelToViewDir() 0 9 2
A getOptions() 20 20 1
A handle() 27 27 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace JunaidQadirB\Cray\Console\Commands;
4
5
6
use Illuminate\Support\Str;
7
use InvalidArgumentException;
8
use JunaidQadirB\Cray\Console\Contracts\GeneratorCommand;
9
use Symfony\Component\Console\Input\InputOption;
10
11
class ControllerMakeCommand extends GeneratorCommand
12
{
13
    /**
14
     * The console command name.
15
     *
16
     * @var string
17
     */
18
    protected $name = 'cray:controller';
19
20
    /**
21
     * The console command description.
22
     *
23
     * @var string
24
     */
25
    protected $description = 'Create a new controller class';
26
27
    /**
28
     * The type of class being generated.
29
     *
30
     * @var string
31
     */
32
    protected $type = 'Controller';
33
34
    /**
35
     * Get the stub file for the generator.
36
     *
37
     * @return string
38
     */
39
    protected function getStub()
40
    {
41
        $stub = null;
42
43
        if ($this->option('parent')) {
44
            $stub = 'stubs/controller.nested.stub';
45
        } else {
46
            if ($this->option('model')) {
47
                $stub = 'stubs/controller.model.stub';
48
            } else {
49
                if ($this->option('resource')) {
50
                    $stub = 'stubs/controller.stub';
51
                }
52
            }
53
        }
54
55
        if ($this->option('api') && is_null($stub)) {
56
            $stub = 'stubs/controller.api.stub';
57
        } else {
58
            if ($this->option('api') && !is_null($stub)) {
59
                $stub = str_replace('.stub', '.api.stub', $stub);
60
            }
61
        }
62
63
        $stub = $stub ?? 'stubs/controller.plain.stub';
64
65
        return resource_path($stub);
66
    }
67
68
    /**
69
     * Get the default namespace for the class.
70
     *
71
     * @param string $rootNamespace
72
     *
73
     * @return string
74
     */
75
    protected function getDefaultNamespace($rootNamespace)
76
    {
77
        $dir = $this->hasOption('controller-dir') && trim($this->option('controller-dir')) != ''
78
            ? $this->option('controller-dir')
79
            : null;
80
        if ($dir) {
81
            return $rootNamespace . '\Http\Controllers\\' . Str::studly(strtolower($dir));
82
        }
83
84
        return $rootNamespace . '\Http\Controllers';
85
    }
86
87
    /**
88
     * Build the class with the given name.
89
     *
90
     * Remove the base controller import if we are already in base namespace.
91
     *
92
     * @param string $name
93
     *
94
     * @return string
95
     */
96
    protected function buildClass($name)
97
    {
98
        $controllerNamespace = $this->getNamespace($name);
99
100
        $replace = [];
101
102
        if ($this->option('parent')) {
103
            $replace = $this->buildParentReplacements();
104
        }
105
106
        if ($this->option('model')) {
107
            $replace = $this->buildModelReplacements($replace);
108
            if ($model = $this->option('model')) {
109
                $replace = str_replace('$modelSlug$', Str::slug(str_to_words($model), '-'), $replace);
110
            }
111
        }
112
113
114
        $replace["use {$controllerNamespace}\Controller;\n"] = '';
115
116
        return str_replace(
117
            array_keys($replace), array_values($replace), parent::buildClass($name)
118
        );
119
    }
120
121
    /**
122
     * Build the replacements for a parent controller.
123
     *
124
     * @return array
125
     */
126
    protected function buildParentReplacements()
127
    {
128
        $parentModelClass = $this->parseModel($this->option('parent'));
129
130
        if (!class_exists($parentModelClass)) {
131
            if ($this->confirm("A {$parentModelClass} model does not exist. Do you want to generate it?", true)) {
132
                $this->call('cray:model', ['name' => $parentModelClass]);
133
            }
134
        }
135
136
        return [
137
            'ParentDummyFullModelClass' => $parentModelClass,
138
            'ParentDummyModelClass' => class_basename($parentModelClass),
139
            'ParentDummyModelVariable' => lcfirst(class_basename($parentModelClass)),
140
        ];
141
    }
142
143
    /**
144
     * Get the fully-qualified model class name.
145
     *
146
     * @param string $model
147
     *
148
     * @return string
149
     */
150
    protected function parseModel($model)
151
    {
152
        if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) {
153
            throw new InvalidArgumentException('Model name contains invalid characters.');
154
        }
155
156
        $model = trim(str_replace('/', '\\', $model), '\\');
157
158
        if (!Str::startsWith($model, $rootNamespace = $this->laravel->getNamespace())) {
159
            $model = $rootNamespace . $model;
160
        }
161
162
        return $model;
163
    }
164
165
    /**
166
     * Build the model replacement values.
167
     *
168
     * @param array $replace
169
     *
170
     * @return array
171
     */
172
    protected function buildModelReplacements(array $replace)
173
    {
174
        $modelClass = $this->parseModel($this->option('model'));
175
176
        if (!class_exists($modelClass)) {
177
            /*if ($this->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) {
178
179
            }*/
180
            $this->call('cray:model', ['name' => $modelClass]);
181
        }
182
183
        $label = str_to_words(class_basename($modelClass));
184
185
        $modelSlug = Str::slug(Str::plural($label, 2));
186
        $routeBase = $modelSlug;
187
        $dir = $this->appendModelToViewDir($this->option('views-dir'), $modelSlug);
188
        $dir = str_replace('/', '.', $dir);
189
190
        if ($this->option('route-base')) {
191
            $routeBase = $this->option('route-base');
192
        }
193
194
        return array_merge($replace, [
195
            'DummyFullModelClass' => $modelClass,
196
            'DummyModelClass' => class_basename($modelClass),
197
            'DummyModelVariable' => lcfirst(class_basename($modelClass)),
198
            '$modelSlug$' => $modelSlug,
199
            '$label$' => $label,
200
            '$rows$' => Str::plural(lcfirst(class_basename($modelClass)), 2),
201
            '$viewDir$' => $dir,
202
            '$routeBase$' => $routeBase,
203
        ]);
204
    }
205
206
    private function appendModelToViewDir($path, $model)
207
    {
208
        $pathArray = explode("/", $path);
209
        if ($pathArray[sizeof($pathArray) - 1] == $model) {
210
            return $path;
211
        }
212
213
        return rtrim($path, '/') . "/" . $model;
214
    }
215
216
    /**
217
     * Get the console command options.
218
     *
219
     * @return array
220
     */
221 View Code Duplication
    protected function getOptions()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
222
    {
223
        return [
224
            ['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate a resource controller for the given model.'],
225
226
            ['resource', 'r', InputOption::VALUE_NONE, 'Generate a resource controller class.'],
227
228
            ['parent', 'p', InputOption::VALUE_OPTIONAL, 'Generate a nested resource controller class.'],
229
230
            ['api', null, InputOption::VALUE_NONE, 'Exclude the create and edit methods from the controller.'],
231
232
            ['views-dir', 'i', InputOption::VALUE_OPTIONAL, 'Use the specified path in controller actions to return the respective view'],
233
234
            ['controller-dir', 'c', InputOption::VALUE_OPTIONAL, 'Specify the controller path within the Http directory'],
235
236
            ['route-base', 'b', InputOption::VALUE_OPTIONAL, 'Specify the base route to use'],
237
238
            ['force', 'f', InputOption::VALUE_NONE, 'Overwrite existing controller']
239
        ];
240
    }
241
242 View Code Duplication
    public function handle()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
    {
244
        $name = $this->qualifyClass($this->getNameInput());
245
        $path = $this->getPath($name);
246
        // First we will check to see if the class already exists. If it does, we don't want
247
        // to create the class and overwrite the user's code. So, we will bail out so the
248
        // code is untouched. Otherwise, we will continue generating this class' files.
249
        if ((!$this->hasOption('force') ||
250
                !$this->option('force')) &&
251
            $this->alreadyExists($this->getNameInput())
252
        ) {
253
            $this->error($this->type . ' already exists!');
254
255
            return false;
256
        }
257
258
        // Next, we will generate the path to the location where this class' file should get
259
        // written. Then, we will build the class and make the proper replacements on the
260
        // stub files so that it gets the correctly formatted namespace and class name.
261
        $this->makeDirectory($path);
262
263
        $displayPath = str_replace($this->laravel['path'], '/app', $path);
264
265
        $this->files->put($path, $this->buildClass($name));
266
267
        $this->info($this->type . ' created successfully in ' . $displayPath);
268
    }
269
}
270