| Current Path : /var/www/html/jkm/backend/modules/mmngr/controllers/ |
| Current File : /var/www/html/jkm/backend/modules/mmngr/controllers/ModuleGeneratorController.php |
<?php
namespace backend\modules\mmngr\controllers;
use Yii;
use yii\web\Controller;
/**
* Module for import external module trough zip file.
*/
class ModuleGeneratorController extends Controller
{
/**
* Template path
*/
const TEMPLATE_GII = 'dynaweb';
public function actionIndex()
{
return $this->render('index', []);
}
/**
* Generates the code based on the current user input and the specified code template files.
*/
public function actionGenerate()
{
$post = Yii::$app->request->post();
$module_id = $post['moduleid'];
$module_name = $post['name'];
$module_icon = $post['icon'];
$module_version = $post['version'];
$module_author = $post['author'];
$module_email = $post['email'];
$model_ns = "backend\\modules\\{$module_id}\\models";
$module_class = "backend\\modules\\{$module_id}\\Module";
$controller_class = "backend\\modules\\{$module_id}\\controllers";
$module_description = $post['description'];
if(empty($module_id)) {
Yii::$app->session->addFlash('log', 'Empty module, id, module id is required.');
}
if($this->createModule($module_id, $module_class)) {
Yii::$app->session->addFlash('log', 'Generating Module Success');
}
//create table and output tablename
$tablename = $this->createTable($module_id, [
'name' => $post['field_name'],
'type' => $post['field_type'],
'length' => $post['field_length']
]);
// create model
if($this->createModel($tablename, $model_ns, ucfirst($module_id))) {
Yii::$app->session->addFlash('log', 'Generating Model Success ');
};
// create crud
if($this->createCrud(
$controller_class,
ucfirst($module_id) . "Controller", //controller name
$model_ns . "\\" . ucfirst($module_id), // model name,
$module_id
)) {
Yii::$app->session->addFlash('log', 'Generating Crud Success');
};
// create menu
if($this->createMenu($module_name, $module_id, $module_icon)) {
Yii::$app->session->addFlash('log', 'Generating Menu Success');
};
if($this->assignModule($module_name, $module_id, $module_version, $module_author, $module_email, $module_description)) {
Yii::$app->session->addFlash('log', 'Assigning Menu Success');
};
$this->redirect('view');
}
/***
* view model generation status
*
**/
public function actionView() {
return $this->render('view');
}
/**
* Create Module
*/
private function createModule($module_id, $module_class)
{
$parameter = [
'--interactive=' . '0',
'--overwrite=' . '1',
'--moduleID=' . '"' . $module_id . '"',
'--moduleClass=' . '"' . $module_class . '"',
];
$full_parameters = implode(' ', $parameter);
$output = $this->shellCommand('yii gii/module', $full_parameters);
if(strpos($output, 'Files were generated successfully!') > 0) {
return true;
} else {
Yii::$app->session->addFlash('log', $output);
}
return false;
}
private function assignModule($module_name, $module_id, $module_version, $module_author, $module_email, $module_description)
{
try {
$current_date = date('Y-m-d H:i:s');
// add parent menu
Yii::$app->db->createCommand(
<<<SQL
INSERT INTO `module_import` (`id`, `module_id`, `name`, `version`, `class`, `params`, `routes`, `author`, `email`, `licence`, `description`, `file_content`, `image_path`, `data`, `homepage`, `created`) VALUES (NULL, '{$module_id}', '{$module_name}', '{$module_version}', 'backend\\\modules\\\\$module_id\\\\Module', NULL, '', '{$module_author}', '{$module_email}', '', '{$module_description}', '', '', '', '', '{$current_date}');
SQL
)
->execute()
;
return true;
} catch(\Throwable $t) {
Yii::$app->session->addFlash('err', 'Assigning Module error:-' . PHP_EOL );
Yii::$app->session->addFlash('err', $t->getMessage() . PHP_EOL);
}
}
/**
* Create Module
*/
private function createModel($table_name, $namespace, $model_class)
{
$parameter = [
'--interactive=' . '0',
'--tableName=' . '"' . $table_name . '"',
'--ns=' . '"' . $namespace . '"',
'--modelClass=' . '"' . $model_class . '"',
];
$full_parameters = implode(' ', $parameter);
$output = $this->shellCommand('yii gii/model', $full_parameters);
if(strpos($output, 'Files were generated successfully!') > 0) {
return true;
}
return false;
}
/**
* Create Module
*/
private function createCrud($controller_class, $controller_name, $model_class, $module_id)
{
//controler dir
$controller_dir = str_replace("\\", "/", $controller_class);
$controller_dir = '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . $controller_dir;
$view_dir = $this->camelToKebabCase($module_id);
//create dir if not exist
if (!is_dir($controller_dir)) {
mkdir($controller_dir);
}
$parameter = [
'--interactive=' . '0',
'--template=' . '"' . self::TEMPLATE_GII . '"',
'--viewPath=' . '"' . "@backend/modules/{$module_id}/views/{$view_dir}" . '"',
'--controllerClass=' . '"' . $controller_class . '\\' . $controller_name . '"',
'--modelClass=' . '"' . $model_class . '"'
];
$full_parameters = implode(' ', $parameter);
$output = $this->shellCommand('yii gii/crud', $full_parameters);
if(strpos($output, 'done!') > 0) {
echo 'Crud Generated';
return true;
}
return false;
}
/**
* Create table
*/
private function createTable($moduleId, $columns)
{
try {
// create table
$tablename = $this->snakeCaseFromCamelCase($moduleId);
$query_table_exist = Yii::$app->db->createCommand("SHOW TABLES LIKE '{$tablename}'")->queryAll();
if(!empty($query_table_exist)) {
// Yii::$app->db->createCommand("DROP TABLE {$tablename}")->execute();
throw new \Exception("This table name is already exists ({$tablename})");
}
// create the tables
//add column
if(is_array($columns)) {
$rows = [];
$migrate = new \yii\db\Migration();
//column definition
$migrate_columns = [];
// set primary key
$migrate_columns[$tablename . '_id'] = $migrate->primaryKey(); // {modulename}_id as primary key
//combine field as one row array // $key = 'name/type/length'
foreach($columns as $key => $column) {
$i = 0;
foreach($column as $val) {
$rows[$i][$key] = $val;
$i++;
}
}
// loop trough row and construct the column based on type
foreach($rows as $row) {
var_dump($row['type']);
$migrate_columns[$row['name']] = $this->columnTypeMap($row['type'], $row['length']);
}
//run the migrations
$migrate->createTable($tablename, $migrate_columns);
return $tablename;
}
} catch(\Throwable $t) {
Yii::$app->session->addFlash('err', 'Database Error:-' . PHP_EOL );
Yii::$app->session->addFlash('err', $t->getMessage() . PHP_EOL);
return $this->redirect('view');
}
}
/**
* run shell
*/
private function shellCommand($command, $parameters) {
$shell_comand = '';
// detect server os
if (PHP_OS_FAMILY === "Windows") {
echo "Running on Windows";die;
} elseif (PHP_OS_FAMILY === "Linux") {
echo "Running on Linux";
$shell_comand = "cd ../../ && php {$command} {$parameters}";
}
// Yii::$app->session->addFlash('log', $shell_comand . PHP_EOL );
return shell_exec($shell_comand);
}
/**
* Create menu for the module
*/
private function createMenu($module_name, $module_id, $module_icon) {
try {
$module_path = $this->camelToKebabCase($module_id);
$parent_menu_id = 0;
$query_generated_module_menu = Yii::$app->db->createCommand(
<<<SQL
SELECT * FROM backend_menu WHERE menu_name = "Cms Modules"
SQL
)
->queryOne()
;
if(empty($query_generated_module_menu)) {
// add parent menu
Yii::$app->db->createCommand(
<<<SQL
INSERT INTO `backend_menu` (`menu_id`, `menu_name`, `menu_link`, `menu_active_route`, `menu_class`, `menu_param`, `menu_status`, `menu_parent_id`, `menu_descr`) VALUES (NULL, 'Cms Modules', '#', '', 'fa fa-maxcdn', '', '1', '0', 'Generated Module from cms');
SQL
)
->execute()
;
$parent_menu_id = Yii::$app->db->getLastInsertID();
// map parent menu
Yii::$app->db->createCommand(
<<<SQL
INSERT INTO `backend_role_mapping` (`id`, `role_code`, `menu_id`, `parent_id`, `sort`) VALUES (NULL, 'super-admin', '{$parent_menu_id}', '0', '99');
SQL
)
->execute()
;
$parent_map_id = Yii::$app->db->getLastInsertID();
} else {
$parent_menu_id = $query_generated_module_menu['menu_id'];
$query_generated_module_menu = Yii::$app->db->createCommand(
<<<SQL
SELECT * FROM `backend_role_mapping` WHERE `menu_id` = $parent_menu_id
SQL
)
->queryOne()
;
$parent_map_id = $query_generated_module_menu['id'];
}
// add menu
Yii::$app->db->createCommand(
<<<SQL
INSERT INTO `backend_menu` (`menu_id`, `menu_name`, `menu_link`, `menu_class`, `menu_status`) VALUES (NULL, '{$module_name}', '/{$module_id}/{$module_path}/index', '{$module_icon}', '1');
SQL
)
->execute()
;
// map child menu to parent menu
$menu_id = Yii::$app->db->getLastInsertID();
Yii::$app->db->createCommand(
<<<SQL
INSERT INTO `backend_role_mapping` (`id`, `role_code`, `menu_id`, `parent_id`) VALUES (NULL, 'super-admin', '{$menu_id}', '{$parent_map_id}');
SQL
)
->execute()
;
return true;
}
catch(\Throwable $t) {
Yii::$app->session->addFlash('err', 'Create Module Menu error:-' . PHP_EOL );
Yii::$app->session->addFlash('err', $t->getMessage() . PHP_EOL);
}
}
/**
* Column type
*/
private function columnTypeMap($type, $length) {
$migrate = new \yii\db\Migration();
$map = [
'string' => $migrate->string($length),
'text' => $migrate->text($length),
'date' => $migrate->datetime(),
'int' => $migrate->integer($length),
];
return $map[$type];
}
private function camelToKebabCase($str) {
// Replace uppercase letters preceded by lowercase letters with a "-" before them
$kebab = preg_replace('/(?<!^)[A-Z]/', '-\\0', $str);
// Convert the entire string to lowercase
return strtolower($kebab);
}
private function snakeCaseFromCamelCase($input) {
return strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
}
}