Initial commit

This commit is contained in:
omair saleh
2020-08-12 04:16:41 +08:00
commit 57bd2be885
476 changed files with 41783 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
+48
View File
@@ -0,0 +1,48 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
JWT_SECRET=
+5
View File
@@ -0,0 +1,5 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
CHANGELOG.md export-ignore
+13
View File
@@ -0,0 +1,13 @@
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
**/.idea/
.env
.env.backup
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
+13
View File
@@ -0,0 +1,13 @@
php:
preset: laravel
disabled:
- unused_use
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true
+79
View File
@@ -0,0 +1,79 @@
<p align="center"><img src="https://res.cloudinary.com/dtfbvvkyp/image/upload/v1566331377/laravel-logolockup-cmyk-red.svg" width="400"></p>
<p align="center">
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/d/total.svg" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/v/stable.svg" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/license.svg" alt="License"></a>
</p>
## About Laravel
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
Laravel is accessible, powerful, and provides tools required for large, robust applications.
## Learning Laravel
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
## Laravel Sponsors
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Cubet Techno Labs](https://cubettech.com)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[Many](https://www.many.co.uk)**
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
- **[DevSquad](https://devsquad.com)**
- [UserInsights](https://userinsights.com)
- [Fragrantica](https://www.fragrantica.com)
- [SOFTonSOFA](https://softonsofa.com/)
- [User10](https://user10.com)
- [Soumettre.fr](https://soumettre.fr/)
- [CodeBrisk](https://codebrisk.com)
- [1Forge](https://1forge.com)
- [TECPRESSO](https://tecpresso.co.jp/)
- [Runtime Converter](http://runtimeconverter.com/)
- [WebL'Agence](https://weblagence.com/)
- [Invoice Ninja](https://www.invoiceninja.com)
- [iMi digital](https://www.imi-digital.de/)
- [Earthlink](https://www.earthlink.ro/)
- [Steadfast Collective](https://steadfastcollective.com/)
- [We Are The Robots Inc.](https://watr.mx/)
- [Understand.io](https://www.understand.io/)
- [Abdel Elrafa](https://abdelelrafa.com)
- [Hyper Host](https://hyper.host)
- [Appoly](https://www.appoly.co.uk)
- [OP.GG](https://op.gg)
- [云软科技](http://www.yunruan.ltd/)
## Contributing
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
@@ -0,0 +1,277 @@
<?php
namespace App\Classes\CodeGenerator\Commands;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\FactoryGenerator;
use App\Classes\CodeGenerator\Generators\Micros\DataTransferObjectGenerator;
use App\Classes\CodeGenerator\Generators\Micros\ResourceGenerator;
use App\Classes\CodeGenerator\Generators\Micros\RulesGenerator;
use App\Classes\CodeGenerator\Generators\Micros\ServicesGenerator;
use App\Classes\CodeGenerator\Generators\Micros\ValidatorsGenerator;
use App\Classes\CodeGenerator\Generators\MigrationGenerator;
use App\Classes\CodeGenerator\Generators\ModelGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\ControllersGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\ControllerLogicGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\RoutesGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\ViewsGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\VueGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\WebRouteGenerator;
use App\Classes\CodeGenerator\Generators\SeederGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Console\Command;
use Illuminate\Support\Composer;
use Illuminate\Support\Str;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class BaseCommand extends Command
{
/**
* The command Data.
*
* @var CommandData
*/
public $commandData;
/**
* @var Composer
*/
public $composer;
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
$this->composer = app()['composer'];
}
public function handle()
{
$this->commandData->modelName = $this->argument('model');
$this->commandData->initCommandData();
$this->commandData->getFields();
}
public function generateCommonItems()
{
if (!$this->commandData->getOption('fromTable')) {
$migrationGenerator = new MigrationGenerator($this->commandData);
$migrationGenerator->generate();
}
$modelGenerator = new ModelGenerator($this->commandData);
$modelGenerator->generate();
$factoryGenerator = new FactoryGenerator($this->commandData);
$factoryGenerator->generate();
$seederGenerator = new SeederGenerator($this->commandData);
$seederGenerator->generate();
if($this->confirm("\nDo you want to include this seeder to the main seeder? [y|N]", false)){
$seederGenerator->updateMainSeeder();
}
}
public function generateMicroItems()
{
$dataTransferObjectGenerator = new DataTransferObjectGenerator($this->commandData);
$dataTransferObjectGenerator->generate();
$serviceGenerator = new ServicesGenerator($this->commandData);
$serviceGenerator->generate();
}
public function generateScaffoldItems()
{
$resourceGenerator = new ResourceGenerator($this->commandData);
$resourceGenerator->generate();
$validatorsGenerator = new ValidatorsGenerator($this->commandData);
$validatorsGenerator->generate();
$rulesGenerator = new RulesGenerator($this->commandData);
$rulesGenerator->generate();
if (!$this->isSkip('controllers') and !$this->isSkip('scaffold_controller')) {
$controllerLogicGenerator = new ControllerLogicGenerator($this->commandData);
$controllerLogicGenerator->generate();
$controllerGenerator = new ControllersGenerator($this->commandData);
$controllerGenerator->generate();
}
$routesGenerator = new RoutesGenerator($this->commandData);
$routesGenerator->generate();
// $webRouteGenerator = new WebRouteGenerator($this->commandData);
// $webRouteGenerator->generate();
}
public function generateViews(){
$viewGenerator = new ViewsGenerator($this->commandData);
$viewGenerator->generate();
$vueGenerator = new vueGenerator($this->commandData);
$vueGenerator->generate();
if($this->confirm("\nDo you want to compile your vue files? [y|N]", false)){
shell_exec('yarn dev');
}
}
public function performPostActions($runMigration = false)
{
if ($this->commandData->getOption('save')) {
$this->saveSchemaFile();
}
if ($runMigration) {
if ($this->commandData->getOption('forceMigrate')) {
$this->runMigration();
} elseif (!$this->commandData->getOption('fromTable') and !$this->isSkip('migration')) {
$requestFromConsole = (php_sapi_name() == 'cli') ? true : false;
if ($this->commandData->getOption('jsonFromGUI') && $requestFromConsole) {
$this->runMigration();
} elseif ($requestFromConsole && $this->confirm("\nDo you want to migrate database? [y|N]", false)) {
$this->runMigration();
}
}
}
if (!$this->isSkip('dump-autoload')) {
$this->info('Generating autoload files');
$this->composer->dumpOptimized();
}
}
public function runMigration()
{
$migrationPath = database_path('migrations/');
$path = Str::after($migrationPath, base_path()); // get path after base_path
$this->call('migrate', ['--path' => $path, '--force' => true]);
return true;
}
public function isSkip($skip)
{
if ($this->commandData->getOption('skip')) {
return in_array($skip, (array) $this->commandData->getOption('skip'));
}
return false;
}
public function performPostActionsWithMigration()
{
$this->performPostActions(true);
}
private function saveSchemaFile()
{
$fileFields = [];
foreach ($this->commandData->fields as $field) {
$fileFields[] = [
'name' => $field->name,
'dbType' => $field->dbInput,
'htmlType' => $field->htmlInput,
'validations' => $field->validations,
'searchable' => $field->isSearchable,
'fillable' => $field->isFillable,
'primary' => $field->isPrimary,
'inForm' => $field->inForm,
'inIndex' => $field->inIndex,
'inView' => $field->inView,
];
}
foreach ($this->commandData->relations as $relation) {
$fileFields[] = [
'type' => 'relation',
'relation' => $relation->type.','.implode(',', $relation->inputs),
];
}
$path = app_path('Classes/CodeGenerator/Schemas/');
$fileName = $this->commandData->modelName.'.json';
if (file_exists($path.$fileName) && !$this->confirmOverwrite($fileName)) {
return;
}
FileUtil::createFile($path, $fileName, json_encode($fileFields, JSON_PRETTY_PRINT));
$this->commandData->commandComment("\nSchema File saved: ");
$this->commandData->commandInfo($fileName);
}
/**
* @param $fileName
* @param string $prompt
*
* @return bool
*/
protected function confirmOverwrite($fileName, $prompt = '')
{
$prompt = (empty($prompt))
? $fileName.' already exists. Do you want to overwrite it? [y|N]'
: $prompt;
return $this->confirm($prompt, false);
}
/**
* Get the console command options.
*
* @return array
*/
public function getOptions()
{
return [
['fieldsFile', null, InputOption::VALUE_REQUIRED, 'Fields input as json file'],
['jsonFromGUI', null, InputOption::VALUE_REQUIRED, 'Direct Json string while using GUI interface'],
['plural', null, InputOption::VALUE_REQUIRED, 'Plural Model name'],
['tableName', null, InputOption::VALUE_REQUIRED, 'Table Name'],
['fromTable', null, InputOption::VALUE_NONE, 'Generate from existing table'],
['ignoreFields', null, InputOption::VALUE_REQUIRED, 'Ignore fields while generating from table'],
['save', null, InputOption::VALUE_NONE, 'Save model schema to file'],
['primary', null, InputOption::VALUE_REQUIRED, 'Custom primary key'],
['prefix', null, InputOption::VALUE_REQUIRED, 'Prefix for all files'],
['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'],
['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'],
['forceMigrate', null, InputOption::VALUE_NONE, 'Specify if you want to run migration or not'],
['factory', null, InputOption::VALUE_NONE, 'To generate factory'],
['seeder', null, InputOption::VALUE_NONE, 'To generate seeder'],
['localized', null, InputOption::VALUE_NONE, 'Localize files.'],
['repositoryPattern', null, InputOption::VALUE_REQUIRED, 'Repository Pattern'],
['connection', null, InputOption::VALUE_REQUIRED, 'Specify connection name'],
];
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['model', InputArgument::REQUIRED, 'Singular Model name'],
];
}
}
@@ -0,0 +1,187 @@
<?php
namespace App\Classes\CodeGenerator\Commands;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\FactoryGenerator;
use App\Classes\CodeGenerator\Generators\Micros\DataTransferObjectGenerator;
use App\Classes\CodeGenerator\Generators\Micros\ResourceGenerator;
use App\Classes\CodeGenerator\Generators\Micros\RulesGenerator;
use App\Classes\CodeGenerator\Generators\Micros\ServicesGenerator;
use App\Classes\CodeGenerator\Generators\Micros\ValidatorsGenerator;
use App\Classes\CodeGenerator\Generators\MigrationGenerator;
use App\Classes\CodeGenerator\Generators\ModelGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\ControllersGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\ControllerLogicGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\RoutesGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\ViewsGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\VueGenerator;
use App\Classes\CodeGenerator\Generators\Scaffold\WebRouteGenerator;
use App\Classes\CodeGenerator\Generators\SeederGenerator;
use Illuminate\Console\Command;
use Illuminate\Support\Composer;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class RollbackGeneratorCommand extends Command
{
/**
* The command Data.
*
* @var CommandData
*/
public $commandData;
/**
* The console command name.
*
* @var string
*/
protected $name = 'code:rollback';
/**
* The console command description.
*
* @var string
*/
protected $description = 'rollback all files required for CRUD operations';
/**
* @var Composer
*/
public $composer;
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
$this->composer = app()['composer'];
}
/**
* Execute the command.
*
* @return void
*/
public function handle()
{
if (!in_array($this->argument('type'), [
'scaffold', 'micro'
])) {
$this->error('invalid rollback type');
}
$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->rollbackCommon();
$this->rollbackMicros();
if($this->commandData->commandType === 'scaffold'){
$this->rollbackScaffold();
$this->rollbackViews();
}
$this->info('Generating autoload files');
$this->composer->dumpOptimized();
}
private function rollbackCommon(){
$migrationGenerator = new MigrationGenerator($this->commandData);
$migrationGenerator->rollback();
$modelGenerator = new ModelGenerator($this->commandData);
$modelGenerator->rollback();
$factoryGenerator = new FactoryGenerator($this->commandData);
$factoryGenerator->rollback();
$seederGenerator = new SeederGenerator($this->commandData);
$seederGenerator->rollback();
}
private function rollbackMicros(){
$dataTransferObjectGenerator = new DataTransferObjectGenerator($this->commandData);
$dataTransferObjectGenerator->rollback();
$serviceGenerator = new ServicesGenerator($this->commandData);
$serviceGenerator->rollback();
}
private function rollbackScaffold(){
$resourceGenerator = new ResourceGenerator($this->commandData);
$resourceGenerator->rollback();
$validatorsGenerator = new ValidatorsGenerator($this->commandData);
$validatorsGenerator->rollback();
$rulesGenerator = new RulesGenerator($this->commandData);
$rulesGenerator->rollback();
File::deleteDirectories(app_path('Classes/Modules/'. str::pluralStudly($this->commandData->modelName).'/Standards/'));
$routesGenerator = new RoutesGenerator($this->commandData);
$routesGenerator->rollback();
$webRouteGenerator = new WebRouteGenerator($this->commandData);
$webRouteGenerator->rollback();
$controllerGenerator = new ControllersGenerator($this->commandData);
$controllerGenerator->rollback();
$controllerLogicGenerator = new ControllerLogicGenerator($this->commandData);
$controllerLogicGenerator->rollback();
File::deleteDirectories(app_path('Classes/Modules/'. str::pluralStudly($this->commandData->modelName).'/'));
}
private function rollbackViews(){
$viewGenerator = new ViewsGenerator($this->commandData);
$viewGenerator->rollback();
$vueGenerator = new vueGenerator($this->commandData);
$vueGenerator->rollback();
}
/**
* Get the console command options.
*
* @return array
*/
public function getOptions()
{
return [
['tableName', null, InputOption::VALUE_REQUIRED, 'Table Name'],
['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'],
];
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return [
['model', InputArgument::REQUIRED, 'Singular Model name'],
['type', InputArgument::REQUIRED, 'Rollback type: (micro / scaffold )'],
];
}
}
@@ -0,0 +1,91 @@
<?php
namespace App\Classes\CodeGenerator\Commands\Scaffold;
use App\Classes\CodeGenerator\Commands\BaseCommand;
use App\Classes\CodeGenerator\Common\CommandData;
class MicroGeneratorCommand extends BaseCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'code:micro';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate all files required for CRUD operations';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
$this->commandData = new CommandData($this, 'micro');
}
/**
* Execute the command.
*
* @return void
*/
public function handle()
{
parent::handle();
if ($this->checkIsThereAnyDataToGenerate()) {
$this->generateCommonItems();
$this->generateMicroItems();
$this->performPostActionsWithMigration();
} else {
$this->commandData->commandInfo('There are not enough input fields for scaffold generation.');
}
}
/**
* Get the console command options.
*
* @return array
*/
public function getOptions()
{
return array_merge(parent::getOptions(), []);
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array_merge(parent::getArguments(), []);
}
/**
* Check if there is anything to generate.
*
* @return bool
*/
protected function checkIsThereAnyDataToGenerate()
{
if (count($this->commandData->fields) > 1) {
return true;
}
}
}
@@ -0,0 +1,96 @@
<?php
namespace App\Classes\CodeGenerator\Commands\Scaffold;
use App\Classes\CodeGenerator\Commands\BaseCommand;
use App\Classes\CodeGenerator\Common\CommandData;
class ScaffoldGeneratorCommand extends BaseCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'code:scaffold';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate all files required for CRUD operations';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
$this->commandData = new CommandData($this, 'scaffold');
}
/**
* Execute the command.
*
* @return void
*/
public function handle()
{
parent::handle();
if ($this->checkIsThereAnyDataToGenerate()) {
$this->generateCommonItems();
$this->generateMicroItems();
$this->generateScaffoldItems();
// $this->generateViews();
$this->performPostActionsWithMigration();
} else {
$this->commandData->commandInfo('There are not enough input fields for scaffold generation.');
}
}
/**
* Get the console command options.
*
* @return array
*/
public function getOptions()
{
return array_merge(parent::getOptions(), []);
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array_merge(parent::getArguments(), []);
}
/**
* Check if there is anything to generate.
*
* @return bool
*/
protected function checkIsThereAnyDataToGenerate()
{
if (count($this->commandData->fields) > 1) {
return true;
}
}
}
@@ -0,0 +1,294 @@
<?php
namespace App\Classes\CodeGenerator\Common;
use App\Classes\CodeGenerator\Utils\GeneratorFieldsInputUtil;
use App\Classes\CodeGenerator\Utils\TableFieldsGenerator;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
class CommandData
{
/** @var string */
public $modelName;
public $commandType;
/** @var GeneratorConfig */
public $config;
/** @var GeneratorField[] */
public $fields = [];
/** @var GeneratorFieldRelation[] */
public $relations = [];
/** @var Command */
public $commandObj;
/** @var TemplatesManager */
private $templateManager;
/** @var array */
public $dynamicVars = [];
public $fieldNamesMapping = [];
/** @var CommandData */
protected static $instance = null;
public static function getInstance()
{
return self::$instance;
}
public function getTemplatesManager()
{
return $this->templateManager;
}
/**
* @param Command $commandObj
* @param $commandType
* @param TemplatesManager $templatesManager
*/
public function __construct(Command $commandObj, $commandType, TemplatesManager $templatesManager = null)
{
$this->commandObj = $commandObj;
if (is_null($templatesManager)) {
$this->templateManager = app(TemplatesManager::class);
} else {
$this->templateManager = $templatesManager;
}
$this->commandType = $commandType;
$this->fieldNamesMapping = [
'$FIELD_NAME_TITLE$' => 'fieldTitle',
'$FIELD_NAME$' => 'name',
];
$this->config = new GeneratorConfig();
}
public function commandError($error)
{
$this->commandObj->error($error);
}
public function commandComment($message)
{
$this->commandObj->comment($message);
}
public function commandWarn($warning)
{
$this->commandObj->warn($warning);
}
public function commandInfo($message)
{
$this->commandObj->info($message);
}
public function initCommandData()
{
$this->config->init($this);
}
public function getOption($option)
{
return $this->config->getOption($option);
}
public function getAddOn($option)
{
return $this->config->getAddOn($option);
}
public function setOption($option, $value)
{
$this->config->setOption($option, $value);
}
public function addDynamicVariable($name, $val)
{
$this->dynamicVars[$name] = $val;
}
public function getFields()
{
$this->fields = [];
if ($this->getOption('fieldsFile') or $this->getOption('jsonFromGUI')) {
$this->getInputFromFileOrJson();
} elseif ($this->getOption('fromTable')) {
$this->getInputFromTable();
} else {
$this->getInputFromConsole();
}
}
private function getInputFromConsole()
{
$this->commandInfo('Specify fields for the model (skip id & timestamp fields, we will add it automatically)');
$this->commandInfo('Read docs carefully to specify field inputs)');
$this->commandInfo('Enter "exit" to finish');
$this->addPrimaryKey();
while (true) {
$fieldInputStr = $this->commandObj->ask('Field: (name db_type html_type options)', '');
if (empty($fieldInputStr) || $fieldInputStr == false || $fieldInputStr == 'exit') {
break;
}
if (!GeneratorFieldsInputUtil::validateFieldInput($fieldInputStr)) {
$this->commandError('Invalid Input. Try again');
continue;
}
$validations = $this->commandObj->ask('Enter validations: ', false);
$validations = ($validations == false) ? '' : $validations;
if ($this->getOption('relations')) {
$relation = $this->commandObj->ask('Enter relationship (Leave Blank to skip):', false);
} else {
$relation = '';
}
$this->fields[] = GeneratorFieldsInputUtil::processFieldInput(
$fieldInputStr,
$validations
);
if (!empty($relation)) {
$this->relations[] = GeneratorFieldRelation::parseRelation($relation);
}
}
$this->addTimestamps();
}
private function addPrimaryKey()
{
$primaryKey = new GeneratorField();
if ($this->getOption('primary')) {
$primaryKey->name = $this->getOption('primary');
} else {
$primaryKey->name = 'id';
}
$primaryKey->parseDBType('increments');
$primaryKey->parseOptions('s,f,p,if,ii');
$this->fields[] = $primaryKey;
}
private function addTimestamps()
{
$createdAt = new GeneratorField();
$createdAt->name = 'created_at';
$createdAt->parseDBType('timestamp');
$createdAt->parseOptions('s,f,if,ii');
$this->fields[] = $createdAt;
$updatedAt = new GeneratorField();
$updatedAt->name = 'updated_at';
$updatedAt->parseDBType('timestamp');
$updatedAt->parseOptions('s,f,if,ii');
$this->fields[] = $updatedAt;
}
private function getInputFromFileOrJson()
{
// fieldsFile option will get high priority than json option if both options are passed
try {
if ($this->getOption('fieldsFile')) {
$fieldsFileValue = $this->getOption('fieldsFile');
if (file_exists($fieldsFileValue)) {
$filePath = $fieldsFileValue;
} elseif (file_exists(base_path($fieldsFileValue))) {
$filePath = base_path($fieldsFileValue);
} else {
$schemaFileDirector = app_path('Classes/CodeGenerator/Schemas/');
$filePath = $schemaFileDirector.$fieldsFileValue;
}
if (!file_exists($filePath)) {
$this->commandError('Fields file not found');
exit;
}
$fileContents = file_get_contents($filePath);
$jsonData = json_decode($fileContents, true);
$this->fields = [];
foreach ($jsonData as $field) {
if (isset($field['type']) && $field['relation']) {
$this->relations[] = GeneratorFieldRelation::parseRelation($field['relation']);
} else {
$this->fields[] = GeneratorField::parseFieldFromFile($field);
if (isset($field['relation'])) {
$this->relations[] = GeneratorFieldRelation::parseRelation($field['relation']);
}
}
}
} else {
$fileContents = $this->getOption('jsonFromGUI');
$jsonData = json_decode($fileContents, true);
// override config options from jsonFromGUI
$this->config->overrideOptionsFromJsonFile($jsonData);
// Manage custom table name option
if (isset($jsonData['tableName'])) {
$tableName = $jsonData['tableName'];
$this->config->tableName = $tableName;
$this->addDynamicVariable('$TABLE_NAME$', $tableName);
$this->addDynamicVariable('$TABLE_NAME_TITLE$', Str::studly($tableName));
}
// Manage migrate option
if (isset($jsonData['migrate']) && $jsonData['migrate'] == false) {
$this->config->options['skip'][] = 'migration';
}
foreach ($jsonData['fields'] as $field) {
if (isset($field['type']) && $field['relation']) {
$this->relations[] = GeneratorFieldRelation::parseRelation($field['relation']);
} else {
$this->fields[] = GeneratorField::parseFieldFromFile($field);
if (isset($field['relation'])) {
$this->relations[] = GeneratorFieldRelation::parseRelation($field['relation']);
}
}
}
}
} catch (Exception $e) {
$this->commandError($e->getMessage());
exit;
}
}
private function getInputFromTable()
{
$tableName = $this->dynamicVars['$TABLE_NAME$'];
$ignoredFields = $this->getOption('ignoreFields');
if (!empty($ignoredFields)) {
$ignoredFields = explode(',', trim($ignoredFields));
} else {
$ignoredFields = [];
}
$tableFieldsGenerator = new TableFieldsGenerator($tableName, $ignoredFields, $this->config->connection);
$tableFieldsGenerator->prepareFieldsFromTable();
$tableFieldsGenerator->prepareRelations();
$this->fields = $tableFieldsGenerator->fields;
$this->relations = $tableFieldsGenerator->relations;
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Classes\CodeGenerator\Common;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use Illuminate\Support\Str;
class GenerateGetters extends BaseGenerator
{
public function generate($name, $type){
$functionPrefix = $type !== 'bool' ? 'get':'';
$template = $this->generatorHelpers->get_template('Micros.getter_function');
$template = str_replace('$FIELD_NAME$', str::camel($name), $template);
$template = str_replace('$DATA_TYPE$', $type, $template);
$template = str_replace('$FUNCTION_NAME$', $functionPrefix.str::studly($name), $template);
return $template;
}
}
@@ -0,0 +1,413 @@
<?php
namespace App\Classes\CodeGenerator\Common;
use Illuminate\Support\Str;
class GeneratorConfig
{
/* Namespace variables */
public $nsApp;
public $nsModel;
public $nsModelExtend;
public $nsController;
public $nsBaseController;
public $nsApiTests;
public $nsTestTraits;
public $nsTests;
/* Path variables */
public $pathModel;
public $pathFactory;
public $pathSeeder;
public $pathDatabaseSeeder;
public $pathApiRoutes;
public $pathApiTests;
public $pathController;
public $pathRoutes;
/* Model Names */
public $mName;
public $mPlural;
public $mCamel;
public $mCamelPlural;
public $mSnake;
public $mSnakePlural;
public $mDashed;
public $mDashedPlural;
public $mSlash;
public $mSlashPlural;
public $mHuman;
public $mHumanPlural;
public $connection = '';
/* Generator Options */
public $options;
/* Prefixes */
public $prefixes;
/** @var CommandData */
private $commandData;
/* Command Options */
public static $availableOptions = [
'fieldsFile',
'jsonFromGUI',
'tableName',
'fromTable',
'ignoreFields',
'save',
'primary',
'prefix',
'skip',
'views',
'relations',
'plural',
'softDelete',
'forceMigrate',
'factory',
'seeder',
];
public static $excludeFields = ['id', 'created_at', 'updated_at', 'deleted_at'];
public $tableName;
/** @var string */
protected $primaryName;
/* Generator AddOns */
public $addOns;
public function init(CommandData &$commandData, $options = null)
{
if (!empty($options)) {
self::$availableOptions = $options;
}
$this->mName = $commandData->modelName;
$this->prepareAddOns();
$this->prepareOptions($commandData);
$this->prepareModelNames();
$this->preparePrefixes();
$this->loadPaths();
$this->prepareTableName();
$this->preparePrimaryName();
$this->loadNamespaces($commandData);
$commandData = $this->loadDynamicVariables($commandData);
$this->commandData = &$commandData;
}
public function loadNamespaces(CommandData &$commandData)
{
$prefix = $this->prefixes['ns'];
if (!empty($prefix)) {
$prefix = '\\'.$prefix;
}
$this->nsApp = $commandData->commandObj->getLaravel()->getNamespace();
$this->nsApp = substr($this->nsApp, 0, strlen($this->nsApp) - 1);
$this->nsModel = 'App\Models';
$this->nsModelExtend = 'App\Models\AbstractModel';
$this->nsBaseController = 'App\Http\Controllers';
$this->nsController = 'App\Http\Controllers'.$prefix;
$this->nsApiTests = 'Tests\APIs';
$this->nsTests = 'Tests';
}
public function loadPaths()
{
$prefix = $this->prefixes['path'];
if (!empty($prefix)) {
$prefix .= '/';
}
$this->pathModel = app_path('Models/');
$this->pathApiRoutes = base_path('routes/api.php');
$this->pathApiTests = base_path('tests/APIs/');
$this->pathController = app_path('Http/Controllers/').$prefix;
$this->pathRoutes = base_path('routes/web.php');
$this->pathFactory = database_path('factories/');
$this->pathSeeder = database_path('seeds/');
$this->pathDatabaseSeeder = database_path('seeds/DatabaseSeeder.php');
}
public function loadDynamicVariables(CommandData &$commandData)
{
$commandData->addDynamicVariable('$NAMESPACE_APP$', $this->nsApp);
$commandData->addDynamicVariable('$NAMESPACE_MODEL$', $this->nsModel);
$commandData->addDynamicVariable('$NAMESPACE_MODEL_EXTEND$', $this->nsModelExtend);
$commandData->addDynamicVariable('$NAMESPACE_BASE_CONTROLLER$', $this->nsBaseController);
$commandData->addDynamicVariable('$NAMESPACE_CONTROLLER$', $this->nsController);
$commandData->addDynamicVariable('$NAMESPACE_API_TESTS$', $this->nsApiTests);
$commandData->addDynamicVariable('$NAMESPACE_TESTS$', $this->nsTests);
$commandData->addDynamicVariable('$TABLE_NAME$', $this->tableName);
$commandData->addDynamicVariable('$TABLE_NAME_TITLE$', Str::studly($this->tableName));
$commandData->addDynamicVariable('$PRIMARY_KEY_NAME$', $this->primaryName);
$commandData->addDynamicVariable('$MODEL_NAME$', $this->mName);
$commandData->addDynamicVariable('$MODEL_NAME_CAMEL$', $this->mCamel);
$commandData->addDynamicVariable('$MODEL_NAME_PLURAL$', $this->mPlural);
$commandData->addDynamicVariable('$MODEL_NAME_PLURAL_CAMEL$', $this->mCamelPlural);
$commandData->addDynamicVariable('$MODEL_NAME_SNAKE$', $this->mSnake);
$commandData->addDynamicVariable('$MODEL_NAME_PLURAL_SNAKE$', $this->mSnakePlural);
$commandData->addDynamicVariable('$MODEL_NAME_DASHED$', $this->mDashed);
$commandData->addDynamicVariable('$MODEL_NAME_PLURAL_DASHED$', $this->mDashedPlural);
$commandData->addDynamicVariable('$MODEL_NAME_SLASH$', $this->mSlash);
$commandData->addDynamicVariable('$MODEL_NAME_PLURAL_SLASH$', $this->mSlashPlural);
$commandData->addDynamicVariable('$MODEL_NAME_HUMAN$', $this->mHuman);
$commandData->addDynamicVariable('$MODEL_NAME_PLURAL_HUMAN$', $this->mHumanPlural);
$commandData->addDynamicVariable('$FILES$', '');
if (!empty($this->prefixes['route'])) {
$commandData->addDynamicVariable('$ROUTE_NAMED_PREFIX$', $this->prefixes['route'].'.');
$commandData->addDynamicVariable('$ROUTE_PREFIX$', str_replace('.', '/', $this->prefixes['route']).'/');
$commandData->addDynamicVariable('$RAW_ROUTE_PREFIX$', $this->prefixes['route']);
} else {
$commandData->addDynamicVariable('$ROUTE_PREFIX$', '');
$commandData->addDynamicVariable('$ROUTE_NAMED_PREFIX$', '');
}
if (!empty($this->prefixes['ns'])) {
$commandData->addDynamicVariable('$PATH_PREFIX$', $this->prefixes['ns'].'\\');
} else {
$commandData->addDynamicVariable('$PATH_PREFIX$', '');
}
if (!empty($this->prefixes['view'])) {
$commandData->addDynamicVariable('$VIEW_PREFIX$', str_replace('/', '.', $this->prefixes['view']).'.');
} else {
$commandData->addDynamicVariable('$VIEW_PREFIX$', '');
}
if (!empty($this->prefixes['public'])) {
$commandData->addDynamicVariable('$PUBLIC_PREFIX$', $this->prefixes['public']);
} else {
$commandData->addDynamicVariable('$PUBLIC_PREFIX$', '');
}
$commandData->addDynamicVariable(
'$API_PREFIX$',
'api'
);
$commandData->addDynamicVariable(
'$API_VERSION$',
'v1'
);
$commandData->addDynamicVariable('$SEARCHABLE$', '');
return $commandData;
}
public function prepareTableName()
{
if ($this->getOption('tableName')) {
$this->tableName = $this->getOption('tableName');
} else {
$this->tableName = $this->mSnakePlural;
}
}
public function preparePrimaryName()
{
if ($this->getOption('primary')) {
$this->primaryName = $this->getOption('primary');
} else {
$this->primaryName = 'id';
}
}
public function prepareModelNames()
{
if ($this->getOption('plural')) {
$this->mPlural = $this->getOption('plural');
} else {
$this->mPlural = Str::plural($this->mName);
}
$this->mCamel = Str::camel($this->mName);
$this->mCamelPlural = Str::camel($this->mPlural);
$this->mSnake = Str::snake($this->mName);
$this->mSnakePlural = Str::snake($this->mPlural);
$this->mDashed = str_replace('_', '-', Str::snake($this->mSnake));
$this->mDashedPlural = str_replace('_', '-', Str::snake($this->mSnakePlural));
$this->mSlash = str_replace('_', '/', Str::snake($this->mSnake));
$this->mSlashPlural = str_replace('_', '/', Str::snake($this->mSnakePlural));
$this->mHuman = Str::title(str_replace('_', ' ', Str::snake($this->mSnake)));
$this->mHumanPlural = Str::title(str_replace('_', ' ', Str::snake($this->mSnakePlural)));
}
public function prepareOptions(CommandData &$commandData)
{
foreach (self::$availableOptions as $option) {
$this->options[$option] = $commandData->commandObj->option($option);
}
if (isset($options['fromTable']) and $this->options['fromTable']) {
if (!$this->options['tableName']) {
$commandData->commandError('tableName required with fromTable option.');
exit;
}
}
$this->options['softDelete'] = true;
if (!empty($this->options['skip'])) {
$this->options['skip'] = array_map('trim', explode(',', $this->options['skip']));
}
}
public function preparePrefixes()
{
$this->prefixes['route'] = explode('/', '');
$this->prefixes['path'] = explode('/', '');
$this->prefixes['view'] = explode('.', '');
$this->prefixes['public'] = explode('/', '');
if ($this->getOption('prefix')) {
$multiplePrefixes = explode('/', $this->getOption('prefix'));
$this->prefixes['route'] = array_merge($this->prefixes['route'], $multiplePrefixes);
$this->prefixes['path'] = array_merge($this->prefixes['path'], $multiplePrefixes);
$this->prefixes['view'] = array_merge($this->prefixes['view'], $multiplePrefixes);
$this->prefixes['public'] = array_merge($this->prefixes['public'], $multiplePrefixes);
}
$this->prefixes['route'] = array_diff($this->prefixes['route'], ['']);
$this->prefixes['path'] = array_diff($this->prefixes['path'], ['']);
$this->prefixes['view'] = array_diff($this->prefixes['view'], ['']);
$this->prefixes['public'] = array_diff($this->prefixes['public'], ['']);
$routePrefix = '';
foreach ($this->prefixes['route'] as $singlePrefix) {
$routePrefix .= Str::camel($singlePrefix).'.';
}
if (!empty($routePrefix)) {
$routePrefix = substr($routePrefix, 0, strlen($routePrefix) - 1);
}
$this->prefixes['route'] = $routePrefix;
$nsPrefix = '';
foreach ($this->prefixes['path'] as $singlePrefix) {
$nsPrefix .= Str::title($singlePrefix).'\\';
}
if (!empty($nsPrefix)) {
$nsPrefix = substr($nsPrefix, 0, strlen($nsPrefix) - 1);
}
$this->prefixes['ns'] = $nsPrefix;
$pathPrefix = '';
foreach ($this->prefixes['path'] as $singlePrefix) {
$pathPrefix .= Str::title($singlePrefix).'/';
}
if (!empty($pathPrefix)) {
$pathPrefix = substr($pathPrefix, 0, strlen($pathPrefix) - 1);
}
$this->prefixes['path'] = $pathPrefix;
$viewPrefix = '';
foreach ($this->prefixes['view'] as $singlePrefix) {
$viewPrefix .= Str::camel($singlePrefix).'/';
}
if (!empty($viewPrefix)) {
$viewPrefix = substr($viewPrefix, 0, strlen($viewPrefix) - 1);
}
$this->prefixes['view'] = $viewPrefix;
$publicPrefix = '';
foreach ($this->prefixes['public'] as $singlePrefix) {
$publicPrefix .= Str::camel($singlePrefix).'/';
}
if (!empty($publicPrefix)) {
$publicPrefix = substr($publicPrefix, 0, strlen($publicPrefix) - 1);
}
$this->prefixes['public'] = $publicPrefix;
}
public function overrideOptionsFromJsonFile($jsonData)
{
$options = self::$availableOptions;
foreach ($options as $option) {
if (isset($jsonData['options'][$option])) {
$this->setOption($option, $jsonData['options'][$option]);
}
}
// prepare prefixes than reload namespaces, paths and dynamic variables
if (!empty($this->getOption('prefix'))) {
$this->preparePrefixes();
$this->loadPaths();
$this->loadNamespaces($this->commandData);
$this->loadDynamicVariables($this->commandData);
}
}
public function getOption($option)
{
if (isset($this->options[$option])) {
return $this->options[$option];
}
return false;
}
public function getAddOn($addOn)
{
if (isset($this->addOns[$addOn])) {
return $this->addOns[$addOn];
}
return false;
}
public function setOption($option, $value)
{
$this->options[$option] = $value;
}
public function prepareAddOns()
{
$this->addOns['tests'] = false;
}
public function excludeFields()
{
return self::$excludeFields;
}
}
@@ -0,0 +1,173 @@
<?php
namespace App\Classes\CodeGenerator\Common;
use Illuminate\Support\Str;
class GeneratorField
{
/** @var string */
public $name;
public $dbInput;
public $htmlInput;
public $htmlType;
public $fieldType;
public $description;
/** @var array */
public $htmlValues;
/** @var string */
public $migrationText;
public $foreignKeyText;
public $validations;
/** @var bool */
public $isSearchable = true;
public $isFillable = true;
public $isPrimary = false;
public $inForm = true;
public $inIndex = true;
public $inView = true;
public $isNotNull = false;
/**
* @param Column $column
* @param $dbInput
*/
public function parseDBType($dbInput, $column = null)
{
$this->dbInput = $dbInput;
if (!is_null($column)) {
$this->dbInput = ($column->getLength() > 0) ? $this->dbInput.','.$column->getLength() : $this->dbInput;
$this->dbInput = (!$column->getNotnull()) ? $this->dbInput.':nullable' : $this->dbInput;
}
$this->prepareMigrationText();
}
public function parseHtmlInput($htmlInput)
{
$this->htmlInput = $htmlInput;
$this->htmlValues = [];
if (empty($htmlInput)) {
$this->htmlType = 'text';
return;
}
if (Str::contains($htmlInput, 'selectTable')) {
$inputsArr = explode(':', $htmlInput);
$this->htmlType = array_shift($inputsArr);
$this->htmlValues = $inputsArr;
return;
}
$inputsArr = explode(',', $htmlInput);
$this->htmlType = array_shift($inputsArr);
if (count($inputsArr) > 0) {
$this->htmlValues = $inputsArr;
}
}
public function parseOptions($options)
{
$options = strtolower($options);
$optionsArr = explode(',', $options);
if (in_array('s', $optionsArr)) {
$this->isSearchable = false;
}
if (in_array('p', $optionsArr)) {
// if field is primary key, then its not searchable, fillable, not in index & form
$this->isPrimary = true;
$this->isSearchable = false;
$this->isFillable = false;
$this->inForm = false;
$this->inIndex = false;
$this->inView = false;
}
if (in_array('f', $optionsArr)) {
$this->isFillable = false;
}
if (in_array('if', $optionsArr)) {
$this->inForm = false;
}
if (in_array('ii', $optionsArr)) {
$this->inIndex = false;
}
if (in_array('iv', $optionsArr)) {
$this->inView = false;
}
}
private function prepareMigrationText()
{
$inputsArr = explode(':', $this->dbInput);
$this->migrationText = '$table->';
$fieldTypeParams = explode(',', array_shift($inputsArr));
$this->fieldType = array_shift($fieldTypeParams);
$this->migrationText .= $this->fieldType."('".$this->name."'";
if ($this->fieldType == 'enum') {
$this->migrationText .= ', [';
foreach ($fieldTypeParams as $param) {
$this->migrationText .= "'".$param."',";
}
$this->migrationText = substr($this->migrationText, 0, strlen($this->migrationText) - 1);
$this->migrationText .= ']';
} else {
foreach ($fieldTypeParams as $param) {
$this->migrationText .= ', '.$param;
}
}
$this->migrationText .= ')';
foreach ($inputsArr as $input) {
$inputParams = explode(',', $input);
$functionName = array_shift($inputParams);
if ($functionName == 'foreign') {
$foreignTable = array_shift($inputParams);
$foreignField = array_shift($inputParams);
$this->foreignKeyText .= "\$table->foreign('".$this->name."')->references('".$foreignField."')->on('".$foreignTable."');";
} else {
$this->migrationText .= '->'.$functionName;
$this->migrationText .= '(';
$this->migrationText .= implode(', ', $inputParams);
$this->migrationText .= ')';
}
}
$this->migrationText .= ';';
}
public static function parseFieldFromFile($fieldInput)
{
$field = new self();
$field->name = $fieldInput['name'];
$field->parseDBType($fieldInput['dbType']);
$field->parseHtmlInput(isset($fieldInput['htmlType']) ? $fieldInput['htmlType'] : '');
$field->validations = isset($fieldInput['validations']) ? $fieldInput['validations'] : '';
$field->isSearchable = isset($fieldInput['searchable']) ? $fieldInput['searchable'] : false;
$field->isFillable = isset($fieldInput['fillable']) ? $fieldInput['fillable'] : true;
$field->isPrimary = isset($fieldInput['primary']) ? $fieldInput['primary'] : false;
$field->inForm = isset($fieldInput['inForm']) ? $fieldInput['inForm'] : true;
$field->inIndex = isset($fieldInput['inIndex']) ? $fieldInput['inIndex'] : true;
$field->inView = isset($fieldInput['inView']) ? $fieldInput['inView'] : true;
return $field;
}
public function __get($key)
{
if ($key == 'fieldTitle') {
return Str::title(str_replace('_', ' ', $this->name));
}
return $this->$key;
}
}
@@ -0,0 +1,103 @@
<?php
namespace App\Classes\CodeGenerator\Common;
use Illuminate\Support\Str;
class GeneratorFieldRelation
{
/** @var string */
public $type;
public $inputs;
public $relationName;
public static function parseRelation($relationInput)
{
$inputs = explode(',', $relationInput);
$relation = new self();
$relation->type = array_shift($inputs);
$modelWithRelation = explode(':', array_shift($inputs)); //e.g ModelName:relationName
if (count($modelWithRelation) == 2) {
$relation->relationName = $modelWithRelation[1];
unset($modelWithRelation[1]);
}
$relation->inputs = array_merge($modelWithRelation, $inputs);
return $relation;
}
public function getRelationFunctionText($relationText = null)
{
$singularRelation = (!empty($this->relationName)) ? $this->relationName : Str::camel($relationText);
$pluralRelation = (!empty($this->relationName)) ? $this->relationName : Str::camel(Str::plural($relationText));
switch ($this->type) {
case '1t1':
$functionName = $singularRelation;
$relation = 'hasOne';
$relationClass = 'HasOne';
break;
case '1tm':
$functionName = $pluralRelation;
$relation = 'hasMany';
$relationClass = 'HasMany';
break;
case 'mt1':
if (!empty($this->relationName)) {
$singularRelation = $this->relationName;
} elseif (isset($this->inputs[1])) {
$singularRelation = Str::camel(str_replace('_id', '', strtolower($this->inputs[1])));
}
$functionName = $singularRelation;
$relation = 'belongsTo';
$relationClass = 'BelongsTo';
break;
case 'mtm':
$functionName = $pluralRelation;
$relation = 'belongsToMany';
$relationClass = 'BelongsToMany';
break;
case 'hmt':
$functionName = $pluralRelation;
$relation = 'hasManyThrough';
$relationClass = 'HasManyThrough';
break;
default:
$functionName = '';
$relation = '';
$relationClass = '';
break;
}
if (!empty($functionName) and !empty($relation)) {
return $this->generateRelation($functionName, $relation, $relationClass);
}
return '';
}
private function generateRelation($functionName, $relation, $relationClass)
{
$inputs = $this->inputs;
$modelName = array_shift($inputs);
$template = (new GeneratorHelpers())->get_template('Models.relationship');
$template = str_replace('$RELATIONSHIP_CLASS$', $relationClass, $template);
$template = str_replace('$FUNCTION_NAME$', $functionName, $template);
$template = str_replace('$RELATION$', $relation, $template);
$template = str_replace('$RELATION_MODEL_NAME$', $modelName, $template);
if (count($inputs) > 0) {
$inputFields = implode("', '", $inputs);
$inputFields = ", '".$inputFields."'";
} else {
$inputFields = '';
}
$template = str_replace('$INPUT_FIELDS$', $inputFields, $template);
return $template;
}
}
@@ -0,0 +1,78 @@
<?php
namespace App\Classes\CodeGenerator\Common;
use Illuminate\Support\Str;
class GeneratorHelpers
{
public function generator_tab($spaces = 4)
{
return str_repeat(' ', $spaces);
}
public function generator_tabs($tabs, $spaces = 4)
{
return str_repeat($this->generator_tab($spaces), $tabs);
}
public function generator_nl($count = 1)
{
return str_repeat(PHP_EOL, $count);
}
public function generator_nls($count, $nls = 1)
{
return str_repeat($this->generator_nl($nls), $count);
}
public function generator_nl_tab($lns = 1, $tabs = 1)
{
return $this->generator_nl($lns) . $this->generator_tabs($tabs);
}
public function get_template_file_path($templateName)
{
$templateName = str_replace('.', '/', $templateName);
return base_path('App/Classes/CodeGenerator/Stubs/'.$templateName.'.stub');
}
public function get_template($templateName)
{
$path = $this->get_template_file_path($templateName);
return file_get_contents($path);
}
public function fill_template($variables, $template)
{
foreach ($variables as $variable => $value) {
$template = str_replace($variable, $value, $template);
}
return $template;
}
public function fill_field_template($variables, $template, $field)
{
foreach ($variables as $variable => $key) {
$template = str_replace($variable, $field->$key, $template);
}
return $template;
}
public function fill_template_with_field_data($variables, $fieldVariables, $template, $field)
{
$template = $this->fill_template($variables, $template);
return $this->fill_field_template($fieldVariables, $template, $field);
}
public function model_name_from_table_name($tableName)
{
return Str::ucfirst(Str::camel(Str::singular($tableName)));
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\CodeGenerator\Common;
class TemplatesManager
{
protected $useLocale = false;
/**
* @return bool
*/
public function isUsingLocale(): bool
{
return $this->useLocale;
}
/**
* @param bool $useLocale
*/
public function setUseLocale(bool $useLocale): void
{
$this->useLocale = $useLocale;
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Classes\CodeGenerator\Generators;
use App\Classes\CodeGenerator\Common\GeneratorHelpers;
use App\Classes\CodeGenerator\Utils\FileUtil;
class BaseGenerator
{
/** @var GeneratorHelpers */
public $generatorHelpers;
/**
* BaseGenerator constructor.
*/
public function __construct()
{
$this->generatorHelpers = new GeneratorHelpers();
}
public function rollbackFile($path, $fileName)
{
if (file_exists($path.$fileName)) {
return FileUtil::deleteFile($path, $fileName);
}
return false;
}
}
@@ -0,0 +1,119 @@
<?php
namespace App\Classes\CodeGenerator\Generators;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Utils\FileUtil;
use App\Classes\CodeGenerator\Utils\GeneratorFieldsInputUtil;
use Illuminate\Support\Str;
/**
* Class FactoryGenerator.
*/
class FactoryGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var string */
private $fileName;
/**
* FactoryGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = $commandData->config->pathFactory;
$this->fileName = Str::studly(Str::singular($this->commandData->modelName)).'Factory.php';
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template('Factories.model_factory');
$templateData = $this->fillTemplate($templateData);
FileUtil::createFile($this->path, $this->fileName, $templateData);
$this->commandData->commandObj->comment("\nFactory created: ");
$this->commandData->commandObj->info($this->fileName);
}
/**
* @param string $templateData
*
* @return mixed|string
*/
private function fillTemplate($templateData)
{
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace(
'$FIELDS$',
implode(','.$this->generatorHelpers->generator_nl_tab(1, 2), $this->generateFields()),
$templateData
);
return $templateData;
}
/**
* @return array
*/
private function generateFields()
{
$fields = [];
foreach ($this->commandData->fields as $field) {
if ($field->isPrimary) {
continue;
}
$fieldData = "'".$field->name."' => ".'$faker->';
switch ($field->fieldType) {
case 'integer':
case 'float':
$fakerData = 'randomDigitNotNull';
break;
case 'string':
$fakerData = 'word';
break;
case 'text':
$fakerData = 'text';
break;
case 'datetime':
case 'timestamp':
$fakerData = "date('Y-m-d H:i:s')";
break;
case 'enum':
$fakerData = 'randomElement('.
GeneratorFieldsInputUtil::prepareValuesArrayStr($field->htmlValues).
')';
break;
default:
$fakerData = 'word';
}
$fieldData .= $fakerData;
$fields[] = $fieldData;
}
return $fields;
}
public function rollback()
{
if ($this->rollbackFile($this->path, $this->fileName)) {
$this->commandData->commandComment('Factory file deleted: '.$this->fileName);
}
}
}
@@ -0,0 +1,140 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Micros;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Common\GenerateGetters;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class DataTransferObjectGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var string */
private $fileName;
/**
* FactoryGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = app_path('Classes/Modules/'. str::pluralStudly($this->commandData->modelName).'/DataTransferObjects/');
$this->fileName = Str::studly(Str::singular($this->commandData->modelName)).'Object.php';
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template('Micros.data_transfer_object');
$templateData = $this->fillTemplate($templateData);
FileUtil::createFile($this->path, $this->fileName, $templateData);
$this->commandData->commandComment("\nDataTransferObject created: ");
$this->commandData->commandObj->info($this->fileName);
}
/**
* @param string $templateData
*
* @return mixed|string
*/
private function fillTemplate($templateData)
{
$properties = [];
$docs = [];
$injection = [];
$body = [];
$getters = [];
foreach ($this->commandData->fields as $field) {
if(!in_array($field->name, $this->commandData->config->excludeFields())){
$docType = $this->getPHPDocType($field->fieldType);
$fieldName = $docType === 'bool' ? 'is'.str::studly($field->name) : str::camel($field->name);
$properties[] = '/** @var '.$docType.' */'.PHP_EOL.$this->generatorHelpers->generator_nl_tab(0, 1).'private $'.str::camel($fieldName).';';
$docs[] = '* @param '.$docType.' $'.str::camel($fieldName);
$injection[] = $docType.' $'.str::camel($fieldName);
$body[] = '$this->'.str::camel($fieldName).' = $'.str::camel($fieldName).';';
$getters[] = (new GenerateGetters())->generate($fieldName, $docType);
}
}
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace(
'$PROPERTIES$',
implode(PHP_EOL.$this->generatorHelpers->generator_nl_tab(1, 1), $properties),
$templateData
);
$templateData = str_replace(
'$CONSTRUCTOR_DOCS$',
implode($this->generatorHelpers->generator_nl_tab(1, 2), $docs),
$templateData
);
$templateData = str_replace(
'$CONSTRUCTOR_PROPERTIES$',
implode(', ', $injection),
$templateData
);
$templateData = str_replace(
'$CONSTRUCTOR_BODY$',
implode($this->generatorHelpers->generator_nl_tab(1, 2), $body),
$templateData
);
$templateData = str_replace(
'$GETTER_FUNCTIONS$',
implode($this->generatorHelpers->generator_nl_tab(1, 0), $getters),
$templateData
);
return $templateData;
}
private function getPHPDocType($db_type){
switch ($db_type) {
case 'text':
return 'string';
case 'datetime':
return '\Carbon\Carbon';
case 'boolean':
return 'bool';
default:
return $db_type;
}
}
public function rollback()
{
if ($this->rollbackFile($this->path, $this->fileName)) {
File::deleteDirectory($this->path);
$this->commandData->commandComment('DataTransferObject file deleted: '.$this->fileName);
}
}
}
@@ -0,0 +1,75 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Micros;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Str;
class ResourceGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var string */
private $fileName;
/**
* FactoryGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = app_path('Http/Resources/');
$this->fileName = Str::studly(Str::singular($this->commandData->modelName)).'Resource.php';
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template('Resource.model_resource');
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace('$FIELDS$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 3), $this->generateFields()), $templateData);
FileUtil::createFile($this->path, $this->fileName, $templateData);
$this->commandData->commandComment("\n Resource Object created: ");
$this->commandData->commandObj->info($this->fileName);
}
private function generateFields()
{
$fields = [];
foreach ($this->commandData->fields as $field) {
$field = "'" . $field->name . "' => " . "$" . "this->" . str::snake($field->name);
$fields[] = $field;
}
return $fields;
}
public function rollback()
{
if ($this->rollbackFile($this->path, $this->fileName)) {
$this->commandData->commandComment('Resource Object file deleted: '.$this->fileName);
}
}
}
@@ -0,0 +1,68 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Micros;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class RulesGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/**
* FactoryGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = app_path('Classes/Modules/'. str::pluralStudly($this->commandData->modelName).'/Standards/Rules/');
}
public function generate()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename = 'Can'.str::studly($type.$name).'.php';
$templateData = $this->generatorHelpers->get_template('Rules.can_'.$type);
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
FileUtil::createFile($this->path, $filename, $templateData);
$this->commandData->commandComment("\n" . $type . " Rules created: ");
$this->commandData->commandObj->info($filename);
}
}
public function rollback()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename ='Can'.str::studly($type.$name).'.php';
if ($this->rollbackFile($this->path, $filename)) {
$this->commandData->commandComment($type . ' Rules file deleted: '.$filename);
}
}
File::deleteDirectory($this->path);
}
}
@@ -0,0 +1,96 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Micros;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class ServicesGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/**
* FactoryGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = app_path('Classes/Modules/'. str::pluralStudly($this->commandData->modelName).'/Services/');
}
public function generate()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename = str::studly($type.($type === 'fetch'?'es':'s').$name).'.php';
$templateData = $this->generatorHelpers->get_template("Services.".str::snake($type.'_service'));
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace(
'$FIELDS$',
implode($this->generatorHelpers->generator_nl_tab(1, 2), $this->generateFields()),
$templateData
);
FileUtil::createFile($this->path, $filename, $templateData);
$this->commandData->commandComment("\n" . $type . " service class created: ");
$this->commandData->commandObj->info($filename);
}
}
private function generateFields()
{
$fields = [];
foreach ($this->commandData->fields as $field) {
if(!in_array($field->name, $this->commandData->config->excludeFields())) {
$getterName = $field->dbInput === 'boolean' ? 'is' . str::studly($field->name) : 'get' . str::studly($field->name);
$field = "$" . "model->" . $field->name . " = $" . "object->" . $getterName . "();";
$fields[] = $field;
}
}
return $fields;
}
public function rollback()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename = str::studly($type.($type === 'fetch'?'es':'s').$name).'.php';
if ($this->rollbackFile($this->path, $filename)) {
$this->commandData->commandComment( $type . ' service class file deleted: '.$filename);
}
}
File::deleteDirectory(($this->path));
}
}
@@ -0,0 +1,112 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Micros;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class ValidatorsGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var string */
private $fileName;
/**
* FactoryGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = app_path('Classes/Modules/'. str::pluralStudly($this->commandData->modelName).'/Standards/Validators/');
$this->fileName = Str::studly(Str::singular($this->commandData->modelName)).'Validation.php';
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template('Validator.request_validation');
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace('$FIELDS$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 3), $this->generateFields()), $templateData);
$templateData = str_replace('$RULES$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 3), $this->generateRules()), $templateData);
FileUtil::createFile($this->path, $this->fileName, $templateData);
$this->commandData->commandComment("\n Request Validator created: ");
$this->commandData->commandObj->info($this->fileName);
}
private function generateRules()
{
$dont_require_fields = [];
$rules = [];
foreach ($this->commandData->fields as $field) {
if (!$field->isPrimary && $field->isNotNull && empty($field->validations) &&
!in_array($field->name, $dont_require_fields)) {
$field->validations = 'required';
}
if (!empty($field->validations)) {
if (Str::contains($field->validations, 'unique:')) {
$rule = explode('|', $field->validations);
// move unique rule to last
usort($rule, function ($record) {
return (Str::contains($record, 'unique:')) ? 1 : 0;
});
$field->validations = implode('|', $rule);
}
$rule = "'".$field->name."' => '".$field->validations."'";
$rules[] = $rule;
}
}
return $rules;
}
private function generateFields()
{
$fields = [];
foreach ($this->commandData->fields as $field) {
if(!in_array($field->name, $this->commandData->config->excludeFields())) {
$getterName = $field->dbInput === 'boolean' ? 'is' . str::studly($field->name) : 'get' . str::studly($field->name);
$field = "'" . $field->name . "' => " . "$" . "object->" . $getterName . "()";
$fields[] = $field;
}
}
return $fields;
}
public function rollback()
{
if ($this->rollbackFile($this->path, $this->fileName)) {
File::deleteDirectory($this->path);
$this->commandData->commandComment('Request Validation file deleted: '.$this->fileName);
}
}
}
@@ -0,0 +1,92 @@
<?php
namespace App\Classes\CodeGenerator\Generators;
use Illuminate\Support\Facades\File;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Str;
class MigrationGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
public function __construct($commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = database_path('migrations/');
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template('Migration.migration');
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace('$FIELDS$', $this->generateFields(), $templateData);
$tableName = $this->commandData->dynamicVars['$TABLE_NAME$'];
$fileName = date('Y_m_d_His').'_'.'create_'.Str::snake(Str::plural($tableName)).'_table.php';
FileUtil::createFile($this->path, $fileName, $templateData);
$this->commandData->commandComment("\nMigration created: ");
$this->commandData->commandInfo($fileName);
}
private function generateFields()
{
$fields = [];
$foreignKeys = [];
$createdAtField = null;
$updatedAtField = null;
$fields[] = '$table->id();';
foreach ($this->commandData->fields as $field) {
$fields[] = $field->migrationText;
if (!empty($field->foreignKeyText)) {
$foreignKeys[] = $field->foreignKeyText;
}
}
$fields[] = '$table->timestamps();';
if ($this->commandData->getOption('softDelete')) {
$fields[] = '$table->softDeletes();';
}
return implode($this->generatorHelpers->generator_nl_tab(1, 3), array_merge($fields, $foreignKeys));
}
public function rollback()
{
$fileName = 'create_'.$this->commandData->config->tableName.'_table.php';
$allFiles = File::allFiles($this->path);
$files = [];
foreach ($allFiles as $file) {
$files[] = $file->getFilename();
}
$files = array_reverse($files);
foreach ($files as $file) {
if (Str::contains($file, $fileName)) {
if ($this->rollbackFile($this->path, $file)) {
$this->commandData->commandComment('Migration file deleted: '.$file);
}
break;
}
}
}
}
@@ -0,0 +1,351 @@
<?php
namespace App\Classes\CodeGenerator\Generators;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Common\GeneratorFieldRelation;
use App\Classes\CodeGenerator\Utils\FileUtil;
use App\Classes\CodeGenerator\Utils\TableFieldsGenerator;
use Illuminate\Support\Str;
class ModelGenerator extends BaseGenerator
{
/**
* Fields not included in the generator by default.
*
* @var array
*/
protected $excluded_fields = [
'created_at',
'updated_at',
];
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
private $fileName;
private $table;
/**
* ModelGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = $commandData->config->pathModel;
$this->fileName = Str::studly(Str::singular($this->commandData->modelName)).'.php';
$this->table = $this->commandData->dynamicVars['$TABLE_NAME$'];
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template('Models.model');
$templateData = $this->fillTemplate($templateData);
FileUtil::createFile($this->path, $this->fileName, $templateData);
$this->commandData->commandComment("\nModel created: ");
$this->commandData->commandInfo($this->fileName);
}
private function fillTemplate($templateData)
{
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = $this->fillSoftDeletes($templateData);
$fillables = [];
foreach ($this->commandData->fields as $field) {
if ($field->isFillable) {
$fillables[] = "'".$field->name."'";
}
}
$templateData = $this->fillDocs($templateData);
$templateData = $this->fillTimestamps($templateData);
if ($this->commandData->getOption('primary')) {
$primary = $this->generatorHelpers->generator_tab()."protected \$primaryKey = '".$this->commandData->getOption('primary')."';\n";
} else {
$primary = '';
}
$templateData = str_replace('$PRIMARY$', $primary, $templateData);
$templateData = str_replace('$FIELDS$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 2), $fillables), $templateData);
$templateData = str_replace('$RULES$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 2), $this->generateRules()), $templateData);
$templateData = str_replace('$CAST$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 2), $this->generateCasts()), $templateData);
$templateData = str_replace(
'$RELATIONS$',
$this->generatorHelpers->fill_template($this->commandData->dynamicVars, implode(PHP_EOL.$this->generatorHelpers->generator_nl_tab(1, 1), $this->generateRelations())),
$templateData
);
$templateData = str_replace('$GENERATE_DATE$', date('F j, Y, g:i a T'), $templateData);
return $templateData;
}
private function fillSoftDeletes($templateData)
{
if (!$this->commandData->getOption('softDelete')) {
$templateData = str_replace('$SOFT_DELETE_IMPORT$', '', $templateData);
$templateData = str_replace('$SOFT_DELETE$', '', $templateData);
$templateData = str_replace('$SOFT_DELETE_DATES$', '', $templateData);
} else {
$templateData = str_replace(
'$SOFT_DELETE_IMPORT$',
"use Illuminate\\Database\\Eloquent\\SoftDeletes;\n",
$templateData
);
$templateData = str_replace('$SOFT_DELETE$', $this->generatorHelpers->generator_tab()."use SoftDeletes;\n", $templateData);
$deletedAtTimestamp = 'deleted_at';
$templateData = str_replace(
'$SOFT_DELETE_DATES$',
$this->generatorHelpers->generator_nl_tab()."protected \$dates = ['".$deletedAtTimestamp."'];\n",
$templateData
);
}
return $templateData;
}
private function fillDocs($templateData)
{
$docsTemplate = $this->generatorHelpers->get_template('Docs.model');
$docsTemplate = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $docsTemplate);
$fillables = '';
$fieldsArr = [];
$count = 1;
foreach ($this->commandData->relations as $relation) {
$field = $relationText = (isset($relation->inputs[0])) ? $relation->inputs[0] : null;
if (in_array($field, $fieldsArr)) {
$relationText = $relationText.'_'.$count;
$count++;
}
$fillables .= ' * @property '.$this->getPHPDocType($relation->type, $relation, $relationText).PHP_EOL;
$fieldsArr[] = $field;
}
foreach ($this->commandData->fields as $field) {
if ($field->isFillable) {
$fillables .= ' * @property '.$this->getPHPDocType($field->fieldType).' '.$field->name.PHP_EOL;
}
}
$docsTemplate = str_replace('$GENERATE_DATE$', date('F j, Y, g:i a'), $docsTemplate);
$docsTemplate = str_replace('$PHPDOC$', $fillables, $docsTemplate);
$templateData = str_replace('$DOCS$', $docsTemplate, $templateData);
return $templateData;
}
/**
* @param $db_type
* @param GeneratorFieldRelation|null $relation
* @param string|null $relationText
*
* @return string
*/
private function getPHPDocType($db_type, $relation = null, $relationText = null)
{
$relationText = (!empty($relationText)) ? $relationText : null;
switch ($db_type) {
case 'text':
return 'string';
case 'datetime':
return 'string|\Carbon\Carbon';
case '1t1':
return '\\'.$this->commandData->config->nsModel.'\\'.$relation->inputs[0].' '.Str::camel($relationText);
case 'mt1':
if (isset($relation->inputs[1])) {
$relationName = str_replace('_id', '', strtolower($relation->inputs[1]));
} else {
$relationName = $relationText;
}
return '\\'.$this->commandData->config->nsModel.'\\'.$relation->inputs[0].' '.Str::camel($relationName);
case '1tm':
case 'mtm':
case 'hmt':
return '\Illuminate\Database\Eloquent\Collection'.' '.Str::camel(Str::plural($relationText));
default:
if (!empty($fieldData['fieldType'])) {
return $fieldData['fieldType'];
}
return $db_type;
}
}
private function fillTimestamps($templateData)
{
$timestamps = TableFieldsGenerator::getTimestampFieldNames();
$replace = '';
if (empty($timestamps)) {
$replace = $this->generatorHelpers->generator_nl_tab()."public \$timestamps = false;\n";
}
if ($this->commandData->getOption('fromTable') && !empty($timestamps)) {
list($created_at, $updated_at) = collect($timestamps)->map(function ($field) {
return !empty($field) ? "'$field'" : 'null';
});
$replace .= $this->generatorHelpers->generator_nl_tab()."const CREATED_AT = $created_at;";
$replace .= $this->generatorHelpers->generator_nl_tab()."const UPDATED_AT = $updated_at;\n";
}
return str_replace('$TIMESTAMPS$', $replace, $templateData);
}
private function generateRules()
{
$dont_require_fields = [];
$rules = [];
foreach ($this->commandData->fields as $field) {
if (!$field->isPrimary && $field->isNotNull && empty($field->validations) &&
!in_array($field->name, $dont_require_fields)) {
$field->validations = 'required';
}
if (!empty($field->validations)) {
if (Str::contains($field->validations, 'unique:')) {
$rule = explode('|', $field->validations);
// move unique rule to last
usort($rule, function ($record) {
return (Str::contains($record, 'unique:')) ? 1 : 0;
});
$field->validations = implode('|', $rule);
}
$rule = "'".$field->name."' => '".$field->validations."'";
$rules[] = $rule;
}
}
return $rules;
}
public function generateUniqueRules()
{
$tableNameSingular = Str::singular($this->commandData->config->tableName);
$uniqueRules = '';
foreach ($this->generateRules() as $rule) {
if (Str::contains($rule, 'unique:')) {
$rule = explode('=>', $rule);
$string = '$rules['.trim($rule[0]).'].","';
$uniqueRules .= '$rules['.trim($rule[0]).'] = '.$string.'.$this->route("'.$tableNameSingular.'");';
}
}
return $uniqueRules;
}
public function generateCasts()
{
$casts = [];
$timestamps = TableFieldsGenerator::getTimestampFieldNames();
foreach ($this->commandData->fields as $field) {
if (in_array($field->name, $timestamps)) {
continue;
}
$rule = "'".$field->name."' => ";
switch (strtolower($field->fieldType)) {
case 'integer':
case 'increments':
case 'smallinteger':
case 'long':
case 'biginteger':
$rule .= "'integer'";
break;
case 'double':
$rule .= "'double'";
break;
case 'float':
case 'decimal':
$rule .= "'float'";
break;
case 'boolean':
$rule .= "'boolean'";
break;
case 'datetime':
case 'datetimetz':
$rule .= "'datetime'";
break;
case 'date':
$rule .= "'date'";
break;
case 'enum':
case 'string':
case 'char':
case 'text':
$rule .= "'string'";
break;
default:
$rule = '';
break;
}
if (!empty($rule)) {
$casts[] = $rule;
}
}
return $casts;
}
private function generateRelations()
{
$relations = [];
$count = 1;
$fieldsArr = [];
foreach ($this->commandData->relations as $relation) {
$field = (isset($relation->inputs[0])) ? $relation->inputs[0] : null;
$relationShipText = $field;
if (in_array($field, $fieldsArr)) {
$relationShipText = $relationShipText.'_'.$count;
$count++;
}
$relationText = $relation->getRelationFunctionText($relationShipText);
if (!empty($relationText)) {
$fieldsArr[] = $field;
$relations[] = $relationText;
}
}
return $relations;
}
public function rollback()
{
if ($this->rollbackFile($this->path, $this->fileName)) {
$this->commandData->commandComment('Model file deleted: '.$this->fileName);
}
}
}
@@ -0,0 +1,83 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Scaffold;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class ControllerLogicGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = app_path('Classes/Modules/'. str::pluralStudly($this->commandData->modelName).'/ControllerLogic/');
}
public function generate()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename = str::studly($type.$name).'ControllerLogic.php';
$templateData = $this->generatorHelpers->get_template("Scaffold.ControllersLogic.".$type."_controller_logic");
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace(
'$REQUEST_FIELDS$',
implode(', ', $this->generateFields()),
$templateData
);
FileUtil::createFile($this->path, $filename, $templateData);
$this->commandData->commandComment("\n" . $type . " Controller logic created: ");
$this->commandData->commandInfo($filename);
}
}
private function generateFields(){
$fields = [];
foreach ($this->commandData->fields as $field) {
if(!in_array($field->name, $this->commandData->config->excludeFields())) {
$fields[] = '$request->input(\'' . $field->name . '\')';
}
}
return $fields;
}
public function rollback()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename = str::studly($type.$name).'ControllerLogic.php';
if ($this->rollbackFile($this->path, $filename)) {
$this->commandData->commandComment($type . ' Controller logic file deleted: '.$filename);
}
}
File::deleteDirectory($this->path);
}
}
@@ -0,0 +1,64 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Scaffold;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class ControllersGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = $commandData->config->pathController.'/'.str::pluralStudly($this->commandData->modelName).'/';
}
public function generate()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename = str::studly($type.$name).'Controller.php';
$templateData = $this->generatorHelpers->get_template("Scaffold.Controllers.".$type."_controller");
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
FileUtil::createFile($this->path, $filename, $templateData);
$this->commandData->commandComment("\n" . $type . " Controller created: ");
$this->commandData->commandInfo($filename);
}
}
public function rollback()
{
foreach(['create', 'list', 'fetch', 'update', 'delete'] as $type){
$name = $type === 'list' ? str::pluralStudly($this->commandData->modelName) : str::singular($this->commandData->modelName);
$filename = str::studly($type.$name).'Controller.php';
if ($this->rollbackFile($this->path, $filename)) {
$this->commandData->commandComment($type . ' Controller file deleted: '.$filename);
}
}
File::deleteDirectory($this->path);
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Scaffold;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use Illuminate\Support\Str;
class RoutesGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var string */
private $routeContents;
/** @var string */
private $routesTemplate;
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = base_path('routes/crud.php');;
$this->routeContents = file_get_contents($this->path);
$this->routesTemplate = $this->generatorHelpers->get_template('Routes.route');
$this->routesTemplate = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $this->routesTemplate);
}
public function generate()
{
if (Str::contains($this->routeContents, "Route::group(['prefix' => '".$this->commandData->config->mSnake."',")) {
$this->commandData->commandObj->info('Routes for '.$this->commandData->config->mName.' already exists, Skipping Adjustment.');
return;
}
file_put_contents($this->path, $this->routeContents.$this->routesTemplate);
$this->commandData->commandComment("\n".$this->commandData->config->mName.' routes added.');
}
public function rollback()
{
if (Str::contains($this->routeContents, $this->routesTemplate)) {
$this->routeContents = str_replace($this->routesTemplate, '', $this->routeContents);
file_put_contents($this->path, $this->routeContents);
$this->commandData->commandComment('Routes deleted');
}
}
}
@@ -0,0 +1,53 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Scaffold;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class ViewsGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var string */
private $fileName;
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = resource_path('views/pages/'.str::plural(str::snake($this->commandData->modelName)).'/');
$this->fileName = 'index.blade.php';
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template("Views.view");
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
FileUtil::createFile($this->path, $this->fileName, $templateData);
$this->commandData->commandComment("\nView created: ");
$this->commandData->commandInfo($this->fileName);
}
public function rollback()
{
if ($this->rollbackFile($this->path, $this->fileName)) {
$this->commandData->commandComment('View file deleted: '.$this->fileName);
File::deleteDirectory($this->path);
}
}
}
@@ -0,0 +1,196 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Scaffold;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use App\Classes\CodeGenerator\Utils\FileUtil;
use App\Classes\CodeGenerator\Utils\HTMLFieldGenerator;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
class VueGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var array */
private $htmlFields;
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = resource_path('assets/vue/components/'.str::camel($this->commandData->modelName).'/');
}
public function generate()
{
$fields = [];
$i = 1;
foreach ($this->commandData->fields as $index => $field) {
if (!$field->inIndex) {
continue;
}
$fieldTemplate = $this->generatorHelpers->get_template("Views.column");
$fieldTemplate = str_replace('$FIRST_COLUMN_CLASS$', $i === 1 ? 'ist-item-heading truncate' : 'text-small', $fieldTemplate);
$fieldTemplate = str_replace('$COLUMN_SIZE$', $i === 1 ? 'col-3' : 'col', $fieldTemplate);
$fieldTemplate = $this->generatorHelpers->fill_template_with_field_data(
$this->commandData->dynamicVars,
$this->commandData->fieldNamesMapping,
$fieldTemplate,
$field
);
$fields[] = $fieldTemplate;
$i++;
}
$templateData = $this->generatorHelpers->get_template("VueJs.element_component");
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace('$FIELD_BODY$', implode($this->generatorHelpers->generator_nl_tab(1, 0), $fields), $templateData);
$fileName = $this->commandData->modelName.'Component.vue';
FileUtil::createFile($this->path.'elements/', $fileName, $templateData);
$this->commandData->commandComment("\nvue element created: ");
$this->commandData->commandInfo($fileName);
$this->generateForm();
$this->generateFilterForm();
}
private function generateForm()
{
$this->htmlFields = [];
$formFields = [];
$validations = [];
foreach ($this->commandData->fields as $field) {
if (!$field->inForm) {
continue;
}
$formFields[] = $field->name.": ''";
$validations[] = $field->name . ": { " . implode(', ', explode('|', $field->validations)) ." }";
$fieldTemplate = $this->generatorHelpers->get_template('Fields.field');
$fieldInputTemplate = HTMLFieldGenerator::generateHTML($field);
if($field->htmlType === 'selectTable'){
$fieldTemplate = str_replace('$v.parameters.$FIELD_NAME$', '$v.parameters.'.$field->name, $fieldTemplate);
$fieldTemplate = str_replace('$FIELD_NAME$', Str::replaceLast('_id', '', $field->name), $fieldTemplate);
}
$fieldTemplate = str_replace('$FIELD$', $fieldInputTemplate, $fieldTemplate);
if (!empty($fieldTemplate)) {
$fieldTemplate = $this->generatorHelpers->fill_template_with_field_data(
$this->commandData->dynamicVars,
$this->commandData->fieldNamesMapping,
$fieldTemplate,
$field
);
$this->htmlFields[] = $fieldTemplate;
}
}
$templateData = $this->generatorHelpers->get_template('VueJs.form_component');
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace('$FIELDS$', implode("\n", $this->htmlFields), $templateData);
$templateData = str_replace('$REQUEST_FIELDS$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 5), $formFields), $templateData);
$templateData = str_replace('$VALIDATION$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 4), $validations), $templateData);
FileUtil::createFile($this->path.'forms/', $this->commandData->modelName.'FormComponent.vue', $templateData);
$this->commandData->commandComment("\nvue form created: ");
$this->commandData->commandInfo($this->commandData->modelName.'FormComponent.vue');
}
private function generateFilterForm()
{
$filterFields = [];
$filterMap = [];
foreach ($this->commandData->fields as $field) {
if (!$field->isSearchable) {
continue;
}
$filterMap[] = $field->name.": ''";
$fieldTemplate = $this->generatorHelpers->get_template('Fields.filter_field');
$fieldInputTemplate = HTMLFieldGenerator::generateHTML($field);
if($field->htmlType === 'selectTable'){
$fieldTemplate = str_replace('$v.parameters.$FIELD_NAME$', '$v.parameters.'.$field->name, $fieldTemplate);
$fieldTemplate = str_replace('$FIELD_NAME$', Str::replaceLast('_id', '', $field->name), $fieldTemplate);
}
$fieldTemplate = str_replace('$FIELD$', $fieldInputTemplate, $fieldTemplate);
if (!empty($fieldTemplate)) {
$fieldTemplate = $this->generatorHelpers->fill_template_with_field_data(
$this->commandData->dynamicVars,
$this->commandData->fieldNamesMapping,
$fieldTemplate,
$field
);
$filterFields[] = $fieldTemplate;
}
}
$templateData = $this->generatorHelpers->get_template('VueJs.filter_component');
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
$templateData = str_replace('$FIELDS$', implode("\n", $filterFields), $templateData);
$templateData = str_replace('$REQUEST_FIELDS$', implode(','.$this->generatorHelpers->generator_nl_tab(1, 5), $filterMap), $templateData);
FileUtil::createFile($this->path.'forms/', $this->commandData->modelName.'FiltersComponent.vue', $templateData);
$this->commandData->commandComment("\nvue filter created: ");
$this->commandData->commandInfo($this->commandData->modelName.'FiltersComponent.vue');
}
public function rollback()
{
foreach(['elements', 'forms'] as $folderType){
if($folderType === 'elements'){
if ($this->rollbackFile($this->path.$folderType.'/', $this->commandData->modelName.'Component.vue')) {
$this->commandData->commandComment('Vue element file deleted: '.$this->commandData->modelName.'Component.vue');
}
} else {
foreach(['form', 'filter'] as $type){
if ($this->rollbackFile($this->path.$folderType.'/', $this->commandData->modelName.str::studly($type).'Component.vue')) {
$this->commandData->commandComment('Vue '.$type.' file deleted: '.$this->commandData->modelName.str::studly($type).'Component.vue');
}
}
}
File::deleteDirectory($this->path.$folderType.'/');
}
File::deleteDirectory($this->path);
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Classes\CodeGenerator\Generators\Scaffold;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Generators\BaseGenerator;
use Illuminate\Support\Str;
class WebRouteGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
/** @var string */
private $routeContents;
/** @var string */
private $routesTemplate;
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = base_path('routes/web.php');;
$this->routeContents = file_get_contents($this->path);
$this->routesTemplate = $this->generatorHelpers->get_template('Routes.web');
$this->routesTemplate = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $this->routesTemplate);
}
public function generate()
{
if (Str::contains($this->routeContents, "Route::get('/".$this->commandData->config->mSnakePlural."'")) {
$this->commandData->commandObj->info('Web route for '.$this->commandData->config->mName.' already exists, Skipping Adjustment.');
return;
}
file_put_contents($this->path, $this->routeContents.$this->routesTemplate);
$this->commandData->commandComment("\n".$this->commandData->config->mName.' web route added.');
}
public function rollback()
{
if (Str::contains($this->routeContents, $this->routesTemplate)) {
$this->routeContents = str_replace($this->routesTemplate, '', $this->routeContents);
file_put_contents($this->path, $this->routeContents);
$this->commandData->commandComment('web route deleted');
}
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\CodeGenerator\Generators;
use App\Classes\CodeGenerator\Common\CommandData;
use App\Classes\CodeGenerator\Utils\FileUtil;
use Illuminate\Support\Str;
/**
* Class SeederGenerator.
*/
class SeederGenerator extends BaseGenerator
{
/** @var CommandData */
private $commandData;
/** @var string */
private $path;
private $fileName;
/**
* ModelGenerator constructor.
*
* @param CommandData $commandData
*/
public function __construct(CommandData $commandData)
{
parent::__construct();
$this->commandData = $commandData;
$this->path = $commandData->config->pathSeeder;
$this->fileName = Str::studly($this->commandData->config->mPlural).'TableSeeder.php';
}
public function generate()
{
$templateData = $this->generatorHelpers->get_template('Seeds.model_seeder');
$templateData = $this->generatorHelpers->fill_template($this->commandData->dynamicVars, $templateData);
FileUtil::createFile($this->path, $this->fileName, $templateData);
$this->commandData->commandComment("\nSeeder created: ");
$this->commandData->commandInfo($this->fileName);
}
public function updateMainSeeder()
{
$mainSeederContent = file_get_contents($this->commandData->config->pathDatabaseSeeder);
$newSeederStatement = '$this->call('.$this->commandData->config->mPlural.'TableSeeder::class);';
if (strpos($mainSeederContent, $newSeederStatement) != false) {
$this->commandData->commandObj->info($this->commandData->config->mPlural.'TableSeeder entry found in DatabaseSeeder. Skipping Adjustment.');
return;
}
$newSeederStatement = $this->generatorHelpers->generator_tabs(2).$newSeederStatement.$this->generatorHelpers->generator_nl();
preg_match_all('/\\$this->call\\((.*);/', $mainSeederContent, $matches);
$totalMatches = count($matches[0]);
$lastSeederStatement = $matches[0][$totalMatches - 1];
$replacePosition = strpos($mainSeederContent, $lastSeederStatement);
$mainSeederContent = substr_replace($mainSeederContent, $newSeederStatement, $replacePosition + strlen($lastSeederStatement) + 1, 0);
file_put_contents($this->commandData->config->pathDatabaseSeeder, $mainSeederContent);
$this->commandData->commandComment('Main Seeder file updated.');
}
public function rollback()
{
if ($this->rollbackFile($this->path, $this->fileName)) {
$this->commandData->commandComment('Seeder file deleted: '.$this->fileName);
}
$mainSeederContent = file_get_contents($this->commandData->config->pathDatabaseSeeder);
$mainSeederContent = str_replace('$this->call('.$this->commandData->config->mPlural.'TableSeeder::class);', '', $mainSeederContent);
file_put_contents($this->commandData->config->pathDatabaseSeeder, $mainSeederContent);
$this->commandData->commandComment('Main Seeder file updated.');
}
}
@@ -0,0 +1,102 @@
[
{
"name": "company_id",
"dbType": "foreignId:foreign,companies,id",
"htmlType": "selectTable:companies:name,id",
"validations": "required",
"searchable": true,
"fillable": false,
"primary": false,
"inForm": false,
"inIndex": true,
"relation": "1t1,Company,company_id,id"
},
{
"name": "street_one",
"dbType": "string",
"htmlType": "text",
"validations": "required",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "street_two",
"dbType": "string:nullable",
"htmlType": "text",
"validations": "",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "city",
"dbType": "string",
"htmlType": "text",
"validations": "required",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "state",
"dbType": "string",
"htmlType": "text",
"validations": "required",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "post_code",
"dbType": "string",
"htmlType": "text",
"validations": "required",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "country",
"dbType": "string",
"htmlType": "text",
"validations": "required",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "default",
"dbType": "integer",
"htmlType": "number",
"validations": "required",
"searchable": false,
"fillable": false,
"primary": false,
"inForm": false,
"inIndex": false
},
{
"name": "billing",
"dbType": "integer",
"htmlType": "number",
"validations": "required",
"searchable": false,
"fillable": false,
"primary": false,
"inForm": false,
"inIndex": false
}
]
@@ -0,0 +1,35 @@
[
{
"name": "reference_no",
"dbType": "integer:unique",
"htmlType": "number",
"validations": "required",
"searchable": true,
"fillable": false,
"primary": false,
"inForm": false,
"inIndex": true
},
{
"name": "name",
"dbType": "string",
"htmlType": "text",
"validations": "required",
"searchable": true,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "type",
"dbType": "integer",
"htmlType": "number",
"validations": "required",
"searchable": true,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
}
]
@@ -0,0 +1,70 @@
[
{
"name": "company_id",
"dbType": "foreignId:foreign,companies,id",
"htmlType": "selectTable:companies:name,id",
"validations": "required",
"searchable": true,
"fillable": false,
"primary": false,
"inForm": false,
"inIndex": true,
"relation": "1t1,Company,company_id,id"
},
{
"name": "name",
"dbType": "string",
"htmlType": "text",
"validations": "required",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "designation",
"dbType": "string:nullable",
"htmlType": "text",
"validations": "",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "email",
"dbType": "string:nullable",
"htmlType": "text",
"validations": "",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
}
,
{
"name": "phone",
"dbType": "string:nullable",
"htmlType": "text",
"validations": "",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
},
{
"name": "wechat_id",
"dbType": "string:nullable",
"htmlType": "text",
"validations": "",
"searchable": false,
"fillable": true,
"primary": false,
"inForm": true,
"inIndex": true
}
]
@@ -0,0 +1,6 @@
/**
* Class $MODEL_NAME$
* @package $NAMESPACE_MODEL$
* @version $GENERATE_DATE$
*
$PHPDOC$ */
@@ -0,0 +1,12 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
$factory->define($NAMESPACE_MODEL$\$MODEL_NAME$::class, function (Faker $faker) {
return [
$FIELDS$
];
});
@@ -0,0 +1 @@
<date-picker-component v-model="parameters.$FIELD_NAME$"></date-picker-component>
@@ -0,0 +1 @@
<input v-model="parameters.$FIELD_NAME$" type="email" class="form-control">
@@ -0,0 +1,8 @@
<div class="row mb-3 animated fadeInDown fast">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.$FIELD_NAME$">
$FIELD$
<span>$FIELD_NAME$</span>
</validation-wrapper-component>
</div>
</div>
@@ -0,0 +1,8 @@
<div class="row mb-3 animated fadeInDown fast">
<div class="col">
<label class="form-group has-float-label mb-1">
$FIELD$
<span>$FIELD_NAME$</span>
</label>
</div>
</div>
@@ -0,0 +1 @@
<input v-model="parameters.$FIELD_NAME$" type="password" class="form-control">
@@ -0,0 +1 @@
<select-component :options="$INPUT_ARR$" v-model="parameters.$FIELD_NAME$"></select-component>
@@ -0,0 +1 @@
<selectable-component :endpoint="route('api.$SELECT_TABLE$.list')" section="$SELECT_TABLE_CAMEL$Section" valueColumn="$VALUE_COLUMN$" labelColumn="$LABEL_COLUMN$" v-model="parameters.$FIELD_NAME$"></selectable-component>
@@ -0,0 +1 @@
<input v-model="parameters.$FIELD_NAME$" type="text" class="form-control">
@@ -0,0 +1 @@
<textarea v-model="parameters.$FIELD_NAME$" class="form-control"></textarea>
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects;
use App\Classes\Interfaces\DataTransferObject;
class $MODEL_NAME$Object implements DataTransferObject
{
$PROPERTIES$
/**
* $MODEL_NAME$Object constructor.
$CONSTRUCTOR_DOCS$
*/
public function __construct($CONSTRUCTOR_PROPERTIES$)
{
$CONSTRUCTOR_BODY$
}
$GETTER_FUNCTIONS$
}
@@ -0,0 +1,7 @@
/**
* @return $DATA_TYPE$
*/
public function $FUNCTION_NAME$(): $DATA_TYPE$
{
return $this->$FIELD_NAME$;
}
@@ -0,0 +1,31 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class Create$TABLE_NAME_TITLE$Table extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('$TABLE_NAME$', function (Blueprint $table) {
$FIELDS$
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('$TABLE_NAME$');
}
}
@@ -0,0 +1,44 @@
<?php
namespace $NAMESPACE_MODEL$;
use $NAMESPACE_MODEL_EXTEND$ as Model;
$SOFT_DELETE_IMPORT$
$DOCS$
class $MODEL_NAME$ extends AbstractModel
{
$SOFT_DELETE$
protected $table = '$TABLE_NAME$';
$TIMESTAMPS$
$SOFT_DELETE_DATES$
$PRIMARY$
public $fillable = [
$FIELDS$
];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts = [
$CAST$
];
/**
* Validation rules
*
* @var array
*/
public static $rules = [
$RULES$
];
$RELATIONS$
}
@@ -0,0 +1,7 @@
/**
* @return \Illuminate\Database\Eloquent\Relations\$RELATIONSHIP_CLASS$
**/
public function $FUNCTION_NAME$(): $RELATIONSHIP_CLASS$
{
return $this->$RELATION$(\$NAMESPACE_MODEL$\$RELATION_MODEL_NAME$::class$INPUT_FIELDS$);
}
@@ -0,0 +1,22 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class $MODEL_NAME$Resource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
$FIELDS$
];
}
}
@@ -0,0 +1,15 @@
Route::group(['prefix' => '$MODEL_NAME_SNAKE$', 'as' => '$MODEL_NAME_SNAKE$.', 'namespace' => '$MODEL_NAME_PLURAL$'], function () {
Route::get('/{id}/show', 'Fetch$MODEL_NAME$Controller@fetch')->name('show');
Route::get('/list', 'List$MODEL_NAME_PLURAL$Controller@list')->name('list');
Route::post('/create', 'Create$MODEL_NAME$Controller@create')->name('create');
Route::put('/update/{id}', 'Update$MODEL_NAME$Controller@update')->name('update');
Route::delete('/delete/{id}', 'Delete$MODEL_NAME$Controller@destroy')->name('delete');
});
@@ -0,0 +1,5 @@
Route::get('/$MODEL_NAME_PLURAL_SNAKE$', function () {
return view('pages.$MODEL_NAME_PLURAL_SNAKE$.index');
})->name('$MODEL_NAME_SNAKE$.dashboard');
@@ -0,0 +1,57 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Validators\$MODEL_NAME$Validation;
class CanCreate$MODEL_NAME$ extends AbstractRule
{
/** @var $MODEL_NAME$Validation */
private $$MODEL_NAME_CAMEL$Validation;
/**
* CanCreate$MODEL_NAME$ constructor.
* @param $MODEL_NAME$Validation $$MODEL_NAME_CAMEL$Validation
*/
public function __construct($MODEL_NAME$Validation $$MODEL_NAME_CAMEL$Validation)
{
$this->$MODEL_NAME_CAMEL$Validation = $$MODEL_NAME_CAMEL$Validation;
}
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return $this->$MODEL_NAME_CAMEL$Validation->validate($object);
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
class CanDelete$MODEL_NAME$ extends AbstractRule
{
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function validators($object): bool
{
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
class CanFetch$MODEL_NAME$ extends AbstractRule
{
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function validators($object): bool
{
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
class CanList$MODEL_NAME_PLURAL$ extends AbstractRule
{
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function validators($object): bool
{
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,57 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Validators\$MODEL_NAME$Validation;
class CanUpdate$MODEL_NAME$ extends AbstractRule
{
/** @var $MODEL_NAME$Validation */
private $$MODEL_NAME_CAMEL$Validation;
/**
* CanUpdate$MODEL_NAME$ constructor.
* @param $MODEL_NAME$Validation $$MODEL_NAME_CAMEL$Validation
*/
public function __construct($MODEL_NAME$Validation $$MODEL_NAME_CAMEL$Validation)
{
$this->$MODEL_NAME_CAMEL$Validation = $$MODEL_NAME_CAMEL$Validation;
}
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return $this->$MODEL_NAME_CAMEL$Validation->validate($object);
}
/**
* @param $MODEL_NAME$Object $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\$MODEL_NAME_PLURAL$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic\Create$MODEL_NAME$ControllerLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Create$MODEL_NAME$Controller
{
/**
* @param Request $request
* @param Create$MODEL_NAME$ControllerLogic $logic
* @return JsonResponse
*/
public function create(Request $request, Create$MODEL_NAME$ControllerLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\$MODEL_NAME_PLURAL$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic\Delete$MODEL_NAME$ControllerLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Delete$MODEL_NAME$Controller
{
/**
* @param Request $request
* @param Delete$MODEL_NAME$ControllerLogic $logic
* @return JsonResponse
*/
public function destroy(Request $request, Delete$MODEL_NAME$ControllerLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\$MODEL_NAME_PLURAL$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic\Fetch$MODEL_NAME$ControllerLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Fetch$MODEL_NAME$Controller
{
/**
* @param Request $request
* @param Fetch$MODEL_NAME$ControllerLogic $logic
* @return JsonResponse
*/
public function fetch(Request $request, Fetch$MODEL_NAME$ControllerLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\$MODEL_NAME_PLURAL$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic\List$MODEL_NAME_PLURAL$ControllerLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class List$MODEL_NAME_PLURAL$Controller
{
/**
* @param Request $request
* @param list$MODEL_NAME_PLURAL$ControllerLogic $logic
* @return JsonResponse
*/
public function list(Request $request, list$MODEL_NAME_PLURAL$ControllerLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\$MODEL_NAME_PLURAL$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic\Update$MODEL_NAME$ControllerLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Update$MODEL_NAME$Controller
{
/**
* @param Request $request
* @param Update$MODEL_NAME$ControllerLogic $logic
* @return JsonResponse
*/
public function update(Request $request, Update$MODEL_NAME$ControllerLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,69 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Services\Creates$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules\CanCreate$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Http\Resources\$MODEL_NAME$Resource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Create$MODEL_NAME$ControllerLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Created $MODEL_NAME_HUMAN$',
'message' => 'You have successfully created a new $MODEL_NAME_HUMAN$'
];
}
/** @var CanCreate$MODEL_NAME$ */
private $canCreate$MODEL_NAME$;
/** @var Creates$MODEL_NAME$ */
private $creates$MODEL_NAME$;
/**
* Create$MODEL_NAME$ControllerLogic constructor.
* @param CanCreate$MODEL_NAME$ $canCreate$MODEL_NAME$
* @param Creates$MODEL_NAME$ $creates$MODEL_NAME$
*/
public function __construct(CanCreate$MODEL_NAME$ $canCreate$MODEL_NAME$, Creates$MODEL_NAME$ $creates$MODEL_NAME$)
{
$this->canCreate$MODEL_NAME$ = $canCreate$MODEL_NAME$;
$this->creates$MODEL_NAME$ = $creates$MODEL_NAME$;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
try {
$object = new $MODEL_NAME$Object($REQUEST_FIELDS$);
$this->canCreate$MODEL_NAME$->passes($object);
$query = $this->creates$MODEL_NAME$->execute($object);
return $this->resourceResponse(new $MODEL_NAME$Resource($query));
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
}
}
@@ -0,0 +1,73 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Services\Deletes$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Services\Fetches$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules\CanDelete$MODEL_NAME$;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Delete$MODEL_NAME$ControllerLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Deleted $MODEL_NAME_HUMAN$',
'message' => 'You have successfully deleted a $MODEL_NAME_HUMAN$'
];
}
/** @var CanDelete$MODEL_NAME$ */
private $canDelete$MODEL_NAME$;
/** @var Deletes$MODEL_NAME$ */
private $deletes$MODEL_NAME$;
/** @var Fetches$MODEL_NAME$ */
private $fetches$MODEL_NAME$;
/**
* Delete$MODEL_NAME$ControllerLogic constructor.
* @param CanDelete$MODEL_NAME$ $canDelete$MODEL_NAME$
* @param Deletes$MODEL_NAME$ $deletes$MODEL_NAME$
* @param Fetches$MODEL_NAME$ $fetches$MODEL_NAME$
*/
public function __construct(CanDelete$MODEL_NAME$ $canDelete$MODEL_NAME$, Deletes$MODEL_NAME$ $deletes$MODEL_NAME$, Fetches$MODEL_NAME$ $fetches$MODEL_NAME$)
{
$this->canDelete$MODEL_NAME$ = $canDelete$MODEL_NAME$;
$this->deletes$MODEL_NAME$ = $deletes$MODEL_NAME$;
$this->fetches$MODEL_NAME$ = $fetches$MODEL_NAME$;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
try {
$this->canDelete$MODEL_NAME$->passes();
$query = $this->fetches$MODEL_NAME$->execute(['id' => $request->route('id')]);
$this->deletes$MODEL_NAME$->execute($query);
return $this->response([]);
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
}
}
@@ -0,0 +1,67 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Services\Fetches$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules\CanFetch$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Http\Resources\$MODEL_NAME$Resource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Fetch$MODEL_NAME$ControllerLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved $MODEL_NAME_HUMAN$',
'message' => 'You have successfully retrieved a $MODEL_NAME_HUMAN$'
];
}
/** @var CanFetch$MODEL_NAME$ */
private $canFetch$MODEL_NAME$;
/** @var Fetches$MODEL_NAME$ */
private $fetches$MODEL_NAME$;
/**
* Fetch$MODEL_NAME$ControllerLogic constructor.
* @param CanFetch$MODEL_NAME$ $canFetch$MODEL_NAME$
* @param Fetches$MODEL_NAME$ $fetches$MODEL_NAME$
*/
public function __construct(CanFetch$MODEL_NAME$ $canFetch$MODEL_NAME$, Fetches$MODEL_NAME$ $fetches$MODEL_NAME$)
{
$this->canFetch$MODEL_NAME$ = $canFetch$MODEL_NAME$;
$this->fetches$MODEL_NAME$ = $fetches$MODEL_NAME$;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
try {
$this->canFetch$MODEL_NAME$->passes();
$query = $this->fetches$MODEL_NAME$->execute(['id' => $request->route('id')]);
return $this->resourceResponse(new $MODEL_NAME$Resource($query));
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
}
}
@@ -0,0 +1,66 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Services\Lists$MODEL_NAME_PLURAL$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules\CanList$MODEL_NAME_PLURAL$;
use App\Http\Resources\$MODEL_NAME$Resource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class List$MODEL_NAME_PLURAL$ControllerLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved $MODEL_NAME_PLURAL_HUMAN$',
'message' => 'You have successfully retrieved a list of $MODEL_NAME_PLURAL_HUMAN$'
];
}
/** @var CanList$MODEL_NAME_PLURAL$ */
private $canList$MODEL_NAME_PLURAL$;
/** @var Lists$MODEL_NAME_PLURAL$ */
private $lists$MODEL_NAME_PLURAL$;
/**
* List$MODEL_NAME_PLURAL$ControllerLogic constructor.
* @param CanList$MODEL_NAME_PLURAL$ $canList$MODEL_NAME_PLURAL$
* @param Lists$MODEL_NAME_PLURAL$ $lists$MODEL_NAME_PLURAL$
*/
public function __construct(CanList$MODEL_NAME_PLURAL$ $canList$MODEL_NAME_PLURAL$, Lists$MODEL_NAME_PLURAL$ $lists$MODEL_NAME_PLURAL$)
{
$this->canList$MODEL_NAME_PLURAL$ = $canList$MODEL_NAME_PLURAL$;
$this->lists$MODEL_NAME_PLURAL$ = $lists$MODEL_NAME_PLURAL$;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
try {
$this->canList$MODEL_NAME_PLURAL$->passes();
$query = $this->lists$MODEL_NAME_PLURAL$->execute($this->lists$MODEL_NAME_PLURAL$->deserializeFilters($request->input('filters')));
return $this->collectionResponse($MODEL_NAME$Resource::collection($query));
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
}
}
@@ -0,0 +1,78 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\ControllerLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Services\Updates$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Services\Fetches$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Rules\CanUpdate$MODEL_NAME$;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Http\Resources\$MODEL_NAME$Resource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class Update$MODEL_NAME$ControllerLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated $MODEL_NAME_HUMAN$',
'message' => 'You have successfully updated the $MODEL_NAME_HUMAN$'
];
}
/** @var CanUpdate$MODEL_NAME$ */
private $canUpdate$MODEL_NAME$;
/** @var Updates$MODEL_NAME$ */
private $updates$MODEL_NAME$;
/** @var Fetches$MODEL_NAME$ */
private $fetches$MODEL_NAME$;
/**
* Update$MODEL_NAME$ControllerLogic constructor.
* @param CanUpdate$MODEL_NAME$ $canUpdate$MODEL_NAME$
* @param Updates$MODEL_NAME$ $updates$MODEL_NAME$
* @param Fetches$MODEL_NAME$ $fetches$MODEL_NAME$
*/
public function __construct(CanUpdate$MODEL_NAME$ $canUpdate$MODEL_NAME$, Updates$MODEL_NAME$ $updates$MODEL_NAME$, Fetches$MODEL_NAME$ $fetches$MODEL_NAME$)
{
$this->canUpdate$MODEL_NAME$ = $canUpdate$MODEL_NAME$;
$this->updates$MODEL_NAME$ = $updates$MODEL_NAME$;
$this->fetches$MODEL_NAME$ = $fetches$MODEL_NAME$;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
try {
$object = new $MODEL_NAME$Object($REQUEST_FIELDS$);
$this->canUpdate$MODEL_NAME$->passes($object);
$query = $this->fetches$MODEL_NAME$->execute(['id' => $request->route('id')]);
$query = $this->updates$MODEL_NAME$->execute($query, $object);
return $this->resourceResponse(new $MODEL_NAME$Resource($query));
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
}
}
@@ -0,0 +1,16 @@
<?php
use Illuminate\Database\Seeder;
class $MODEL_NAME_PLURAL$TableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory($NAMESPACE_MODEL$\$MODEL_NAME$::class, 30)->create();
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Models\$MODEL_NAME$;
class Creates$MODEL_NAME$ extends AbstractUpdateRecord
{
public function execute($MODEL_NAME$Object $object) {
$model = new $MODEL_NAME$();
$FIELDS$
return $this->handler($model);
}
}
@@ -0,0 +1,15 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Services;
use App\Classes\General\Eloquent\AbstractDeleteRecord;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Models\$MODEL_NAME$;
class Deletes$MODEL_NAME$ extends AbstractDeleteRecord
{
public function execute($MODEL_NAME$ $model) {
return $this->handler($model);
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Services;
use App\Classes\General\Eloquent\AbstractFetchRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\$MODEL_NAME$;
class Fetches$MODEL_NAME$ extends AbstractFetchRecord
{
/** @var $MODEL_NAME$ */
private $repository;
/**
* Fetches$MODEL_NAME$ constructor.
* @param $MODEL_NAME$ $repository
*/
public function __construct($MODEL_NAME$ $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Services;
use App\Classes\General\Eloquent\AbstractListRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\$MODEL_NAME$;
class Lists$MODEL_NAME_PLURAL$ extends AbstractListRecord
{
/** @var $MODEL_NAME$ */
private $repository;
/**
* Lists$MODEL_NAME_PLURAL$ constructor.
* @param $MODEL_NAME$ $repository
*/
public function __construct($MODEL_NAME$ $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
use App\Models\$MODEL_NAME$;
class Updates$MODEL_NAME$ extends AbstractUpdateRecord
{
public function execute($MODEL_NAME$ $model, $MODEL_NAME$Object $object) {
$FIELDS$
return $this->handler($model);
}
}
@@ -0,0 +1,39 @@
<?php
namespace App\Classes\Modules\$MODEL_NAME_PLURAL$\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\$MODEL_NAME_PLURAL$\DataTransferObjects\$MODEL_NAME$Object;
class $MODEL_NAME$Validation extends AbstractValidation
{
/**
* @param $MODEL_NAME$Object $object
* @return array
*/
protected function data($object): array {
return [
$FIELDS$
];
}
/**
* @return array
*/
protected function rules(): array {
return [
$RULES$
];
}
/**
* @return array
*/
protected function messages(): array {
return [];
}
}
@@ -0,0 +1,16 @@
<div class="$COLUMN_SIZE$">
<div class="row">
<div class="col">
<div class=" mb-1 w-xs-100 mt-0">
<span class="align-middle d-inline-block text-muted text-small text-uppercase" style=" font-size: 9px !important; ">$FIELD_NAME$</span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="$FIRST_COLUMN_CLASS$ mb-0 w-xs-100 mt-0">
<span class="align-middle d-inline-block">{{$MODEL_NAME_CAMEL$.$FIELD_NAME$}}</span>
</div>
</div>
</div>
</div>
@@ -0,0 +1,31 @@
@extends('layouts.base_portal')
@section('inner_content')
<div class="container-fluid">
<div class="row app-row">
<div class="col-12">
<div class="row align-items-center mb-5">
<div class="col">
<h3 class="text-uppercase m-0">$MODEL_NAME_PLURAL_HUMAN$</h3>
</div>
<div class="col-auto">
<div class="top-right-button-container parentContainer">
<button type="button" class="btn btn-primary btn-lg top-right-button mr-1 requestModal" data-type="createModal">ADD NEW</button>
<form-component section="$MODEL_NAME_CAMEL$Section">
<template slot="form" slot-scope="{section}">
<$MODEL_NAME_DASHED$-form-component :section="section"></$MODEL_NAME_DASHED$-form-component>
</template>
</form-component>
</div>
</div>
</div>
<list-component key="2" section="$MODEL_NAME_CAMEL$Section" endpoint="{{ route('api.$MODEL_NAME_SNAKE$.list') }}">
<template slot="list" slot-scope="{data}">
<$MODEL_NAME_DASHED$-component :data="data"></$MODEL_NAME_DASHED$-component>
</template>
</list-component>
</div>
</div>
</div>
<$MODEL_NAME_DASHED$-filters-component section="$MODEL_NAME_CAMEL$Section"></$MODEL_NAME_DASHED$-filters-component>
@endsection
@@ -0,0 +1,41 @@
<template>
<div class="card mb-3 parentContainer">
<div class="row pt-3 pb-3 pr-4 pl-4">
<div class="col">
<div class="row align-items-center">
$FIELD_BODY$
<div class="col text-right">
<button type="button" class="btn btn-outline-secondary icon-button mr-3 requestModal" data-type="editModal"><i class="iconsminds-pen-2"></i></button>
<button type="button" class="btn btn-outline-danger icon-button requestModal" data-type="deleteModal"><i class="simple-icon-trash"></i></button>
</div>
</div>
</div>
</div>
<form-component section="$MODEL_NAME_CAMEL$Section" :data="$MODEL_NAME_CAMEL$">
<template slot="form" slot-scope="{section, data}">
<$MODEL_NAME_DASHED$-form-component :section="section" :data="data"></$MODEL_NAME_DASHED$-form-component>
</template>
</form-component>
<delete-component section="$MODEL_NAME_CAMEL$Section" :requestRoute="route('api.$MODEL_NAME_SNAKE$.delete', $MODEL_NAME_CAMEL$.id)" name="$MODEL_NAME_DASHED$"></delete-component>
</div>
</template>
<script>
export default {
props: {
data: {
type: Object,
required: true
}
},
data() {
return {
$MODEL_NAME_CAMEL$: this.data,
}
},
watch: {
'data': function() {
this.$MODEL_NAME_CAMEL$ = this.data;
}
}
}
</script>
@@ -0,0 +1,49 @@
<template>
<div class="app-menu">
<div class="p-4 h-100">
<div class="scroll">
<p class="text-muted text-small">Filter</p>
<div class="row">
<div class="col">
<div class="row mb-3">
<div class="col">
$FIELDS$
</div>
</div>
<div class="row mb-3">
<div class="col">
<div class="row">
<div class="col">
<button type="button" class="btn btn-secondary btn-block" @click="updateFilters()">Search</button>
</div>
</div>
<div class="row mt-3">
<div class="col text-center">
<small class="text-small text-muted pointer" @click="resetForm();updateFilters()">Clear Search Filters</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
section: {
type: String,
required: true
}
},
data(){
return {
parameters: {
$REQUEST_FIELDS$
},
}
}
}
</script>
@@ -0,0 +1,63 @@
<template>
<div class="row" v-on:keyup.enter="submitForm()">
<div class="col">
<div class="row mb-3">
<div class="col">
$FIELDS$
</div>
</div>
<div class="row mb-3">
<div class="col">
<div class="row">
<div class="col text-right">
<button type="button" class="btn btn-outline-dark float-left" @click="closeModal()">Cancel</button>
<button type="button" class="btn btn-primary" @click="submitForm()">Submit</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { required, email } from "vuelidate/lib/validators";
export default {
props: {
section: {
type: String,
required: true
},
data: {
type: Object,
default: null
}
},
created() {
if(this.data){
this.parameters = this.data;
}
},
data() {
return {
parameters: {
$REQUEST_FIELDS$
},
};
},
validations: {
parameters: {
$VALIDATION$
}
},
methods:{
submitForm(){
this.submit((this.data ? this.route('api.$MODEL_NAME_SNAKE$.update', this.data.id) : this.route('api.$MODEL_NAME_SNAKE$.create')), (this.data ? 'put' : 'post'), this.section+'.form', true, true)
},
successHandler(){
this.crudSuccess();
}
}
}
</script>
@@ -0,0 +1,193 @@
<?php
namespace $NAMESPACE_APP$\Repositories;
use Illuminate\Container\Container as Application;
use Illuminate\Database\Eloquent\Model;
abstract class BaseRepository
{
/**
* @var Model
*/
protected $model;
/**
* @var Application
*/
protected $app;
/**
* @param Application $app
*
* @throws \Exception
*/
public function __construct(Application $app)
{
$this->app = $app;
$this->makeModel();
}
/**
* Get searchable fields array
*
* @return array
*/
abstract public function getFieldsSearchable();
/**
* Configure the Model
*
* @return string
*/
abstract public function model();
/**
* Make Model instance
*
* @throws \Exception
*
* @return Model
*/
public function makeModel()
{
$model = $this->app->make($this->model());
if (!$model instanceof Model) {
throw new \Exception("Class {$this->model()} must be an instance of Illuminate\\Database\\Eloquent\\Model");
}
return $this->model = $model;
}
/**
* Paginate records for scaffold.
*
* @param int $perPage
* @param array $columns
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
public function paginate($perPage, $columns = ['*'])
{
$query = $this->allQuery();
return $query->paginate($perPage, $columns);
}
/**
* Build a query for retrieving all records.
*
* @param array $search
* @param int|null $skip
* @param int|null $limit
* @return \Illuminate\Database\Eloquent\Builder
*/
public function allQuery($search = [], $skip = null, $limit = null)
{
$query = $this->model->newQuery();
if (count($search)) {
foreach($search as $key => $value) {
if (in_array($key, $this->getFieldsSearchable())) {
$query->where($key, $value);
}
}
}
if (!is_null($skip)) {
$query->skip($skip);
}
if (!is_null($limit)) {
$query->limit($limit);
}
return $query;
}
/**
* Retrieve all records with given filter criteria
*
* @param array $search
* @param int|null $skip
* @param int|null $limit
* @param array $columns
*
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
*/
public function all($search = [], $skip = null, $limit = null, $columns = ['*'])
{
$query = $this->allQuery($search, $skip, $limit);
return $query->get($columns);
}
/**
* Create model record
*
* @param array $input
*
* @return Model
*/
public function create($input)
{
$model = $this->model->newInstance($input);
$model->save();
return $model;
}
/**
* Find model record for given id
*
* @param int $id
* @param array $columns
*
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|Model|null
*/
public function find($id, $columns = ['*'])
{
$query = $this->model->newQuery();
return $query->find($id, $columns);
}
/**
* Update model record for given id
*
* @param array $input
* @param int $id
*
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|Model
*/
public function update($input, $id)
{
$query = $this->model->newQuery();
$model = $query->findOrFail($id);
$model->fill($input);
$model->save();
return $model;
}
/**
* @param int $id
*
* @throws \Exception
*
* @return bool|mixed|null
*/
public function delete($id)
{
$query = $this->model->newQuery();
$model = $query->findOrFail($id);
return $model->delete();
}
}
@@ -0,0 +1,37 @@
<?php
namespace App\Classes\CodeGenerator\Utils;
class FileUtil
{
public static function createFile($path, $fileName, $contents)
{
if (!file_exists($path)) {
mkdir($path, 0755, true);
}
$path = $path.$fileName;
file_put_contents($path, $contents);
}
public static function createDirectoryIfNotExist($path, $replace = false)
{
if (file_exists($path) && $replace) {
rmdir($path);
}
if (!file_exists($path)) {
mkdir($path, 0755, true);
}
}
public static function deleteFile($path, $fileName)
{
if (file_exists($path.$fileName)) {
return unlink($path.$fileName);
}
return false;
}
}
@@ -0,0 +1,105 @@
<?php
namespace App\Classes\CodeGenerator\Utils;
use App\Classes\CodeGenerator\Common\GeneratorField;
class GeneratorFieldsInputUtil
{
public static function validateFieldInput($fieldInputStr)
{
$fieldInputs = explode(' ', $fieldInputStr);
if (count($fieldInputs) < 2) {
return false;
}
return true;
}
/**
* @param string $fieldInput
* @param string $validations
*
* @return GeneratorField
*/
public static function processFieldInput($fieldInput, $validations)
{
/*
* Field Input Format: field_name <space> db_type <space> html_type(optional) <space> options(optional)
* Options are to skip the field from certain criteria like searchable, fillable, not in form, not in index
* Searchable (s), Fillable (f), In Form (if), In Index (ii)
* Sample Field Inputs
*
* title string text
* body text textarea
* name string,20 text
* post_id integer:unsigned:nullable
* post_id integer:unsigned:nullable:foreign,posts,id
* password string text if,ii,s - options will skip field from being added in form, in index and searchable
*/
$fieldInputsArr = explode(' ', $fieldInput);
$field = new GeneratorField();
$field->name = $fieldInputsArr[0];
$field->parseDBType($fieldInputsArr[1]);
if (count($fieldInputsArr) > 2) {
$field->parseHtmlInput($fieldInputsArr[2]);
}
if (count($fieldInputsArr) > 3) {
$field->parseOptions($fieldInputsArr[3]);
}
$field->validations = $validations;
return $field;
}
public static function prepareKeyValueArrayStr($arr)
{
$arrStr = '[';
foreach ($arr as $key => $item) {
$arrStr .= "'$item' => '$key', ";
}
$arrStr = substr($arrStr, 0, strlen($arrStr) - 2);
$arrStr .= ']';
return $arrStr;
}
public static function prepareValuesArrayStr($arr)
{
$arrStr = '[';
foreach ($arr as $item) {
$arrStr .= "'$item', ";
}
$arrStr = substr($arrStr, 0, strlen($arrStr) - 2);
$arrStr .= ']';
return $arrStr;
}
public static function prepareKeyValueArrFromLabelValueStr($values)
{
$arr = [];
foreach ($values as $value) {
$labelValue = explode(':', $value);
if (count($labelValue) > 1) {
$arr[$labelValue[0]] = $labelValue[1];
} else {
$arr[$labelValue[0]] = $labelValue[0];
}
}
return $arr;
}
}
@@ -0,0 +1,85 @@
<?php
namespace App\Classes\CodeGenerator\Utils;
use App\Classes\CodeGenerator\Common\GeneratorField;
use App\Classes\CodeGenerator\Common\GeneratorHelpers;
use Illuminate\Support\Str;
class HTMLFieldGenerator
{
public static function generateHTML(GeneratorField $field)
{
$fieldTemplate = '';
$generatorHelpers = new GeneratorHelpers();
switch ($field->htmlType) {
case 'text':
case 'number':
case 'checkbox':
$fieldTemplate = $generatorHelpers->get_template('Fields.text');
break;
case 'textarea':
case 'date':
case 'file':
case 'email':
case 'password':
$fieldTemplate = $generatorHelpers->get_template('Fields.'.$field->htmlType);
break;
case 'select':
case 'enum':
$fieldTemplate = $generatorHelpers->get_template('Fields.select');
$radioLabels = GeneratorFieldsInputUtil::prepareKeyValueArrFromLabelValueStr($field->htmlValues);
$fieldTemplate = str_replace(
'$INPUT_ARR$',
GeneratorFieldsInputUtil::prepareKeyValueArrayStr($radioLabels),
$fieldTemplate
);
break;
case 'selectTable':
$inputArr = explode(',', $field->htmlValues[1]);
$selectTable = $field->htmlValues[0];
$fieldTemplate = $generatorHelpers->get_template('Fields.selectable');
$fieldTemplate = str_replace('$SELECT_TABLE$', str::singular($selectTable),$fieldTemplate);
$fieldTemplate = str_replace('$SELECT_TABLE_CAMEL$', str::singular(str::camel($selectTable)),$fieldTemplate);
$fieldTemplate = str_replace('$LABEL_COLUMN$',$inputArr[0],$fieldTemplate);
$fieldTemplate = str_replace('$VALUE_COLUMN$',$inputArr[1],$fieldTemplate);
break;
case 'checkbox_2':
$fieldTemplate = $generatorHelpers->get_template('Fields.checkbox');
if (count($field->htmlValues) > 0) {
$checkboxValue = $field->htmlValues[0];
} else {
$checkboxValue = 1;
}
$fieldTemplate = str_replace('$CHECKBOX_VALUE$', $checkboxValue, $fieldTemplate);
break;
case 'radio':
$fieldTemplate = $generatorHelpers->get_template('Fields.radio_group');
$radioTemplate = $generatorHelpers->get_template('Fields.radio');
$radioLabels = GeneratorFieldsInputUtil::prepareKeyValueArrFromLabelValueStr($field->htmlValues);
$radioButtons = [];
foreach ($radioLabels as $label => $value) {
$radioButtonTemplate = str_replace('$LABEL$', $label, $radioTemplate);
$radioButtonTemplate = str_replace('$VALUE$', $value, $radioButtonTemplate);
$radioButtons[] = $radioButtonTemplate;
}
$fieldTemplate = str_replace('$RADIO_BUTTONS$', implode("\n", $radioButtons), $fieldTemplate);
break;
case 'toggle-switch':
$fieldTemplate = $generatorHelpers->get_template('Fields.toggle-switch');
break;
}
return $fieldTemplate;
}
}
@@ -0,0 +1,41 @@
<?php
namespace App\Classes\CodeGenerator\Utils;
class ResponseUtil
{
/**
* @param string $message
* @param mixed $data
*
* @return array
*/
public static function makeResponse($message, $data)
{
return [
'success' => true,
'data' => $data,
'message' => $message,
];
}
/**
* @param string $message
* @param array $data
*
* @return array
*/
public static function makeError($message, array $data = [])
{
$res = [
'success' => false,
'message' => $message,
];
if (!empty($data)) {
$res['data'] = $data;
}
return $res;
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Classes\CodeGenerator\Utils;
class SchemaUtil
{
public static function createField($field)
{
$fieldName = $field['fieldName'];
$databaseInputStr = $field['databaseInputs'];
$databaseInputs = explode(':', $databaseInputStr);
$fieldTypeParams = explode(',', array_shift($databaseInputs));
$fieldType = array_shift($fieldTypeParams);
$fieldStr = '$table->'.$fieldType."('".$fieldName."'";
if (count($fieldTypeParams) > 0) {
$fieldStr .= ', '.implode(' ,', $fieldTypeParams);
}
if ($fieldType == 'enum') {
$inputsArr = explode(',', $field['htmlTypeInputs']);
$inputArrStr = GeneratorFieldsInputUtil::prepareValuesArrayStr($inputsArr);
$fieldStr .= ', '.$inputArrStr;
}
$fieldStr .= ')';
if (count($databaseInputs) > 0) {
foreach ($databaseInputs as $databaseInput) {
$databaseInput = explode(',', $databaseInput);
$type = array_shift($databaseInput);
$fieldStr .= "->$type(".implode(',', $databaseInput).')';
}
}
$fieldStr .= ';';
return $fieldStr;
}
}
@@ -0,0 +1,541 @@
<?php
namespace App\Classes\CodeGenerator\Utils;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Column;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use App\Classes\CodeGenerator\Common\GeneratorField;
use App\Classes\CodeGenerator\Common\GeneratorFieldRelation;
class GeneratorForeignKey
{
/** @var string */
public $name;
public $localField;
public $foreignField;
public $foreignTable;
public $onUpdate;
public $onDelete;
}
class GeneratorTable
{
/** @var string */
public $primaryKey;
/** @var GeneratorForeignKey[] */
public $foreignKeys;
}
class TableFieldsGenerator
{
/** @var string */
public $tableName;
public $primaryKey;
/** @var bool */
public $defaultSearchable;
/** @var array */
public $timestamps;
/** @var AbstractSchemaManager */
private $schemaManager;
/** @var Column[] */
private $columns;
/** @var GeneratorField[] */
public $fields;
/** @var GeneratorFieldRelation[] */
public $relations;
/** @var array */
public $ignoredFields;
public function __construct($tableName, $ignoredFields, $connection = '')
{
$this->tableName = $tableName;
$this->ignoredFields = $ignoredFields;
if (!empty($connection)) {
$this->schemaManager = DB::connection($connection)->getDoctrineSchemaManager();
} else {
$this->schemaManager = DB::getDoctrineSchemaManager();
}
$platform = $this->schemaManager->getDatabasePlatform();
$defaultMappings = [
'enum' => 'string',
'json' => 'text',
'bit' => 'boolean',
];
$mappings = [];
$mappings = array_merge($mappings, $defaultMappings);
foreach ($mappings as $dbType => $doctrineType) {
$platform->registerDoctrineTypeMapping($dbType, $doctrineType);
}
$columns = $this->schemaManager->listTableColumns($tableName);
$this->columns = [];
foreach ($columns as $column) {
if (!in_array($column->getName(), $ignoredFields)) {
$this->columns[] = $column;
}
}
$this->primaryKey = $this->getPrimaryKeyOfTable($tableName);
$this->timestamps = static::getTimestampFieldNames();
$this->defaultSearchable = false;
}
/**
* Prepares array of GeneratorField from table columns.
*/
public function prepareFieldsFromTable()
{
foreach ($this->columns as $column) {
$type = $column->getType()->getName();
switch ($type) {
case 'integer':
$field = $this->generateIntFieldInput($column, 'integer');
break;
case 'smallint':
$field = $this->generateIntFieldInput($column, 'smallInteger');
break;
case 'bigint':
$field = $this->generateIntFieldInput($column, 'bigInteger');
break;
case 'boolean':
$name = Str::title(str_replace('_', ' ', $column->getName()));
$field = $this->generateField($column, 'boolean', 'checkbox,1');
break;
case 'datetime':
$field = $this->generateField($column, 'datetime', 'date');
break;
case 'datetimetz':
$field = $this->generateField($column, 'dateTimeTz', 'date');
break;
case 'date':
$field = $this->generateField($column, 'date', 'date');
break;
case 'time':
$field = $this->generateField($column, 'time', 'text');
break;
case 'decimal':
$field = $this->generateNumberInput($column, 'decimal');
break;
case 'float':
$field = $this->generateNumberInput($column, 'float');
break;
case 'string':
$field = $this->generateField($column, 'string', 'text');
break;
case 'text':
$field = $this->generateField($column, 'text', 'textarea');
break;
default:
$field = $this->generateField($column, 'string', 'text');
break;
}
if (strtolower($field->name) == 'password') {
$field->htmlType = 'password';
} elseif (strtolower($field->name) == 'email') {
$field->htmlType = 'email';
} elseif (in_array($field->name, $this->timestamps)) {
$field->isSearchable = false;
$field->isFillable = false;
$field->inForm = false;
$field->inIndex = false;
$field->inView = false;
}
$field->isNotNull = (bool) $column->getNotNull();
$field->description = $column->getComment(); // get comments from table
$this->fields[] = $field;
}
}
/**
* Get primary key of given table.
*
* @param string $tableName
*
* @return string|null The column name of the (simple) primary key
*/
public function getPrimaryKeyOfTable($tableName)
{
$column = $this->schemaManager->listTableDetails($tableName)->getPrimaryKey();
return $column ? $column->getColumns()[0] : '';
}
/**
* Get timestamp columns from config.
*
* @return array the set of [created_at column name, updated_at column name]
*/
public static function getTimestampFieldNames()
{
$createdAtName = 'created_at';
$updatedAtName = 'updated_at';
$deletedAtName = 'deleted_at';
return [$createdAtName, $updatedAtName, $deletedAtName];
}
/**
* Generates integer text field for database.
*
* @param string $dbType
* @param Column $column
*
* @return GeneratorField
*/
private function generateIntFieldInput($column, $dbType)
{
$field = new GeneratorField();
$field->name = $column->getName();
$field->parseDBType($dbType);
$field->htmlType = 'number';
if ($column->getAutoincrement()) {
$field->dbInput .= ',true';
} else {
$field->dbInput .= ',false';
}
if ($column->getUnsigned()) {
$field->dbInput .= ',true';
}
return $this->checkForPrimary($field);
}
/**
* Check if key is primary key and sets field options.
*
* @param GeneratorField $field
*
* @return GeneratorField
*/
private function checkForPrimary(GeneratorField $field)
{
if ($field->name == $this->primaryKey) {
$field->isPrimary = true;
$field->isFillable = false;
$field->isSearchable = false;
$field->inIndex = false;
$field->inForm = false;
$field->inView = false;
}
return $field;
}
/**
* Generates field.
*
* @param Column $column
* @param $dbType
* @param $htmlType
*
* @return GeneratorField
*/
private function generateField($column, $dbType, $htmlType)
{
$field = new GeneratorField();
$field->name = $column->getName();
$field->parseDBType($dbType, $column);
$field->parseHtmlInput($htmlType);
return $this->checkForPrimary($field);
}
/**
* Generates number field.
*
* @param Column $column
* @param string $dbType
*
* @return GeneratorField
*/
private function generateNumberInput($column, $dbType)
{
$field = new GeneratorField();
$field->name = $column->getName();
$field->parseDBType($dbType.','.$column->getPrecision().','.$column->getScale());
$field->htmlType = 'number';
return $this->checkForPrimary($field);
}
/**
* Prepares relations (GeneratorFieldRelation) array from table foreign keys.
*/
public function prepareRelations()
{
$foreignKeys = $this->prepareForeignKeys();
$this->checkForRelations($foreignKeys);
}
/**
* Prepares foreign keys from table with required details.
*
* @return GeneratorTable[]
*/
public function prepareForeignKeys()
{
$tables = $this->schemaManager->listTables();
$fields = [];
foreach ($tables as $table) {
$primaryKey = $table->getPrimaryKey();
if ($primaryKey) {
$primaryKey = $primaryKey->getColumns()[0];
}
$formattedForeignKeys = [];
$tableForeignKeys = $table->getForeignKeys();
foreach ($tableForeignKeys as $tableForeignKey) {
$generatorForeignKey = new GeneratorForeignKey();
$generatorForeignKey->name = $tableForeignKey->getName();
$generatorForeignKey->localField = $tableForeignKey->getLocalColumns()[0];
$generatorForeignKey->foreignField = $tableForeignKey->getForeignColumns()[0];
$generatorForeignKey->foreignTable = $tableForeignKey->getForeignTableName();
$generatorForeignKey->onUpdate = $tableForeignKey->onUpdate();
$generatorForeignKey->onDelete = $tableForeignKey->onDelete();
$formattedForeignKeys[] = $generatorForeignKey;
}
$generatorTable = new GeneratorTable();
$generatorTable->primaryKey = $primaryKey;
$generatorTable->foreignKeys = $formattedForeignKeys;
$fields[$table->getName()] = $generatorTable;
}
return $fields;
}
/**
* Prepares relations array from table foreign keys.
*
* @param GeneratorTable[] $tables
*/
private function checkForRelations($tables)
{
// get Model table name and table details from tables list
$modelTableName = $this->tableName;
$modelTable = $tables[$modelTableName];
unset($tables[$modelTableName]);
$this->relations = [];
// detects many to one rules for model table
$manyToOneRelations = $this->detectManyToOne($tables, $modelTable);
if (count($manyToOneRelations) > 0) {
$this->relations = array_merge($this->relations, $manyToOneRelations);
}
foreach ($tables as $tableName => $table) {
$foreignKeys = $table->foreignKeys;
$primary = $table->primaryKey;
// if foreign key count is 2 then check if many to many relationship is there
if (count($foreignKeys) == 2) {
$manyToManyRelation = $this->isManyToMany($tables, $tableName, $modelTable, $modelTableName);
if ($manyToManyRelation) {
$this->relations[] = $manyToManyRelation;
continue;
}
}
// iterate each foreign key and check for relationship
foreach ($foreignKeys as $foreignKey) {
// check if foreign key is on the model table for which we are using generator command
if ($foreignKey->foreignTable == $modelTableName) {
// detect if one to one relationship is there
$isOneToOne = $this->isOneToOne($primary, $foreignKey, $modelTable->primaryKey);
if ($isOneToOne) {
$modelName = model_name_from_table_name($tableName);
$this->relations[] = GeneratorFieldRelation::parseRelation('1t1,'.$modelName);
continue;
}
// detect if one to many relationship is there
$isOneToMany = $this->isOneToMany($primary, $foreignKey, $modelTable->primaryKey);
if ($isOneToMany) {
$modelName = model_name_from_table_name($tableName);
$this->relations[] = GeneratorFieldRelation::parseRelation(
'1tm,'.$modelName.','.$foreignKey->localField
);
continue;
}
}
}
}
}
/**
* Detects many to many relationship
* If table has only two foreign keys
* Both foreign keys are primary key in foreign table
* Also one is from model table and one is from diff table.
*
* @param GeneratorTable[] $tables
* @param string $tableName
* @param GeneratorTable $modelTable
* @param string $modelTableName
*
* @return bool|GeneratorFieldRelation
*/
private function isManyToMany($tables, $tableName, $modelTable, $modelTableName)
{
// get table details
$table = $tables[$tableName];
$isAnyKeyOnModelTable = false;
// many to many model table name
$manyToManyTable = '';
$foreignKeys = $table->foreignKeys;
$primary = $table->primaryKey;
// check if any foreign key is there from model table
foreach ($foreignKeys as $foreignKey) {
if ($foreignKey->foreignTable == $modelTableName) {
$isAnyKeyOnModelTable = true;
}
}
// if foreign key is there
if (!$isAnyKeyOnModelTable) {
return false;
}
foreach ($foreignKeys as $foreignKey) {
$foreignField = $foreignKey->foreignField;
$foreignTableName = $foreignKey->foreignTable;
// if foreign table is model table
if ($foreignTableName == $modelTableName) {
$foreignTable = $modelTable;
} else {
$foreignTable = $tables[$foreignTableName];
// get the many to many model table name
$manyToManyTable = $foreignTableName;
}
// if foreign field is not primary key of foreign table
// then it can not be many to many
if ($foreignField != $foreignTable->primaryKey) {
return false;
break;
}
// if foreign field is primary key of this table
// then it can not be many to many
if ($foreignField == $primary) {
return false;
}
}
if (empty($manyToManyTable)) {
return false;
}
$modelName = model_name_from_table_name($manyToManyTable);
return GeneratorFieldRelation::parseRelation('mtm,'.$modelName.','.$tableName);
}
/**
* Detects if one to one relationship is there
* If foreign key of table is primary key of foreign table
* Also foreign key field is primary key of this table.
*
* @param string $primaryKey
* @param GeneratorForeignKey $foreignKey
* @param string $modelTablePrimary
*
* @return bool
*/
private function isOneToOne($primaryKey, $foreignKey, $modelTablePrimary)
{
if ($foreignKey->foreignField == $modelTablePrimary) {
if ($foreignKey->localField == $primaryKey) {
return true;
}
}
return false;
}
/**
* Detects if one to many relationship is there
* If foreign key of table is primary key of foreign table
* Also foreign key field is not primary key of this table.
*
* @param string $primaryKey
* @param GeneratorForeignKey $foreignKey
* @param string $modelTablePrimary
*
* @return bool
*/
private function isOneToMany($primaryKey, $foreignKey, $modelTablePrimary)
{
if ($foreignKey->foreignField == $modelTablePrimary) {
if ($foreignKey->localField != $primaryKey) {
return true;
}
}
return false;
}
/**
* Detect many to one relationship on model table
* If foreign key of model table is primary key of foreign table.
*
* @param GeneratorTable[] $tables
* @param GeneratorTable $modelTable
*
* @return array
*/
private function detectManyToOne($tables, $modelTable)
{
$manyToOneRelations = [];
$foreignKeys = $modelTable->foreignKeys;
foreach ($foreignKeys as $foreignKey) {
$foreignTable = $foreignKey->foreignTable;
$foreignField = $foreignKey->foreignField;
if (!isset($tables[$foreignTable])) {
continue;
}
if ($foreignField == $tables[$foreignTable]->primaryKey) {
$modelName = model_name_from_table_name($foreignTable);
$manyToOneRelations[] = GeneratorFieldRelation::parseRelation(
'mt1,'.$modelName.','.$foreignKey->localField
);
}
}
return $manyToOneRelations;
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class AccessForbiddenException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'A forbidden attempt to access protected resources was detected',
HttpStatus::ACCESS_FORBIDDEN);
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class AccessUnauthorisedException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'An unauthorised attempt to access protected resources was detected',
HttpStatus::ACCESS_UNAUTHORISED);
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\Exceptions;
use Exception;
use Illuminate\Support\Facades\Log;
class ErrorException extends Exception {
/**
* ErrorException constructor.
*
* @param string $message
* @param int $code
*/
public function __construct(string $message, int $code = 0) {
parent::__construct($message, $code);
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class InternalServerErrorException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'An internal server error has occurred. Please check application logs for more information.',
HttpStatus::SERVER_ERROR);
}
}
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class MalformedRequestException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'Unable to process the request as it is malformed', HttpStatus::BAD_REQUEST);
}
}
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class RequestValidationException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'Unable to process the request due to validation failure', HttpStatus::VALIDATION_FAILED);
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class ResourceConflictException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'Unable to create the requested resource as it already exists',
HttpStatus::RESOURCE_ALREADY_EXISTS);
}
}
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class ResourceNotFoundException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'Unable to find the requested resource', HttpStatus::RESOURCE_NOT_FOUND);
}
}
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\Exceptions;
abstract class ServiceApiException extends ErrorException {
public function __construct(string $message, int $httpStatusCode = 500) {
parent::__construct($message, $httpStatusCode);
$this->httpStatusCode = $httpStatusCode;
}
}
@@ -0,0 +1,87 @@
<?php
namespace App\Classes\General\Abstracts;
use App\Classes\ValueObjects\Constants\Notifications;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
abstract class AbstractControllerLogic
{
/**
* @return array
*/
abstract protected function notification(): array;
/**
* @return string
*/
private function getNotificationTitle():string {
return $this->notification()['title'] ? $this->notification()['title']: Notifications::UNDEFINED['title'];
}
/**
* @return string
*/
private function getNotificationMessage():string {
return $this->notification()['message'] ? $this->notification()['message']: Notifications::UNDEFINED['message'];
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
abstract protected function logic(Request $request) : JsonResponse;
/**
* @param Request $request
* @return JsonResponse
*/
public function execute(Request $request) : JsonResponse {
try {
return $this->logic($request);
} catch (ErrorException $exception){
return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(), $exception->getCode()))->handler();
}
}
/**
* @param array|null $data
* @return JsonResponse
*/
public function response(?array $data = []) : JsonResponse {
return (new ApiResponseObject($this->getNotificationTitle().' Successful',
$this->getNotificationMessage(),
HttpStatus::OK_WITH_MESSAGE, $data))->handler();
}
/**
* @param JsonResource $resource
* @return JsonResponse
*/
public function resourceResponse(JsonResource $resource){
return $this->response(['data' => $resource]);
}
/**
* @param ResourceCollection $collection
* @return JsonResponse
*/
public function collectionResponse(ResourceCollection $collection){
return $this->response(json_decode($collection->response()->getContent(), true));
}
}
@@ -0,0 +1,46 @@
<?php
namespace App\Classes\General\Abstracts;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\Interfaces\DataTransferObject;
abstract class AbstractRule
{
abstract protected function authorized(): bool;
abstract protected function validators($object): bool;
abstract protected function criteria($object): bool;
/**
* @param DataTransferObject|null $object
* @return bool
* @throws AccessForbiddenException
* @throws RequestValidationException
*/
public function passes(?DataTransferObject $object = null): bool {
try {
if(!$this->authorized()){
throw new AccessForbiddenException('You don\'t have permission to preform this action');
}
$this->validators($object);
$this->criteria($object);
return true;
} catch(AccessForbiddenException $exception){
throw new AccessForbiddenException('You don\'t have permission to preform this action');
} catch(\Exception $exception){
throw new RequestValidationException($exception->getMessage());
}
}
}

Some files were not shown because too many files have changed in this diff Show More