diff --git a/composer.json b/composer.json index 32d4a1b1b..611263f19 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ ], "require": { "php": "^7.2.5", - "illuminate/support": "^7.0", + "illuminate/support": "^7.0 || ^6.0", "laracasts/flash": "^3.1" }, "require-dev": { @@ -51,5 +51,5 @@ "\\InfyOm\\Generator\\InfyOmGeneratorServiceProvider" ] } - } + } } diff --git a/config/laravel_generator.php b/config/laravel_generator.php index 7c656c250..c958e378e 100755 --- a/config/laravel_generator.php +++ b/config/laravel_generator.php @@ -101,6 +101,7 @@ */ 'model_extend_class' => 'Eloquent', + 'model_default_date_format' => 'Y-m-d H:i:s.uP', /* |-------------------------------------------------------------------------- diff --git a/src/Commands/BaseCommand.php b/src/Commands/BaseCommand.php index ec59f6c05..51a7504b6 100755 --- a/src/Commands/BaseCommand.php +++ b/src/Commands/BaseCommand.php @@ -293,6 +293,7 @@ public function getOptions() ['paginate', null, InputOption::VALUE_REQUIRED, 'Pagination for index.blade.php'], ['skip', null, InputOption::VALUE_REQUIRED, 'Skip Specific Items to Generate (migration,model,controllers,api_controller,scaffold_controller,repository,requests,api_requests,scaffold_requests,routes,api_routes,scaffold_routes,views,tests,menu,dump-autoload)'], ['datatables', null, InputOption::VALUE_REQUIRED, 'Override datatables settings'], + ['datagrid', null, InputOption::VALUE_NONE, 'Use datagrid for in table.blade.php'], ['views', null, InputOption::VALUE_REQUIRED, 'Specify only the views you want generated: index,create,edit,show'], ['relations', null, InputOption::VALUE_NONE, 'Specify if you want to pass relationships for fields'], ['softDelete', null, InputOption::VALUE_NONE, 'Soft Delete Option'], @@ -302,6 +303,7 @@ public function getOptions() ['localized', null, InputOption::VALUE_NONE, 'Localize files.'], ['repositoryPattern', null, InputOption::VALUE_REQUIRED, 'Repository Pattern'], ['connection', null, InputOption::VALUE_REQUIRED, 'Specify connection name'], + ['moduleName', null, InputOption::VALUE_REQUIRED, 'Generate files to this module & namespace (eg. Admin)'], ]; } diff --git a/src/Commands/RollbackGeneratorCommand.php b/src/Commands/RollbackGeneratorCommand.php index 11a462831..04768d7c5 100755 --- a/src/Commands/RollbackGeneratorCommand.php +++ b/src/Commands/RollbackGeneratorCommand.php @@ -75,7 +75,7 @@ public function handle() $this->commandData = new CommandData($this, $this->argument('type')); $this->commandData->config->mName = $this->commandData->modelName = $this->argument('model'); - $this->commandData->config->init($this->commandData, ['tableName', 'prefix', 'plural', 'views']); + $this->commandData->config->init($this->commandData, ['tableName', 'prefix', 'plural', 'views', 'moduleName']); $views = $this->commandData->getOption('views'); if (!empty($views)) { @@ -151,6 +151,7 @@ public function getOptions() ['prefix', null, InputOption::VALUE_REQUIRED, 'Prefix for all files'], ['plural', null, InputOption::VALUE_REQUIRED, 'Plural Model name'], ['views', null, InputOption::VALUE_REQUIRED, 'Views to rollback'], + ['moduleName', null, InputOption::VALUE_REQUIRED, 'Generate files to this module & namespace (eg. Admin)'], ]; } diff --git a/src/Common/CommandData.php b/src/Common/CommandData.php index 336e94858..fbbe7b485 100755 --- a/src/Common/CommandData.php +++ b/src/Common/CommandData.php @@ -73,8 +73,10 @@ public function __construct(Command $commandObj, $commandType, TemplatesManager $this->commandType = $commandType; $this->fieldNamesMapping = [ - '$FIELD_NAME_TITLE$' => 'fieldTitle', - '$FIELD_NAME$' => 'name', + '$FIELD_NAME_TITLE$' => 'fieldTitle', + '$FIELD_NAME$' => 'name', + '$FIELD_DOT_NOTATION_NAME$' => 'dotNotationName', + '$FIELD_IS_FILLABLE$' => 'isFillable', ]; $this->config = new GeneratorConfig(); diff --git a/src/Common/GeneratorConfig.php b/src/Common/GeneratorConfig.php index 0ec957ae4..676e7c5ae 100755 --- a/src/Common/GeneratorConfig.php +++ b/src/Common/GeneratorConfig.php @@ -84,6 +84,7 @@ class GeneratorConfig 'paginate', 'skip', 'datatables', + 'datagrid', 'views', 'relations', 'plural', @@ -94,6 +95,7 @@ class GeneratorConfig 'repositoryPattern', 'localized', 'connection', + 'moduleName', ]; public $tableName; @@ -391,6 +393,61 @@ public function prepareOptions(CommandData &$commandData) $this->addOns['datatables'] = false; } } + + if (!empty($this->options['datagrid'])) { + if (isset($this->options['datatables']) && $this->options['datatables'] === 'true' && $this->options['datatables']) { + $commandData->commandError('Can\'t use datagrid and datables at the same time.'); + exit; + } + } + if (!empty($this->options['moduleName'])) { + if (!file_exists(config_path('modules.php'))) { + $commandData->commandError('Can\'t use modules since config doesn\'t exist in '.config_path('modules.php').'.'); + exit; + } + // change folder locations + $this->modules_path = config('modules.paths.modules', base_path('Modules')).'/'.$this->options['moduleName']; + $config_paths = config('infyom.laravel_generator.path'); + $new_config_paths = []; + foreach($config_paths as $key => $path) { + if (preg_match('/migrations/', $path)) + $path = str_replace('migrations', 'Migrations', $path); + if (strpos($path, app_path()) === 0) { + $new_config_paths[$key] = str_replace(app_path(), $this->modules_path, $path); + } else { + $new_config_paths[$key] = str_replace(base_path(), $this->modules_path, $path); + } + $new_config_paths[$key][strlen($this->modules_path)+1] = strtoupper($new_config_paths[$key][strlen($this->modules_path)+1]); + } + config(['infyom.laravel_generator.path' => $new_config_paths]); + + // change namespace + $this->module_namespace = config('modules.namespace', 'Modules').'\\'.$this->options['moduleName'].'\\'; + $config_namespaces = config('infyom.laravel_generator.namespace'); + $new_config_namespaces = []; + foreach($config_namespaces as $key => $namespace) + { + if (strpos($namespace, 'App\\') === 0) + $namespace = str_replace('App\\', '', $namespace); + $new_config_namespaces[$key] = $this->module_namespace.$namespace; + } + config(['infyom.laravel_generator.namespace' => $new_config_namespaces]); + + // change prefix + $viewPrefix = isset($this->prefixes['view'])?$this->prefixes['view']:null; + config(['infyom.laravel_generator.prefixes.view' => strtolower($this->options['moduleName']).'::']); + $this->prefixes['view'] = config('infyom.laravel_generator.prefixes.view'); + if ($this->getOption('plural')) { + $this->mPlural = $this->getOption('plural'); + } else { + $this->mPlural = Str::plural($this->mName); + } + $this->mSnakePlural = Str::snake($this->mPlural); + $this->pathViews = config( + 'infyom.laravel_generator.path.views', + base_path('resources/views/') + ).$viewPrefix.$this->mSnakePlural.'/'; + } } public function preparePrefixes() diff --git a/src/Common/GeneratorField.php b/src/Common/GeneratorField.php index 2636a4df1..4fae4cb42 100644 --- a/src/Common/GeneratorField.php +++ b/src/Common/GeneratorField.php @@ -8,6 +8,7 @@ class GeneratorField { /** @var string */ public $name; + public $dotNotationname; public $dbInput; public $htmlInput; public $htmlType; @@ -171,6 +172,10 @@ public function __get($key) return Str::title(str_replace('_', ' ', $this->name)); } + if ($key == 'dotNotationName') { + return str_replace('->', '.', $this->name); + } + return $this->$key; } } diff --git a/src/Generators/RepositoryGenerator.php b/src/Generators/RepositoryGenerator.php index 0dbb8f816..0b413fb66 100755 --- a/src/Generators/RepositoryGenerator.php +++ b/src/Generators/RepositoryGenerator.php @@ -33,7 +33,11 @@ public function generate() foreach ($this->commandData->fields as $field) { if ($field->isSearchable) { - $searchables[] = "'".$field->name."'"; + $condition = ''; + if ($field->fieldType == 'text') { + $condition = " => 'ilike'"; + } + $searchables[] = "'".$field->name."'".$condition; } } diff --git a/src/Generators/Scaffold/ControllerGenerator.php b/src/Generators/Scaffold/ControllerGenerator.php index b25e1c888..8e3fede64 100755 --- a/src/Generators/Scaffold/ControllerGenerator.php +++ b/src/Generators/Scaffold/ControllerGenerator.php @@ -63,6 +63,18 @@ public function generate() } else { $templateData = str_replace('$RENDER_TYPE$', 'all()', $templateData); } + + if ($this->commandData->getOption('datagrid')) { + $use_datagrid_path = get_template('scaffold.controller.datagrid_use_path', 'laravel-generator'); + $use_datagrid_trait = get_template('scaffold.controller.datagrid_use_trait', 'laravel-generator'); + $call_datagrid = get_template('scaffold.controller.datagrid_call_filter', 'laravel-generator'); + + $templateData = str_replace('$USE_DATAGRID_PATH$', $use_datagrid_path, $templateData); + $templateData = str_replace('$USE_DATAGRID_TRAIT$', $use_datagrid_trait, $templateData); + } else { + $templateData = str_replace('$USE_DATAGRID_PATH$', $use_datagrid, $templateData); + $templateData = str_replace('$USE_DATAGRID_TRAIT$', '', $templateData); + } } $templateData = fill_template($this->commandData->dynamicVars, $templateData); diff --git a/src/Generators/Scaffold/ViewGenerator.php b/src/Generators/Scaffold/ViewGenerator.php index e00bacc8d..257706035 100755 --- a/src/Generators/Scaffold/ViewGenerator.php +++ b/src/Generators/Scaffold/ViewGenerator.php @@ -86,6 +86,8 @@ private function generateTable() if ($this->commandData->getAddOn('datatables')) { $templateData = $this->generateDataTableBody(); $this->generateDataTableActions(); + } elseif ($this->commandData->getOption('datagrid')) { + $templateData = $this->generateDatagridBladeTableBody(); } else { $templateData = $this->generateBladeTableBody(); } @@ -119,6 +121,41 @@ private function generateDataTableActions() $this->commandData->commandInfo('datatables_actions.blade.php created'); } + private function generateDatagridBladeTableBody() + { + $templateData = get_template('scaffold.views.blade_datagrid_table_body', $this->templateType); + + $templateData = fill_template($this->commandData->dynamicVars, $templateData); + + $templateData = str_replace('$SET_COLUMNS$', $this->generateDatagridSetColumnFields(), $templateData); + + return $templateData; + } + + private function generateDatagridSetColumnFields() + { + $setColumnsTemplate = get_template('scaffold.views.datagrid_table_set_columns', $this->templateType); + + $setColumns = []; + + foreach ($this->commandData->fields as $field) { + if (!$field->inIndex) { + continue; + } + + $field->isFillable = $field->isFillable ? 'true' : 'false'; + + $setColumns[] = $fieldTemplate = fill_template_with_field_data( + $this->commandData->dynamicVars, + $this->commandData->fieldNamesMapping, + $setColumnsTemplate, + $field + ); + } + + return implode(infy_nl_tab(0, 1), $setColumns); + } + private function generateBladeTableBody() { $templateName = 'blade_table_body'; diff --git a/src/Utils/DatagridSortableAndFilterableUtil.php b/src/Utils/DatagridSortableAndFilterableUtil.php new file mode 100644 index 000000000..fb1906715 --- /dev/null +++ b/src/Utils/DatagridSortableAndFilterableUtil.php @@ -0,0 +1,54 @@ + $value) { + if ($value == '') { + continue; + } + $searches[] = $field.':'.$value; + } + $request['search'] = implode(';', $searches); + $request['searchUseAnd'] = 1; + } + + /** + * Set default order by and direction. + * + * @param Request $request + */ + private function setDefaultOrder(&$request, $by, $dir = 'ASC') + { + if (!isset($request['f']['order_by']) || + isset($request['f']['order_by']) && $request['f']['order_by'] == '') { + $request['orderBy'] = $by; + $request['sortedBy'] = $dir; + } + } +} diff --git a/templates/base_repository.stub b/templates/base_repository.stub index cc17ad673..12c9e5f71 100644 --- a/templates/base_repository.stub +++ b/templates/base_repository.stub @@ -81,20 +81,31 @@ abstract class BaseRepository * @param array $search * @param int|null $skip * @param int|null $limit + * @param array $sort with [['field_name' => 'asc|desc'], ...] * @return \Illuminate\Database\Eloquent\Builder */ - public function allQuery($search = [], $skip = null, $limit = null) + public function allQuery($search = [], $skip = null, $limit = null, $sort = []) { $query = $this->model->newQuery(); if (count($search)) { foreach($search as $key => $value) { if (in_array($key, $this->getFieldsSearchable())) { - $query->where($key, $value); + $values = array_unique(array_filter(array_map('trim', explode(" ", $value)))); + foreach($values as $value) + $query->where($key, 'ilike', '%'.$value.'%'); } } } + if (count($sort)) + { + foreach($sort as $field => $sort) + { + $query->orderBy($field, $sort); + } + } + if (!is_null($skip)) { $query->skip($skip); } @@ -113,12 +124,13 @@ abstract class BaseRepository * @param int|null $skip * @param int|null $limit * @param array $columns + * @param array $sort with [['field_name' => 'asc|desc'], ...] * * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection */ - public function all($search = [], $skip = null, $limit = null, $columns = ['*']) + public function all($search = [], $skip = null, $limit = null, $columns = ['*'], $sort = []) { - $query = $this->allQuery($search, $skip, $limit); + $query = $this->allQuery($search, $skip, $limit, $sort); return $query->get($columns); } diff --git a/templates/scaffold/controller/datagrid_use_path.stub b/templates/scaffold/controller/datagrid_use_path.stub new file mode 100644 index 000000000..85a0e697d --- /dev/null +++ b/templates/scaffold/controller/datagrid_use_path.stub @@ -0,0 +1 @@ +use InfyOm\Generator\Utils\DatagridSortableAndFilterableUtil as DatagridSortableAndFilterable; diff --git a/templates/scaffold/controller/datagrid_use_trait.stub b/templates/scaffold/controller/datagrid_use_trait.stub new file mode 100644 index 000000000..8dbe04f22 --- /dev/null +++ b/templates/scaffold/controller/datagrid_use_trait.stub @@ -0,0 +1 @@ +use DatagridSortableAndFilterable;