6 changed files with 481 additions and 2 deletions
-
113src/CrudApiMake.php
-
19src/Generators/ControllerGenerator.php
-
1src/ServiceProvider.php
-
88src/stubs/controller.api.stub
-
156tests/CrudApiMakeCommandTest.php
-
106tests/Generators/Api/ApiControllerGeneratorTest.php
@ -0,0 +1,113 @@ |
|||
<?php |
|||
|
|||
namespace Luthfi\CrudGenerator; |
|||
|
|||
class CrudApiMake extends GeneratorCommand |
|||
{ |
|||
/** |
|||
* The name and signature of the console command. |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $signature = 'make:crud-api {name} {--p|parent=} {--t|tests-only}'; |
|||
|
|||
/** |
|||
* The console command description. |
|||
* |
|||
* @var string |
|||
*/ |
|||
protected $description = 'Create simple Laravel API CRUD files of given model name.'; |
|||
|
|||
/** |
|||
* Execute the console command. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function handle() |
|||
{ |
|||
$this->getModelName(); |
|||
|
|||
if ($this->modelExists()) { |
|||
$this->error("{$this->modelNames['model_name']} model already exists."); |
|||
return; |
|||
} |
|||
|
|||
// Warn if it has no default layout view based on
|
|||
// simple-crud.default_layout_view config
|
|||
if ($this->defaultLayoutNotExists()) { |
|||
$this->warn(config('simple-crud.default_layout_view').' view does not exists.'); |
|||
} |
|||
|
|||
if ($this->option('tests-only')) { |
|||
$this->generateTestFiles(); |
|||
|
|||
$this->info('Test files generated successfully!'); |
|||
return; |
|||
} |
|||
|
|||
$this->generateRoutes(); |
|||
$this->generateModel(); |
|||
$this->generateController(); |
|||
$this->generateResources(); |
|||
$this->generateTestFiles(); |
|||
|
|||
$this->info('CRUD files generated successfully!'); |
|||
} |
|||
|
|||
/** |
|||
* Generate test files |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function generateTestFiles() |
|||
{ |
|||
app('Luthfi\CrudGenerator\Generators\ModelTestGenerator', ['command' => $this])->generate(); |
|||
app('Luthfi\CrudGenerator\Generators\FeatureTestGenerator', ['command' => $this])->generate('simple'); |
|||
app('Luthfi\CrudGenerator\Generators\ModelPolicyTestGenerator', ['command' => $this])->generate(); |
|||
} |
|||
|
|||
/** |
|||
* Generate Controller |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function generateController() |
|||
{ |
|||
app('Luthfi\CrudGenerator\Generators\ControllerGenerator', ['command' => $this])->generate('api'); |
|||
} |
|||
|
|||
/** |
|||
* Generate Model |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function generateModel() |
|||
{ |
|||
app('Luthfi\CrudGenerator\Generators\ModelGenerator', ['command' => $this])->generate(); |
|||
app('Luthfi\CrudGenerator\Generators\MigrationGenerator', ['command' => $this])->generate(); |
|||
app('Luthfi\CrudGenerator\Generators\ModelPolicyGenerator', ['command' => $this])->generate(); |
|||
app('Luthfi\CrudGenerator\Generators\ModelFactoryGenerator', ['command' => $this])->generate(); |
|||
} |
|||
|
|||
/** |
|||
* Generate Route Route |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function generateRoutes() |
|||
{ |
|||
app('Luthfi\CrudGenerator\Generators\WebRouteGenerator', ['command' => $this])->generate(); |
|||
} |
|||
|
|||
/** |
|||
* Generate Resources |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function generateResources() |
|||
{ |
|||
app('Luthfi\CrudGenerator\Generators\LangFileGenerator', ['command' => $this])->generate(); |
|||
app('Luthfi\CrudGenerator\Generators\FormViewGenerator', ['command' => $this])->generate('simple'); |
|||
app('Luthfi\CrudGenerator\Generators\IndexViewGenerator', ['command' => $this])->generate('simple'); |
|||
} |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
<?php |
|||
|
|||
namespace App\Http\Controllers\Api; |
|||
|
|||
use fullMstr; |
|||
use Illuminate\Http\Request; |
|||
|
|||
class MastersController extends Controller |
|||
{ |
|||
/** |
|||
* Display a listing of the singleMstr. |
|||
* |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function index() |
|||
{ |
|||
$mstrCollections = Master::where(function ($query) { |
|||
$query->where('name', 'like', '%'.request('q').'%'); |
|||
})->paginate(25); |
|||
|
|||
return $mstrCollections; |
|||
} |
|||
|
|||
/** |
|||
* Store a newly created singleMstr in storage. |
|||
* |
|||
* @param \Illuminate\Http\Request $request |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function store(Request $request) |
|||
{ |
|||
$this->authorize('create', new Master); |
|||
|
|||
$this->validate($request, [ |
|||
'name' => 'required|max:60', |
|||
'description' => 'nullable|max:255', |
|||
]); |
|||
|
|||
$newMaster = $request->only('name', 'description'); |
|||
$newMaster['creator_id'] = auth()->id(); |
|||
|
|||
$singleMstr = Master::create($newMaster); |
|||
|
|||
return $singleMstr; |
|||
} |
|||
|
|||
/** |
|||
* Update the specified singleMstr in storage. |
|||
* |
|||
* @param \Illuminate\Http\Request $request |
|||
* @param \fullMstr $singleMstr |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function update(Request $request, Master $singleMstr) |
|||
{ |
|||
$this->authorize('update', $singleMstr); |
|||
|
|||
$this->validate($request, [ |
|||
'name' => 'required|max:60', |
|||
'description' => 'nullable|max:255', |
|||
]); |
|||
|
|||
$singleMstr->update($request->only('name', 'description')); |
|||
|
|||
return $singleMstr; |
|||
} |
|||
|
|||
/** |
|||
* Remove the specified singleMstr from storage. |
|||
* |
|||
* @param \fullMstr $singleMstr |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function destroy(Master $singleMstr) |
|||
{ |
|||
$this->authorize('delete', $singleMstr); |
|||
|
|||
$this->validate(request(), [ |
|||
'master_id' => 'required', |
|||
]); |
|||
|
|||
if (request('master_id') == $singleMstr->id && $singleMstr->delete()) { |
|||
return response()->json('master deleted.', 204); |
|||
} |
|||
|
|||
return response()->json('Unprocessable Entity.', 422); |
|||
} |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
<?php |
|||
|
|||
namespace Tests; |
|||
|
|||
use Illuminate\Contracts\Console\Kernel; |
|||
|
|||
class CrudApiMakeCommandTest extends TestCase |
|||
{ |
|||
/** @test */ |
|||
public function it_can_generate_api_crud_files() |
|||
{ |
|||
$this->artisan('make:crud-api', ['name' => $this->model_name, '--no-interaction' => true]); |
|||
|
|||
$this->assertNotContains("{$this->model_name} model already exists.", app(Kernel::class)->output()); |
|||
|
|||
$this->assertFileExists(app_path($this->model_name.'.php')); |
|||
$this->assertFileExists(app_path("Http/Controllers/Api/{$this->plural_model_name}Controller.php")); |
|||
|
|||
$migrationFilePath = database_path('migrations/'.date('Y_m_d_His').'_create_'.$this->table_name.'_table.php'); |
|||
$this->assertFileExists($migrationFilePath); |
|||
|
|||
$this->assertFileExists(resource_path("views/{$this->table_name}/index.blade.php")); |
|||
$this->assertFileExists(resource_path("views/{$this->table_name}/forms.blade.php")); |
|||
|
|||
$localeConfig = config('app.locale'); |
|||
$this->assertFileExists(resource_path("lang/{$localeConfig}/{$this->lang_name}.php")); |
|||
|
|||
$this->assertFileExists(base_path("routes/web.php")); |
|||
$this->assertFileExists(app_path("Policies/{$this->model_name}Policy.php")); |
|||
$this->assertFileExists(database_path("factories/{$this->model_name}Factory.php")); |
|||
$this->assertFileExists(base_path("tests/Unit/Models/{$this->model_name}Test.php")); |
|||
$this->assertFileExists(base_path("tests/Feature/Manage{$this->plural_model_name}Test.php")); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function it_cannot_generate_crud_files_if_model_exists() |
|||
{ |
|||
$this->artisan('make:model', ['name' => $this->model_name, '--no-interaction' => true]); |
|||
$this->artisan('make:crud', ['name' => $this->model_name, '--no-interaction' => true]); |
|||
|
|||
$this->assertContains("{$this->model_name} model already exists.", app(Kernel::class)->output()); |
|||
|
|||
$this->assertFileExists(app_path($this->model_name.'.php')); |
|||
$this->assertFileNotExists(app_path("Http/Controllers/Api/{$this->plural_model_name}Controller.php")); |
|||
|
|||
$migrationFilePath = database_path('migrations/'.date('Y_m_d_His').'_create_'.$this->table_name.'_table.php'); |
|||
$this->assertFileNotExists($migrationFilePath); |
|||
|
|||
$this->assertFileNotExists(resource_path("views/{$this->table_name}/index.blade.php")); |
|||
$this->assertFileNotExists(resource_path("views/{$this->table_name}/forms.blade.php")); |
|||
|
|||
$localeConfig = config('app.locale'); |
|||
$this->assertFileNotExists(resource_path("lang/{$localeConfig}/{$this->lang_name}.php")); |
|||
|
|||
$this->assertFileNotExists(base_path("routes/web.php")); |
|||
$this->assertFileNotExists(app_path("Policies/{$this->model_name}Policy.php")); |
|||
$this->assertFileNotExists(database_path("factories/{$this->model_name}Factory.php")); |
|||
$this->assertFileNotExists(base_path("tests/Unit/Models/{$this->model_name}Test.php")); |
|||
$this->assertFileNotExists(base_path("tests/Feature/Manage{$this->plural_model_name}Test.php")); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function it_cannot_generate_crud_files_if_namespaced_model_exists() |
|||
{ |
|||
$this->artisan('make:model', ['name' => 'Entities/Projects/Problem', '--no-interaction' => true]); |
|||
$this->artisan('make:crud-api', ['name' => 'Entities/Projects/Problem', '--no-interaction' => true]); |
|||
|
|||
$this->assertContains("Problem model already exists.", app(Kernel::class)->output()); |
|||
|
|||
$this->assertFileExists(app_path('Entities/Projects/Problem.php')); |
|||
$this->assertFileNotExists(app_path("Http/Controllers/Api/ProblemsController.php")); |
|||
|
|||
$migrationFilePath = database_path('migrations/'.date('Y_m_d_His').'_create_problems_table.php'); |
|||
$this->assertFileNotExists($migrationFilePath); |
|||
|
|||
$this->assertFileNotExists(resource_path("views/problems/index.blade.php")); |
|||
$this->assertFileNotExists(resource_path("views/problems/forms.blade.php")); |
|||
|
|||
$localeConfig = config('app.locale'); |
|||
$this->assertFileNotExists(resource_path("lang/{$localeConfig}/{$this->lang_name}.php")); |
|||
|
|||
$this->assertFileNotExists(app_path("Policies/ProblemPolicy.php")); |
|||
$this->assertFileNotExists(database_path("factories/ProblemFactory.php")); |
|||
$this->assertFileNotExists(base_path("tests/Unit/Models/ProblemTest.php")); |
|||
$this->assertFileNotExists(base_path("tests/Feature/ManageProblemsTest.php")); |
|||
|
|||
$this->removeFileOrDir(app_path('Entities/Projects')); |
|||
$this->removeFileOrDir(resource_path('views/problems')); |
|||
$this->removeFileOrDir(resource_path("lang/en/problem.php")); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function it_can_generate_crud_files_for_namespaced_model() |
|||
{ |
|||
$inputName = 'Entities/References/Category'; |
|||
$modelName = 'Category'; |
|||
$pluralModelName = 'Categories'; |
|||
$tableName = 'categories'; |
|||
$langName = 'category'; |
|||
$modelPath = 'Entities/References'; |
|||
|
|||
$this->artisan('make:crud-api', ['name' => $inputName, '--no-interaction' => true]); |
|||
|
|||
$this->assertNotContains("{$modelName} model already exists.", app(Kernel::class)->output()); |
|||
|
|||
$this->assertFileExists(app_path($modelPath.'/'.$modelName.'.php')); |
|||
$this->assertFileExists(app_path("Http/Controllers/Api/{$pluralModelName}Controller.php")); |
|||
|
|||
$migrationFilePath = database_path('migrations/'.date('Y_m_d_His').'_create_'.$tableName.'_table.php'); |
|||
$this->assertFileExists($migrationFilePath); |
|||
|
|||
$this->assertFileExists(resource_path("views/{$tableName}/index.blade.php")); |
|||
$this->assertFileExists(resource_path("views/{$tableName}/forms.blade.php")); |
|||
|
|||
$localeConfig = config('app.locale'); |
|||
$this->assertFileExists(resource_path("lang/{$localeConfig}/{$langName}.php")); |
|||
|
|||
$this->assertFileExists(app_path("Policies/{$modelName}Policy.php")); |
|||
$this->assertFileExists(database_path("factories/{$modelName}Factory.php")); |
|||
$this->assertFileExists(base_path("tests/Unit/Models/{$modelName}Test.php")); |
|||
$this->assertFileExists(base_path("tests/Feature/Manage{$pluralModelName}Test.php")); |
|||
} |
|||
|
|||
/** @test */ |
|||
public function it_can_generate_crud_files_with_parent_option() |
|||
{ |
|||
$inputName = 'Entities/References/Category'; |
|||
$modelName = 'Category'; |
|||
$parentName = 'Projects'; |
|||
$pluralModelName = 'Categories'; |
|||
$tableName = 'categories'; |
|||
$langName = 'category'; |
|||
$modelPath = 'Entities/References'; |
|||
|
|||
$this->artisan('make:crud-api', ['name' => $inputName, '--parent' => $parentName, '--no-interaction' => true]); |
|||
|
|||
$this->assertNotContains("{$modelName} model already exists.", app(Kernel::class)->output()); |
|||
|
|||
$this->assertFileExists(app_path($modelPath.'/'.$modelName.'.php')); |
|||
$this->assertFileExists(app_path("Http/Controllers/Api/{$parentName}/{$pluralModelName}Controller.php")); |
|||
|
|||
$migrationFilePath = database_path('migrations/'.date('Y_m_d_His').'_create_'.$tableName.'_table.php'); |
|||
$this->assertFileExists($migrationFilePath); |
|||
|
|||
$this->assertFileExists(resource_path("views/{$tableName}/index.blade.php")); |
|||
$this->assertFileExists(resource_path("views/{$tableName}/forms.blade.php")); |
|||
|
|||
$localeConfig = config('app.locale'); |
|||
$this->assertFileExists(resource_path("lang/{$localeConfig}/{$langName}.php")); |
|||
|
|||
$this->assertFileExists(database_path("factories/{$modelName}Factory.php")); |
|||
$this->assertFileExists(base_path("tests/Unit/Models/{$modelName}Test.php")); |
|||
$this->assertFileExists(app_path("Policies/{$parentName}/{$modelName}Policy.php")); |
|||
$this->assertFileExists(base_path("tests/Feature/Manage{$pluralModelName}Test.php")); |
|||
} |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
<?php |
|||
|
|||
namespace Tests\Generators\Simple; |
|||
|
|||
use Tests\TestCase; |
|||
|
|||
class ApiControllerGeneratorTest extends TestCase |
|||
{ |
|||
/** @test */ |
|||
public function it_creates_correct_controller_class_content() |
|||
{ |
|||
$this->artisan('make:crud-api', ['name' => $this->model_name, '--no-interaction' => true]); |
|||
|
|||
$this->assertFileExists(app_path("Http/Controllers/Api/{$this->plural_model_name}Controller.php")); |
|||
$ctrlClassContent = "<?php
|
|||
|
|||
namespace App\Http\Controllers\Api; |
|||
|
|||
use {$this->full_model_name}; |
|||
use Illuminate\Http\Request; |
|||
|
|||
class {$this->plural_model_name}Controller extends Controller |
|||
{ |
|||
/** |
|||
* Display a listing of the {$this->single_model_var_name}. |
|||
* |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function index() |
|||
{ |
|||
\${$this->collection_model_var_name} = {$this->model_name}::where(function (\$query) { |
|||
\$query->where('name', 'like', '%'.request('q').'%'); |
|||
})->paginate(25); |
|||
|
|||
return \${$this->collection_model_var_name}; |
|||
} |
|||
|
|||
/** |
|||
* Store a newly created {$this->single_model_var_name} in storage. |
|||
* |
|||
* @param \Illuminate\Http\Request \$request |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function store(Request \$request) |
|||
{ |
|||
\$this->authorize('create', new {$this->model_name}); |
|||
|
|||
\$this->validate(\$request, [ |
|||
'name' => 'required|max:60', |
|||
'description' => 'nullable|max:255', |
|||
]); |
|||
|
|||
\$new{$this->model_name} = \$request->only('name', 'description'); |
|||
\$new{$this->model_name}['creator_id'] = auth()->id(); |
|||
|
|||
\${$this->single_model_var_name} = {$this->model_name}::create(\$new{$this->model_name}); |
|||
|
|||
return \${$this->single_model_var_name}; |
|||
} |
|||
|
|||
/** |
|||
* Update the specified {$this->single_model_var_name} in storage. |
|||
* |
|||
* @param \Illuminate\Http\Request \$request |
|||
* @param \\{$this->full_model_name} \${$this->single_model_var_name} |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function update(Request \$request, {$this->model_name} \${$this->single_model_var_name}) |
|||
{ |
|||
\$this->authorize('update', \${$this->single_model_var_name}); |
|||
|
|||
\$this->validate(\$request, [ |
|||
'name' => 'required|max:60', |
|||
'description' => 'nullable|max:255', |
|||
]); |
|||
|
|||
\${$this->single_model_var_name}->update(\$request->only('name', 'description')); |
|||
|
|||
return \${$this->single_model_var_name}; |
|||
} |
|||
|
|||
/** |
|||
* Remove the specified {$this->single_model_var_name} from storage. |
|||
* |
|||
* @param \\{$this->full_model_name} \${$this->single_model_var_name} |
|||
* @return \Illuminate\Http\Response |
|||
*/ |
|||
public function destroy({$this->model_name} \${$this->single_model_var_name}) |
|||
{ |
|||
\$this->authorize('delete', \${$this->single_model_var_name}); |
|||
|
|||
\$this->validate(request(), [ |
|||
'{$this->lang_name}_id' => 'required', |
|||
]); |
|||
|
|||
if (request('{$this->lang_name}_id') == \${$this->single_model_var_name}->id && \${$this->single_model_var_name}->delete()) { |
|||
return response()->json('{$this->lang_name} deleted.', 204); |
|||
} |
|||
|
|||
return response()->json('Unprocessable Entity.', 422); |
|||
} |
|||
} |
|||
";
|
|||
$this->assertEquals($ctrlClassContent, file_get_contents(app_path("Http/Controllers/Api/{$this->plural_model_name}Controller.php"))); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue