You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
6.2 KiB
182 lines
6.2 KiB
4 years ago
|
<?php
|
||
|
|
||
|
namespace App\Console\Commands;
|
||
|
|
||
|
use Illuminate\Console\GeneratorCommand;
|
||
|
use Illuminate\Support\Facades\DB;
|
||
|
use Illuminate\Support\Str;
|
||
|
use Symfony\Component\Console\Input\InputOption;
|
||
|
|
||
|
class ApiControllerGenerator extends GeneratorCommand
|
||
|
{
|
||
|
/**
|
||
|
* The console command name.
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $name = 'make:apiController';
|
||
|
|
||
|
/**
|
||
|
* The console command description.
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $description = 'Create a new controller class';
|
||
|
|
||
|
/**
|
||
|
* The type of class being generated.
|
||
|
*
|
||
|
* @var string
|
||
|
*/
|
||
|
protected $type = 'Controller';
|
||
|
|
||
|
/**
|
||
|
* Get the stub file for the generator.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function getStub()
|
||
|
{
|
||
|
return $this->resolveStubPath('/stubs/controller.model.api.stub');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Resolve the fully-qualified path to the stub.
|
||
|
*
|
||
|
* @param string $stub
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function resolveStubPath($stub)
|
||
|
{
|
||
|
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
|
||
|
? $customPath
|
||
|
: __DIR__.$stub;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the default namespace for the class.
|
||
|
*
|
||
|
* @param string $rootNamespace
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function getDefaultNamespace($rootNamespace)
|
||
|
{
|
||
|
return $rootNamespace.'\Http\Controllers\Api';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Build the class with the given name.
|
||
|
*
|
||
|
* Remove the base controller import if we are already in base namespace.
|
||
|
*
|
||
|
* @param string $name
|
||
|
* @return string
|
||
|
*/
|
||
|
protected function buildClass($name)
|
||
|
{
|
||
|
$modelClass = $this->parseModel(Str::replaceLast('Controller', 'T', class_basename($name)));
|
||
|
|
||
|
if (! class_exists($modelClass)) {
|
||
|
if ($this->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) {
|
||
|
$this->call('make:apiModel', ['name' => $modelClass]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$resourceClass = $this->qualifyResource(Str::replaceLast('Controller', '', class_basename($name)));
|
||
|
if (! class_exists($resourceClass)) {
|
||
|
if ($this->confirm("A {$resourceClass} resource does not exist. Do you want to generate it?", true)) {
|
||
|
$this->call('make:apiResource', ['name' => $resourceClass]);
|
||
|
}
|
||
|
}
|
||
|
$resourceCollectionClass = $resourceClass . 'Collection';
|
||
|
if (! class_exists($resourceCollectionClass)) {
|
||
|
if ($this->confirm("A {$resourceCollectionClass} resource collection does not exist. Do you want to generate it?", true)) {
|
||
|
$this->call('make:resource', ['name' => $resourceCollectionClass]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$table_name = env('DB_PREFIX') . Str::snake(str_replace([$this->getNamespace($name).'\\', 'Controller'], ['','T'], $name));
|
||
|
$columns = DB::select("select COLUMN_NAME,DATA_TYPE,IS_NULLABLE,COLUMN_DEFAULT from information_schema.COLUMNS where table_name = '$table_name'");
|
||
|
$attributes = '';
|
||
|
$rules = '';
|
||
|
foreach ($columns as $column){
|
||
|
if(!in_array($column->COLUMN_NAME, ['id', 'created_at', 'updated_at'])){
|
||
|
$attributes .= ' $this->model->'. $column->COLUMN_NAME .' = $this->params[\''. $column->COLUMN_NAME .'\']';
|
||
|
$rule = " '{$column->COLUMN_NAME}' => '";
|
||
|
if ($column->IS_NULLABLE == 'NO' && $column->COLUMN_DEFAULT === null) {
|
||
|
$rule .= 'required|';
|
||
|
}
|
||
|
if(in_array($column->DATA_TYPE, ['int','integer', 'tinyint','smallint','mediumint','bigint','decimal'])){
|
||
|
$rule .= 'numeric|';
|
||
|
$attributes .= ' ?? 0';
|
||
|
}
|
||
|
if(in_array($column->DATA_TYPE, ['varchar','char'])){
|
||
|
$rule .= 'string|';
|
||
|
$attributes .= ' ?? \'\'';
|
||
|
}
|
||
|
$attributes .= ';'. PHP_EOL;
|
||
|
if (Str::endsWith($rule,'|')) {
|
||
|
$rules .= Str::replaceLast('|', '', $rule) .'\',' . PHP_EOL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
$replace = [
|
||
|
'{{ namespacedModel }}' => $modelClass,
|
||
|
'{{ model }}' => class_basename($modelClass),
|
||
|
'{{ namespacedResource }}' => $resourceClass,
|
||
|
'{{ resource }}' => class_basename($resourceClass),
|
||
|
'{{ namespacedResourceCollection }}' => $resourceCollectionClass,
|
||
|
'{{ resourceCollection }}' => class_basename($resourceCollectionClass),
|
||
|
'{{ attrList }}' => Str::replaceLast(PHP_EOL, '', $attributes),
|
||
|
'{{ ruleList }}' => Str::replaceLast(PHP_EOL, '', $rules),
|
||
|
];
|
||
|
|
||
|
return str_replace(
|
||
|
array_keys($replace), array_values($replace), parent::buildClass($name)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
protected function qualifyResource(string $name)
|
||
|
{
|
||
|
$rootNamespace = $this->rootNamespace();
|
||
|
|
||
|
return $rootNamespace. 'Http' . DIRECTORY_SEPARATOR .'Resources'. DIRECTORY_SEPARATOR . $name;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the fully-qualified model class name.
|
||
|
*
|
||
|
* @param string $model
|
||
|
* @return string
|
||
|
*
|
||
|
* @throws \InvalidArgumentException
|
||
|
*/
|
||
|
protected function parseModel($model)
|
||
|
{
|
||
|
if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) {
|
||
|
throw new InvalidArgumentException('Model name contains invalid characters.');
|
||
|
}
|
||
|
|
||
|
return $this->qualifyModel($model);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the console command options.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
protected function getOptions()
|
||
|
{
|
||
|
return [
|
||
|
['api', null, InputOption::VALUE_NONE, 'Exclude the create and edit methods from the controller.'],
|
||
|
['force', null, InputOption::VALUE_NONE, 'Create the class even if the controller already exists'],
|
||
|
['invokable', 'i', InputOption::VALUE_NONE, 'Generate a single method, invokable controller class.'],
|
||
|
['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate a resource controller for the given model.'],
|
||
|
['parent', 'p', InputOption::VALUE_OPTIONAL, 'Generate a nested resource controller class.'],
|
||
|
['resource', 'r', InputOption::VALUE_NONE, 'Generate a resource controller class.'],
|
||
|
];
|
||
|
}
|
||
|
}
|