Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Routing\Console;
4
 
5
use Illuminate\Console\Concerns\CreatesMatchingTest;
6
use Illuminate\Console\GeneratorCommand;
7
use InvalidArgumentException;
8
use Symfony\Component\Console\Attribute\AsCommand;
9
use Symfony\Component\Console\Input\InputOption;
10
 
11
#[AsCommand(name: 'make:controller')]
12
class ControllerMakeCommand extends GeneratorCommand
13
{
14
    use CreatesMatchingTest;
15
 
16
    /**
17
     * The console command name.
18
     *
19
     * @var string
20
     */
21
    protected $name = 'make:controller';
22
 
23
    /**
24
     * The name of the console command.
25
     *
26
     * This name is used to identify the command during lazy loading.
27
     *
28
     * @var string|null
29
     *
30
     * @deprecated
31
     */
32
    protected static $defaultName = 'make:controller';
33
 
34
    /**
35
     * The console command description.
36
     *
37
     * @var string
38
     */
39
    protected $description = 'Create a new controller class';
40
 
41
    /**
42
     * The type of class being generated.
43
     *
44
     * @var string
45
     */
46
    protected $type = 'Controller';
47
 
48
    /**
49
     * Get the stub file for the generator.
50
     *
51
     * @return string
52
     */
53
    protected function getStub()
54
    {
55
        $stub = null;
56
 
57
        if ($type = $this->option('type')) {
58
            $stub = "/stubs/controller.{$type}.stub";
59
        } elseif ($this->option('parent')) {
60
            $stub = $this->option('singleton')
61
                        ? '/stubs/controller.nested.singleton.stub'
62
                        : '/stubs/controller.nested.stub';
63
        } elseif ($this->option('model')) {
64
            $stub = '/stubs/controller.model.stub';
65
        } elseif ($this->option('invokable')) {
66
            $stub = '/stubs/controller.invokable.stub';
67
        } elseif ($this->option('singleton')) {
68
            $stub = '/stubs/controller.singleton.stub';
69
        } elseif ($this->option('resource')) {
70
            $stub = '/stubs/controller.stub';
71
        }
72
 
73
        if ($this->option('api') && is_null($stub)) {
74
            $stub = '/stubs/controller.api.stub';
75
        } elseif ($this->option('api') && ! is_null($stub) && ! $this->option('invokable')) {
76
            $stub = str_replace('.stub', '.api.stub', $stub);
77
        }
78
 
79
        $stub ??= '/stubs/controller.plain.stub';
80
 
81
        return $this->resolveStubPath($stub);
82
    }
83
 
84
    /**
85
     * Resolve the fully-qualified path to the stub.
86
     *
87
     * @param  string  $stub
88
     * @return string
89
     */
90
    protected function resolveStubPath($stub)
91
    {
92
        return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
93
                        ? $customPath
94
                        : __DIR__.$stub;
95
    }
96
 
97
    /**
98
     * Get the default namespace for the class.
99
     *
100
     * @param  string  $rootNamespace
101
     * @return string
102
     */
103
    protected function getDefaultNamespace($rootNamespace)
104
    {
105
        return $rootNamespace.'\Http\Controllers';
106
    }
107
 
108
    /**
109
     * Build the class with the given name.
110
     *
111
     * Remove the base controller import if we are already in the base namespace.
112
     *
113
     * @param  string  $name
114
     * @return string
115
     */
116
    protected function buildClass($name)
117
    {
118
        $controllerNamespace = $this->getNamespace($name);
119
 
120
        $replace = [];
121
 
122
        if ($this->option('parent')) {
123
            $replace = $this->buildParentReplacements();
124
        }
125
 
126
        if ($this->option('model')) {
127
            $replace = $this->buildModelReplacements($replace);
128
        }
129
 
130
        if ($this->option('creatable')) {
131
            $replace['abort(404);'] = '//';
132
        }
133
 
134
        $replace["use {$controllerNamespace}\Controller;\n"] = '';
135
 
136
        return str_replace(
137
            array_keys($replace), array_values($replace), parent::buildClass($name)
138
        );
139
    }
140
 
141
    /**
142
     * Build the replacements for a parent controller.
143
     *
144
     * @return array
145
     */
146
    protected function buildParentReplacements()
147
    {
148
        $parentModelClass = $this->parseModel($this->option('parent'));
149
 
150
        if (! class_exists($parentModelClass) &&
151
            $this->components->confirm("A {$parentModelClass} model does not exist. Do you want to generate it?", true)) {
152
            $this->call('make:model', ['name' => $parentModelClass]);
153
        }
154
 
155
        return [
156
            'ParentDummyFullModelClass' => $parentModelClass,
157
            '{{ namespacedParentModel }}' => $parentModelClass,
158
            '{{namespacedParentModel}}' => $parentModelClass,
159
            'ParentDummyModelClass' => class_basename($parentModelClass),
160
            '{{ parentModel }}' => class_basename($parentModelClass),
161
            '{{parentModel}}' => class_basename($parentModelClass),
162
            'ParentDummyModelVariable' => lcfirst(class_basename($parentModelClass)),
163
            '{{ parentModelVariable }}' => lcfirst(class_basename($parentModelClass)),
164
            '{{parentModelVariable}}' => lcfirst(class_basename($parentModelClass)),
165
        ];
166
    }
167
 
168
    /**
169
     * Build the model replacement values.
170
     *
171
     * @param  array  $replace
172
     * @return array
173
     */
174
    protected function buildModelReplacements(array $replace)
175
    {
176
        $modelClass = $this->parseModel($this->option('model'));
177
 
178
        if (! class_exists($modelClass) && $this->components->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) {
179
            $this->call('make:model', ['name' => $modelClass]);
180
        }
181
 
182
        $replace = $this->buildFormRequestReplacements($replace, $modelClass);
183
 
184
        return array_merge($replace, [
185
            'DummyFullModelClass' => $modelClass,
186
            '{{ namespacedModel }}' => $modelClass,
187
            '{{namespacedModel}}' => $modelClass,
188
            'DummyModelClass' => class_basename($modelClass),
189
            '{{ model }}' => class_basename($modelClass),
190
            '{{model}}' => class_basename($modelClass),
191
            'DummyModelVariable' => lcfirst(class_basename($modelClass)),
192
            '{{ modelVariable }}' => lcfirst(class_basename($modelClass)),
193
            '{{modelVariable}}' => lcfirst(class_basename($modelClass)),
194
        ]);
195
    }
196
 
197
    /**
198
     * Get the fully-qualified model class name.
199
     *
200
     * @param  string  $model
201
     * @return string
202
     *
203
     * @throws \InvalidArgumentException
204
     */
205
    protected function parseModel($model)
206
    {
207
        if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) {
208
            throw new InvalidArgumentException('Model name contains invalid characters.');
209
        }
210
 
211
        return $this->qualifyModel($model);
212
    }
213
 
214
    /**
215
     * Build the model replacement values.
216
     *
217
     * @param  array  $replace
218
     * @param  string  $modelClass
219
     * @return array
220
     */
221
    protected function buildFormRequestReplacements(array $replace, $modelClass)
222
    {
223
        [$namespace, $storeRequestClass, $updateRequestClass] = [
224
            'Illuminate\\Http', 'Request', 'Request',
225
        ];
226
 
227
        if ($this->option('requests')) {
228
            $namespace = 'App\\Http\\Requests';
229
 
230
            [$storeRequestClass, $updateRequestClass] = $this->generateFormRequests(
231
                $modelClass, $storeRequestClass, $updateRequestClass
232
            );
233
        }
234
 
235
        $namespacedRequests = $namespace.'\\'.$storeRequestClass.';';
236
 
237
        if ($storeRequestClass !== $updateRequestClass) {
238
            $namespacedRequests .= PHP_EOL.'use '.$namespace.'\\'.$updateRequestClass.';';
239
        }
240
 
241
        return array_merge($replace, [
242
            '{{ storeRequest }}' => $storeRequestClass,
243
            '{{storeRequest}}' => $storeRequestClass,
244
            '{{ updateRequest }}' => $updateRequestClass,
245
            '{{updateRequest}}' => $updateRequestClass,
246
            '{{ namespacedStoreRequest }}' => $namespace.'\\'.$storeRequestClass,
247
            '{{namespacedStoreRequest}}' => $namespace.'\\'.$storeRequestClass,
248
            '{{ namespacedUpdateRequest }}' => $namespace.'\\'.$updateRequestClass,
249
            '{{namespacedUpdateRequest}}' => $namespace.'\\'.$updateRequestClass,
250
            '{{ namespacedRequests }}' => $namespacedRequests,
251
            '{{namespacedRequests}}' => $namespacedRequests,
252
        ]);
253
    }
254
 
255
    /**
256
     * Generate the form requests for the given model and classes.
257
     *
258
     * @param  string  $modelClass
259
     * @param  string  $storeRequestClass
260
     * @param  string  $updateRequestClass
261
     * @return array
262
     */
263
    protected function generateFormRequests($modelClass, $storeRequestClass, $updateRequestClass)
264
    {
265
        $storeRequestClass = 'Store'.class_basename($modelClass).'Request';
266
 
267
        $this->call('make:request', [
268
            'name' => $storeRequestClass,
269
        ]);
270
 
271
        $updateRequestClass = 'Update'.class_basename($modelClass).'Request';
272
 
273
        $this->call('make:request', [
274
            'name' => $updateRequestClass,
275
        ]);
276
 
277
        return [$storeRequestClass, $updateRequestClass];
278
    }
279
 
280
    /**
281
     * Get the console command options.
282
     *
283
     * @return array
284
     */
285
    protected function getOptions()
286
    {
287
        return [
288
            ['api', null, InputOption::VALUE_NONE, 'Exclude the create and edit methods from the controller'],
289
            ['type', null, InputOption::VALUE_REQUIRED, 'Manually specify the controller stub file to use'],
290
            ['force', null, InputOption::VALUE_NONE, 'Create the class even if the controller already exists'],
291
            ['invokable', 'i', InputOption::VALUE_NONE, 'Generate a single method, invokable controller class'],
292
            ['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate a resource controller for the given model'],
293
            ['parent', 'p', InputOption::VALUE_OPTIONAL, 'Generate a nested resource controller class'],
294
            ['resource', 'r', InputOption::VALUE_NONE, 'Generate a resource controller class'],
295
            ['requests', 'R', InputOption::VALUE_NONE, 'Generate FormRequest classes for store and update'],
296
            ['singleton', 's', InputOption::VALUE_NONE, 'Generate a singleton resource controller class'],
297
            ['creatable', null, InputOption::VALUE_NONE, 'Indicate that a singleton resource should be creatable'],
298
        ];
299
    }
300
}