Skip to content

Commit 8d7e1da

Browse files
committed
Adds create:mapped-resource command to allow creating bulk resources
1 parent 3fafeb9 commit 8d7e1da

11 files changed

+566
-128
lines changed

config/codegenerator.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,20 @@
106106
*/
107107
'languages_path' => 'resources/lang',
108108

109+
/*
110+
|--------------------------------------------------------------------------
111+
| The name of the default resource mapper.
112+
|--------------------------------------------------------------------------
113+
*/
114+
'default_mapper_file_name' => 'resources_map.json',
115+
116+
/*
117+
|--------------------------------------------------------------------------
118+
| Should the code generator auto manage resources mappers?
119+
|--------------------------------------------------------------------------
120+
*/
121+
'auto_manage_resource_mapper' => true,
122+
109123
/*
110124
|--------------------------------------------------------------------------
111125
| Key phrases that are will be used to determine if a field name should be used for header.

src/CodeGeneratorServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@ public function register()
5656
'CrestApps\CodeGenerator\Commands\CreateRoutesCommand',
5757
'CrestApps\CodeGenerator\Commands\CreateMigrationCommand',
5858
'CrestApps\CodeGenerator\Commands\CreateResourcesCommand',
59+
'CrestApps\CodeGenerator\Commands\CreateMappedResourcesCommand',
5960
'CrestApps\CodeGenerator\Commands\CreateViewLayoutCommand',
6061
'CrestApps\CodeGenerator\Commands\CreateLayoutCommand',
6162
'CrestApps\CodeGenerator\Commands\CreateFieldsFileCommand',
6263
'CrestApps\CodeGenerator\Commands\FieldsFileCreateCommand',
64+
'CrestApps\CodeGenerator\Commands\FieldsFileDeleteCommand',
6365
'CrestApps\CodeGenerator\Commands\FieldsFileAppendCommand',
6466
'CrestApps\CodeGenerator\Commands\FieldsFileReduceCommand'
6567
);

src/Commands/CreateFieldsFileCommand.php

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,53 @@ public function handle()
5757
return false;
5858
}
5959

60-
$content = $this->getFieldAsJson();
60+
$content = $this->getFieldsAsJson();
61+
62+
63+
if(Config::autoManageResourceMapper()) {
64+
$this->appendMapper($this->getModelName(), $this->getFilename());
65+
}
6166

6267
$this->createFile($destenationFile, $content)
63-
->info('A new Fields file have been created.');
68+
->info('The fields file "'. $this->getFilename() .'" was crafted!');
69+
}
70+
71+
/**
72+
* Removes mapping entry from the default mapping file.
73+
*
74+
* @param string $modelName
75+
* @param string $fieldsFileName
76+
*
77+
* @return void
78+
*/
79+
protected function appendMapper($modelName, $fieldsFileName)
80+
{
81+
$file = $path = base_path(Config::getFieldsFilePath(Config::getDefaultMapperFileName()));
82+
83+
$fields = [];
84+
85+
if($this->isFileExists($file)){
86+
$content = $this->getFileContent($file);
87+
88+
$existingFields = json_decode($content);
89+
90+
if(is_null($existingFields)) {
91+
$this->error('The existing mapping file contains invalid json string. Please fix the file then try again');
92+
return false;
93+
}
94+
95+
$existingFields = Collect($existingFields)->filter(function($resource) use($modelName) {
96+
return isset($resource->{'model-name'}) && $resource->{'model-name'} != $modelName;
97+
});
98+
99+
$fields = Collect($existingFields)->push(
100+
[
101+
'model-name' => $modelName,
102+
'fields-file' => $fieldsFileName,
103+
]);
104+
}
105+
106+
$this->putContentInFile($file, json_encode($fields, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
64107
}
65108

66109
/**
@@ -69,7 +112,7 @@ public function handle()
69112
*
70113
* @return string
71114
*/
72-
protected function getFieldAsJson()
115+
protected function getFieldsAsJson()
73116
{
74117
$fields = array_map(function ($field) {
75118
return $field->toArray();
@@ -85,7 +128,7 @@ protected function getFieldAsJson()
85128
*/
86129
protected function getDestinationFullname()
87130
{
88-
return base_path(Config::getFieldsFilePath()) . $this->getFilename();
131+
return base_path(Config::getFieldsFilePath($this->getFilename()));
89132
}
90133

91134
/**
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
<?php
2+
3+
namespace CrestApps\CodeGenerator\Commands;
4+
5+
use Exception;
6+
use Illuminate\Console\Command;
7+
use CrestApps\CodeGenerator\Support\Helpers;
8+
use CrestApps\CodeGenerator\Traits\CommonCommand;
9+
use CrestApps\CodeGenerator\Support\Config;
10+
use CrestApps\CodeGenerator\Models\ResourceInput;
11+
12+
class CreateMappedResourcesCommand extends Command
13+
{
14+
use CommonCommand;
15+
16+
/**
17+
* The name and signature of the console command.
18+
*
19+
* @var string
20+
*/
21+
protected $signature = 'create:mapped-resources
22+
{--controller-directory= : The directory where the controller should be created under. }
23+
{--controller-extends=Http\Controllers\Controller : The base controller to be extend.}
24+
{--model-directory= : The path of the model.}
25+
{--views-directory= : The name of the view path.}
26+
{--models-per-page=25 : The amount of models per page for index pages.}
27+
{--with-form-request : This will extract the validation into a request form class.}
28+
{--with-auth : Generate the controller with Laravel auth middlewear. }
29+
{--with-soft-delete : Enables softdelete future should be enable in the model.}
30+
{--without-timestamps : Prevent Eloquent from maintaining both created_at and the updated_at properties.}
31+
{--without-migration : Prevent creating a migration for this resource.}
32+
{--connection-name= : A specific connection name.}
33+
{--engine-name= : A specific engine name.}
34+
{--layout-name=layouts.app : This will extract the validation into a request form class.}
35+
{--template-name= : The template name to use when generating the code.}
36+
{--table-exists : This option will attempt to fetch the field from existing database table.}
37+
{--primary-key=id : The name of the primary key.}
38+
{--translation-for= : A comma seperated string of languages to create fields for.}
39+
{--mapping-filename= : The name of the resource mapping file.}
40+
{--force : This option will override the controller if one already exists.}';
41+
42+
43+
/**
44+
* The console command description.
45+
*
46+
* @var string
47+
*/
48+
protected $description = 'Create all resources for every model listed in the resources mapping file.';
49+
50+
/**
51+
* Executes the console command.
52+
*
53+
* @return void
54+
*/
55+
public function handle()
56+
{
57+
$content = $this->getFileContent($this->getMappingFile());
58+
59+
$objects = json_decode($content);
60+
61+
if (!is_array($objects)) {
62+
throw new Exception('The mapping-file does not contain a valid array.');
63+
}
64+
65+
$validInputs = $this->getValidInputs($objects, $this->getCommandInput());
66+
67+
foreach ($validInputs as $validInput) {
68+
69+
$this->call('create:resources',
70+
[
71+
'model-name' => $validInput->modelName,
72+
'--controller-name' => $validInput->controllerName,
73+
'--controller-directory' => $validInput->controllerDirectory,
74+
'--controller-extends' => $validInput->controllerExtends,
75+
'--model-directory' => $validInput->modelDirectory,
76+
'--views-directory' => $validInput->viewsDirectory,
77+
'--fields-file' => $validInput->fieldsFile,
78+
'--fields' => $validInput->fields,
79+
'--routes-prefix' => $validInput->prefix,
80+
'--models-per-page' => $validInput->perPage,
81+
'--lang-file-name' => $validInput->languageFileName,
82+
'--with-form-request' => $validInput->formRequest,
83+
'--with-auth' => $validInput->withAuth,
84+
'--table-name' => $validInput->table,
85+
'--fillable' => $validInput->fillable,
86+
'--primary-key' => $validInput->primaryKey,
87+
'--with-soft-delete' => $validInput->withSoftDelete,
88+
'--without-timestamps' => $validInput->withoutTimeStamps,
89+
'--relationships' => $validInput->relationships,
90+
'--without-migration' => $validInput->withoutMigration,
91+
'--migration-class-name' => $validInput->migrationClass,
92+
'--connection-name' => $validInput->connectionName,
93+
'--indexes' => $validInput->indexes,
94+
'--foreign-keys' => $validInput->foreignKeys,
95+
'--engine-name' => $validInput->engineName,
96+
'--layout-name' => $validInput->layoutName,
97+
'--template-name' => $validInput->template,
98+
'--table-exists' => $validInput->tableExists,
99+
'--translation-for' => $validInput->translationFor,
100+
'--force' => $validInput->force
101+
]);
102+
103+
$this->info('---------------------------------');
104+
}
105+
106+
return $this->printInfo('All Done!');
107+
108+
}
109+
110+
/**
111+
* Gets valid input collection
112+
*
113+
* @param array $object
114+
* @param CrestApps\CodeGenerator\Models\ResourceInput $input
115+
*
116+
* @return array of CrestApps\CodeGenerator\Models\ResourceInput
117+
*/
118+
protected function getValidInputs(array $objects, ResourceInput $originalInput)
119+
{
120+
$validInputs = [];
121+
122+
foreach ($objects as $object) {
123+
$input = clone $originalInput;
124+
if(!isset($object->{'model-name'})) {
125+
throw new Exception('Each entry in the mapping file must a have value for model-name');
126+
}
127+
128+
$input->modelName = trim($object->{'model-name'});
129+
$madeupTableName = $this->makeTableName($input->modelName);
130+
$controllerName = Helpers::makeControllerName($input->modelName);
131+
$input->fieldsFile = $this->getValue($object, 'fields-file', Helpers::makeJsonFileName($input->modelName));
132+
$input->table = $this->getValue($object, 'table-name', $madeupTableName);
133+
$input->fields = null;
134+
$input->prefix = $this->getValue($object, 'routes-prefix', $madeupTableName);
135+
$input->controllerName = $this->getValue($object, 'controller-name', $controllerName);
136+
$input->languageFileName = $this->getValue($object, 'lang-file-name', $madeupTableName);
137+
$input->table = $this->getValue($object, 'table-name', $madeupTableName);
138+
$input->viewsDirectory = $this->getValue($object, 'views-directory', $input->viewsDirectory);
139+
$input->perPage = $this->getValue($object, 'models-per-page', $input->perPage);
140+
$input->formRequest = $this->getValue($object, 'with-form-request', $input->formRequest);
141+
$input->controllerDirectory = $this->getValue($object, 'controller-directory', $input->controllerDirectory);
142+
$input->controllerExtends = $this->getValue($object, 'controller-extends', $input->controllerExtends);
143+
$input->withoutMigration = $this->getValue($object, 'without-migration', $input->withoutMigration);
144+
$input->force = $this->getValue($object, 'force', $input->force);
145+
$input->modelDirectory = $this->getValue($object, 'model-directory', $input->modelDirectory);
146+
$input->fillable = $this->getValue($object, 'fillable', $input->fillable);
147+
$input->primaryKey = $this->getValue($object, 'primary-key', $input->primaryKey);
148+
$input->relationships = $this->getValue($object, 'relationships', $input->relationships);
149+
$input->withSoftDelete = $this->getValue($object, 'with-soft-delete', $input->withSoftDelete);
150+
$input->withoutTimeStamps = $this->getValue($object, 'without-timestamps', $input->withoutTimeStamps);
151+
$input->migrationClass = $this->getValue($object, 'migration-class-name', $input->migrationClass);
152+
$input->connectionName = $this->getValue($object, 'connection-name', $input->connectionName);
153+
$input->indexes = $this->getValue($object, 'indexes', $input->indexes);
154+
$input->foreignKeys = $this->getValue($object, 'foreign-keys', $input->foreignKeys);
155+
$input->engineName = $this->getValue($object, 'engine-name', $input->engineName);
156+
$input->template = $this->getValue($object, 'template-name', $input->template);
157+
$input->layoutName = $this->getValue($object, 'layout-name', $input->layoutName);
158+
$input->tableExists = $this->getValue($object, 'table-exists', $input->tableExists);
159+
$input->translationFor = $this->getValue($object, 'translation-for', $input->translationFor);
160+
$input->withAuth = $this->getValue($object, 'with-auth', $input->withAuth);
161+
162+
$fields = $this->getFields($input->fields, $input->languageFileName, $input->fieldsFile);
163+
164+
$this->validateField($fields);
165+
$validInputs[] = $input;
166+
}
167+
168+
return $validInputs;
169+
}
170+
171+
/**
172+
* Gets the full name of the mapping file.
173+
*
174+
* @return string
175+
*/
176+
protected function getMappingFile()
177+
{
178+
$name = trim($this->option('mapping-filename')) ?: Config::getDefaultMapperFileName();
179+
180+
return base_path(Config::getFieldsFilePath($name));
181+
}
182+
183+
/**
184+
* Gets the value of a property of a givig object if exists.
185+
*
186+
* @param object $object
187+
* @param string $name
188+
* @param mix $default
189+
*
190+
* @return mix
191+
*/
192+
protected function getValue($object, $name, $default = null)
193+
{
194+
if (isset($object->{$name})) {
195+
return $object->{$name};
196+
}
197+
198+
return $default;
199+
}
200+
201+
/**
202+
* Prints a message
203+
*
204+
* @param string $message
205+
*
206+
* @return $this
207+
*/
208+
protected function printInfo($message)
209+
{
210+
$this->info($message);
211+
212+
return $this;
213+
}
214+
215+
/**
216+
* Ensured fields contains at least one field.
217+
*
218+
* @param array $fields
219+
*
220+
* @return $this
221+
*/
222+
protected function validateField($fields)
223+
{
224+
if (empty($fields) || !isset($fields[0])) {
225+
throw new Exception('You must provide at least one field to generate the views!');
226+
}
227+
228+
return $this;
229+
}
230+
231+
/**
232+
* Gets a clean user inputs.
233+
*
234+
* @return CrestApps\CodeGenerator\Models\ResourceInput
235+
*/
236+
protected function getCommandInput()
237+
{
238+
$input = new ResourceInput(Config::getDefaultMapperFileName());
239+
//$prefix = $this->option('routes-prefix');
240+
//$input->prefix = ($prefix == 'model-name-as-plural') ? $this->makeTableName($input->modelName) : $prefix;
241+
//$input->languageFileName = trim($this->option('lang-file-name'));
242+
//$input->table = trim($this->option('table-name'));
243+
$input->viewsDirectory = trim($this->option('views-directory'));
244+
//$input->controllerName = trim($this->option('controller-name')) ?: Helpers::makeControllerName($input->modelName);
245+
$input->perPage = intval($this->option('models-per-page'));
246+
//$input->fields = $this->option('fields');
247+
//$input->fieldsFile = trim($this->option('fields-file')) ?: Helpers::makeJsonFileName($input->modelName);
248+
$input->formRequest = $this->option('with-form-request');
249+
$input->controllerDirectory = $this->option('controller-directory');
250+
$input->controllerExtends = $this->option('controller-extends') ?: null;
251+
$input->withoutMigration = $this->option('without-migration');
252+
$input->force = $this->option('force');
253+
$input->modelDirectory = $this->option('model-directory');
254+
//$input->fillable = $this->option('fillable');
255+
$input->primaryKey = $this->option('primary-key');
256+
//$input->relationships = $this->option('relationships');
257+
$input->withSoftDelete = $this->option('with-soft-delete');
258+
$input->withoutTimeStamps = $this->option('without-timestamps');
259+
//$input->migrationClass = $this->option('migration-class-name');
260+
$input->connectionName = $this->option('connection-name');
261+
//$input->indexes = $this->option('indexes');
262+
//$input->foreignKeys = $this->option('foreign-keys');
263+
$input->engineName = $this->option('engine-name');
264+
$input->template = $this->getTemplateName();
265+
$input->layoutName = $this->option('layout-name') ?: 'layouts.app';
266+
$input->tableExists = $this->option('table-exists');
267+
$input->translationFor = $this->option('translation-for');
268+
$input->withAuth = $this->option('with-auth');
269+
270+
return $input;
271+
}
272+
}

0 commit comments

Comments
 (0)