From c0f265d0a9d59552e7175ae186762f6f0bc99d55 Mon Sep 17 00:00:00 2001 From: monkenWu <610877102@mail.nknu.edu.tw> Date: Mon, 9 Mar 2020 21:09:40 +0800 Subject: [PATCH] init --- .gitignore | 1 + composer.json | 27 +++ src/CliCreate.php | 262 ++++++++++++++++++++++++++++ src/Controller/CreateController.php | 101 +++++++++++ src/Controller/template/controller | 10 ++ src/Model/CreateModel.php | 199 +++++++++++++++++++++ src/Model/template/basicModel | 8 + src/Model/template/entity | 8 + src/Model/template/entityModel | 13 ++ src/Model/template/manualModel | 13 ++ src/Model/template/model | 23 +++ 11 files changed, 665 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 src/CliCreate.php create mode 100755 src/Controller/CreateController.php create mode 100755 src/Controller/template/controller create mode 100755 src/Model/CreateModel.php create mode 100755 src/Model/template/basicModel create mode 100755 src/Model/template/entity create mode 100755 src/Model/template/entityModel create mode 100644 src/Model/template/manualModel create mode 100755 src/Model/template/model diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57872d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..c801dc0 --- /dev/null +++ b/composer.json @@ -0,0 +1,27 @@ +{ + "name": "monken/cli-create", + "description": "Cli-Create is based on CodeIgniter4. It will help you generate template files more quickly when developing projects with CodeIgniter4.", + "keywords": [ + "codeigniter", + "codeigniter4", + "cli", + "create" + ], + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "monkenWu", + "email": "610877102@mail.nknu.edu.tw" + } + ], + "minimum-stability": "stable", + "require": { + "php" : "^7.2" + }, + "autoload": { + "psr-4": { + "CliCreate\\Commands\\": "src" + } + } +} diff --git a/src/CliCreate.php b/src/CliCreate.php new file mode 100644 index 0000000..dcbb613 --- /dev/null +++ b/src/CliCreate.php @@ -0,0 +1,262 @@ + + * @link https://github.com/monkenWu/Codeigniter4-Easy-create + * + */ + +namespace CliCreate\Commands; +use CodeIgniter\CLI\CLI; + +class CliCreate { + + /** + * 取得使用者名稱 + * + * @param array $params CLI所取得的 params 陣列 + * @param String $type 將影響到提示中的文字 + * @return string + */ + public static function getName(array &$params,String $type){ + $name = array_shift($params); + if (empty($name)){ + $name = CLI::prompt( + CLI::color("Name the {$type} file","blue") + ); + } + if (empty($name)){ + CLI::error("You must provide a {$type} file name."); + exit(); + } + return $name; + } + + /** + * 取得使用者輸入的命名空間 + * + * 將會判斷使用者所輸入的值是否符合規則,並且將所有的路徑強制轉換成第一個字母大寫的形式。 + * @param String $type Models、Controllers或App下的任何資料夾。 + * @return string 將回傳取得的命名空間。 + */ + public static function getNameSpace(String $type){ + $name = CLI::prompt( + CLI::color("The current namespace is \"App \ {$type}\", and what you type will be concatenated after this ","blue") + ); + while(strstr($name, '/')){ + $name = CLI::prompt( + CLI::color("Namespace cannot be separated by '\',Please retype ","blue") + ); + } + if( (str_split($name)[0] != "\\") && ($name != "")){ + $name = "\\".$name; + } + $tempArray = explode("\\",$name); + $returnName = ""; + foreach ($tempArray as $key => $value) { + if($value != "") $returnName .= "\\".ucfirst($value); + } + return $returnName; + } + + /** + * 判斷是否有一個以上的true存在。 + * + * @param Array $boolArr + * @return boolean + */ + public static function isMulti(Array $boolArr){ + $num = 0; + foreach ($boolArr as $key => $value) { + if($value) $num++; + } + return $num > 1 ? true : false; + } + + /** + * 寫入檔案。 + * + * @param String $writePath 寫入檔案的絕對路徑 + * @param String $fileText 檔案名稱 + * @return string + */ + public static function writeFile(String $writePath,String $fileText){ + helper('filesystem'); + + if (! write_file($writePath, $fileText)){ + CLI::error("Failed to create file."); + exit(); + } + + CLI::write('Created successfully: ' . + CLI::color($writePath, 'green') + ); + } + + /** + * 取得模板。 + * + * @param String $path 絕對路徑 + * @param String $name 模板名稱 + * @return string + */ + public static function getTemplate(String $path,String $name){ + $filePath = $path.$name; + $handle = fopen($filePath, "r"); + $template = fread($handle, filesize($filePath)); + fclose($handle); + if($template){ + return $template; + }else{ + CLI::error("Template loading error."); + exit(); + } + } + + /** + * 確認檔案是否存在。 + * + * 若檔案存在,將會詢問使用者是否需要覆寫檔案,或取消寫入。 + * @param String $filePath 檔案完整路徑,包含檔名 + * @param String $type 本次操作的分類,將影響到提示文字 + * @return void + */ + public static function checkFileEexists(String $filePath,String $type){ + if(file_exists($filePath)){ + $check = CLI::prompt( + CLI::color("Found the same {$type} file name,Do you need overwrite the file?","yellow"), + ['y','n'] + ); + if($check == "n"){ + CLI::write("{$type} creation process has ". + CLI::color("stopped.", 'yellow') + ); + exit(); + } + } + } + + /** + * 替換模板檔案的 Tag 。 + * + * @param String $template 模板字串。 + * @param Array $repalceData 索引陣列, key 值為模板檔案中的 Tag 名稱,Value 為替換值。 + * @return string 替換後的結果 + */ + public static function replaceText(String $template,Array $repalceData){ + foreach ($repalceData as $key => $value) { + $template = str_replace("{{$key}}", $value, $template); + } + return $template; + } + + /** + * 取得檔案路徑。 + * + * 將會判斷當前執行的系統是否為windows,將會回傳符合系統要求的絕對路徑。 + * @param String $appPath 專案app資料夾路徑 + * @param String $type Models、Controllers或App下的任何資料夾。 + * @param String $dir 是否有更多層資料夾,以 "\\" 分隔。預設為空。 + * @param String $fileName 檔案名稱,不須傳入 ".php" 副檔名。預設為空。 + * @return String 回傳絕對路徑。 + */ + static public function getPath(String $appPath,String $type,String $dir = "",String $fileName = ""){ + $word = ""; + + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $word = "\\"; + }else{ + $word = "/"; + } + + $dirArr = explode("\\",$dir); + $appPath = $appPath.$type; + + foreach ($dirArr as $key => $value) { + $temp = $appPath; + if($key > 0){ + $temp .= $word; + } + $temp .= $value; + if(!is_dir($temp)){ + mkdir($temp,0755); + } + $appPath = $temp; + } + + $fileName .= $fileName != "" ? ".php" : ""; + + return $appPath.$word.$fileName; + } + + /** + * 取得資料夾下所有的命名空間。 + * + * @param String $appPath + * @param String $type Models、Controllers或App下的任何資料夾。 + * @return array 命名空間陣列 + */ + public static function getAllNamespace(String $appPath,String $type){ + $map = directory_map("{$appPath}{$type}/", FALSE, TRUE); + $nameArr = []; + + $getDeepMap = function($map,$key,&$nameArr) use (&$getDeepMap){ + $nowDir = $key; + foreach ($map as $key => $value) { + if(gettype($key) != "integer"){ + $getDeepMap($map,"{$nowDir}{$key}",$nameArr); + } + $path = $nowDir.str_replace(".php","",$value); + $path = str_replace("/","\\",$path); + $nameArr[] = $path; + } + }; + + foreach ($map as $key => $value) { + if(gettype($key) != "integer"){ + $getDeepMap($value,"App/{$type}/{$key}",$nameArr); + }else{ + if(!strstr($value,".php")) continue; + $path = "App/{$type}/".str_replace(".php","",$value); + $path = str_replace("/","\\",$path); + $nameArr[] = $path; + } + } + + return $nameArr; + } + + /** + * 顯示表格,並且回傳使用者所選擇的 ID 。 + * + * @param Array $namespaceArr 傳入由命名空間組成的陣列 + * @return array 使用者所選擇的 id + */ + public static function selectTable(Array $namespaceArr){ + + $thead = ['ID', 'Namespace', 'ID', 'Namespace']; + $tbody = []; + foreach ($namespaceArr as $key => $value) { + if($key%2==0){ + $tbody[] = [$key,$value]; + }else{ + array_push($tbody[count($tbody)-1],$key,$value); + } + } + + CLI::table($tbody,$thead); + $useID = CLI::prompt( + CLI::color("Please enter the ID of the model you want to use.\nIf there are multiple, they are separated by \",\" ","blue") + ); + + return $useID; + } + +} \ No newline at end of file diff --git a/src/Controller/CreateController.php b/src/Controller/CreateController.php new file mode 100755 index 0000000..15e00a8 --- /dev/null +++ b/src/Controller/CreateController.php @@ -0,0 +1,101 @@ + + * @link https://github.com/monkenWu/Codeigniter4-Easy-create + * + */ + +namespace CliCreate\Commands\Controller; +use CodeIgniter\CLI\BaseCommand; +use CodeIgniter\CLI\CLI; +use CliCreate\Commands\CliCreate; + +class CreateController extends BaseCommand{ + + protected $group = 'Cli-Create'; + protected $name = 'create:controller'; + protected $description = 'Create a new controller file.'; + protected $usage = 'create:controller [controller_name] [Options]'; + protected $arguments = [ + 'controller_name' => 'The controller name.', + ]; + protected $options = [ + '-nobase' => 'Do not extends BaseControllers Class.', + '-usemodel' => 'Choose models.', + '-space' => 'Using this option will create folders and files according to the path you typed.' + ]; + + private $controllerName; + private $useModel = false; + private $useBase = true; + private $nameSpace = false; + private $templatePath; + private $appPath; + + public function run(array $params = []){ + $this->controllerName = ucfirst(CliCreate::getName($params,"controller")); + $this->appPath = APPPATH; + $this->templatePath = dirname(__FILE__)."/template/"; + $this->getOption(); + + $useController = ""; + $extendsController = "BaseController"; + if(!$this->useBase){ + $useController = "\nuse CodeIgniter\Controller;"; + $extendsController = "Controller"; + } + + //get namespace + $space = ""; + if($this->nameSpace){ + $space = CliCreate::getNameSpace("Controllers"); + } + + //get model + $useModels = ""; + if($this->useModel){ + $modelList = CliCreate::getAllNamespace($this->appPath,"Models"); + + $useID = CliCreate::selectTable($modelList); + + $numArr = explode(",",$useID); + foreach ($numArr as $key => $value) { + $useModels .= "use {$modelList[$value]};\n" ?? ""; + } + } + + $templateData = [ + "name" => $this->controllerName, + "namespace" => $space, + "useController" => $useController, + "extendsController" => $extendsController, + "useModels" => $useModels + ]; + $template = CliCreate::getTemplate($this->templatePath,"controller"); + $replaceTemplate = CliCreate::replaceText($template,$templateData); + $writePath = CliCreate::getPath($this->appPath,"Controllers",$space,$this->controllerName); + CliCreate::checkFileEexists($writePath,"Controller"); + CliCreate::writeFile($writePath,$replaceTemplate); + return; + } + + /** + * 取得可能被使用者輸入的 options + * + * @return Void + */ + private function getOption(){ + $this->useBase = !empty(CLI::getOption('nobase'))?false:true; + $this->useModel = !empty(CLI::getOption('usemodel'))?true:false; + $this->nameSpace = !empty(CLI::getOption('space'))?true:false; + } + +} \ No newline at end of file diff --git a/src/Controller/template/controller b/src/Controller/template/controller new file mode 100755 index 0000000..8e4ecd9 --- /dev/null +++ b/src/Controller/template/controller @@ -0,0 +1,10 @@ + + * @link https://github.com/monkenWu/Codeigniter4-Cli-Create + * + */ + +namespace CliCreate\Commands\Controller; +use CodeIgniter\CLI\BaseCommand; +use CodeIgniter\CLI\CLI; +use CliCreate\Commands\CliCreate; + +class CreateModel extends BaseCommand{ + + protected $group = 'Cli-Create'; + protected $name = 'create:model'; + protected $description = 'Create a new model file.'; + protected $usage = 'create:model [model_name] [entity_name] [Options]'; + protected $arguments = [ + 'model_name' => 'The model name', + 'entity_name' => 'The entity name.If you selected -entity option.You well type this arguments.' + ]; + protected $options = [ + '-basic' => 'Create a basic model file.', + '-entity' => 'Use Entity Classes.', + '-manual' => 'Create a Manual Model.', + '-space' => 'Using this option will create folders and files according to the path you typed.' + ]; + + private $modelName; + private $entityName; + private $nameSpace = false; + private $appPath; + private $templatePath; + private $option; + + public function run(array $params = []){ + $this->option = $this->getOption(); + $this->modelName = ucfirst(CliCreate::getName($params,"model")); + $this->appPath = APPPATH; + $this->templatePath = dirname(__FILE__)."/template/"; + if($this->option == "basic"){ + $this->writeBasicModel(); + }else if($this->option == "entity"){ + $this->entityName = ucfirst(CliCreate::getName($params,"entity")); + $this->writeEntity(); + }else if($this->option == "manual"){ + $this->writeManual(); + }else { + $this->writeModel(); + } + return; + } + + /** + * 取得可能被使用者輸入的 options + * + * @return string 判斷 option 後回傳本次的所執行的模式。 + */ + private function getOption(){ + $basic = CLI::getOption('basic'); + $entity = CLI::getOption('entity'); + $manual = CLI::getOption('manual'); + $space = CLI::getOption('space'); + $isMulti = CliCreate::isMulti([ + !empty($basic),!empty($entity),!empty($manual) + ]); + + if($isMulti){ + CLI::error("Only one option can be selected in -basic , -entity or -manual."); + exit(); + } + + if(!empty($space)){ + $this->nameSpace = true; + } + + if(!empty($basic)){ + return "basic"; + }else if(!empty($entity)){ + return "entity"; + }else if(!empty($manual)){ + return "manual"; + }else{ + return "null"; + } + } + + /** + * 寫入基本的 Model檔案 + * + * @return void + */ + private function writeBasicModel(){ + $space = ""; + if($this->nameSpace){ + $space = CliCreate::getNameSpace("Models"); + } + $sendData = [ + "name" => $this->modelName, + "namespace" => $space + ]; + $template = CliCreate::getTemplate($this->templatePath,"basicModel"); + $replaceTemplate = CliCreate::replaceText($template,$sendData); + $writePath = CliCreate::getPath($this->appPath,"Models",$space,$this->modelName); + CliCreate::checkFileEexists($writePath,"Model"); + CliCreate::writeFile($writePath,$replaceTemplate); + } + + /** + * 寫入 Manual Model 檔案。 + * + * @return void + */ + private function writeManual(){ + $space = ""; + if($this->nameSpace){ + $space = CliCreate::getNameSpace("Models"); + } + $sendData = [ + "name" => $this->modelName, + "namespace" => $space + ]; + $template = CliCreate::getTemplate($this->templatePath,"manualModel"); + $replaceTemplate = CliCreate::replaceText($template,$sendData); + $writePath = CliCreate::getPath($this->appPath,"Models",$space,$this->modelName); + CliCreate::checkFileEexists($writePath,"Model"); + CliCreate::writeFile($writePath,$replaceTemplate); + } + + /** + * 寫入 Model 檔案。 + * + * @return void + */ + private function writeModel(){ + $space = ""; + if($this->nameSpace){ + $space = CliCreate::getNameSpace("Models"); + } + $sendData = [ + "name" => $this->modelName, + "namespace" => $space + ]; + $template = CliCreate::getTemplate($this->templatePath,"model"); + $replaceTemplate = CliCreate::replaceText($template,$sendData); + $writePath = CliCreate::getPath($this->appPath,"Models",$space,$this->modelName); + CliCreate::checkFileEexists($writePath,"Model"); + CliCreate::writeFile($writePath,$replaceTemplate); + } + + /** + * 同時寫入 Entity 與 Model 檔案。 + * + * @return void + */ + private function writeEntity(){ + //get model namespace + $space = ""; + $entitySpace = ""; + if($this->nameSpace){ + $space = CliCreate::getNameSpace("Models"); + $entitySpace = CliCreate::getNameSpace("Entities"); + } + + $sendData = [ + "name" => $this->modelName, + "entityNames" => $this->entityName, + "namespace" => $space, + "entityNamespace" => $entitySpace + ]; + $template = CliCreate::getTemplate($this->templatePath,"entityModel"); + $replaceTemplateModel = CliCreate::replaceText($template,$sendData); + + $sendData = [ + "name" => $this->entityName, + "namespace" => $entitySpace + ]; + $template = CliCreate::getTemplate($this->templatePath,"entity"); + $replaceTemplateEntity = CliCreate::replaceText($template,$sendData); + + $writeModelPath = CliCreate::getPath($this->appPath,"Models",$space,$this->modelName); + $writeEntityPath = CliCreate::getPath($this->appPath,"Entities",$entitySpace,$this->entityName); + CliCreate::checkFileEexists($writeModelPath,"Model"); + CliCreate::checkFileEexists($writeEntityPath,"Entities",$this->entityName,"Entitiy"); + + CliCreate::writeFile($writeModelPath,$replaceTemplateModel); + CliCreate::writeFile($writeEntityPath,$replaceTemplateEntity); + } + +} \ No newline at end of file diff --git a/src/Model/template/basicModel b/src/Model/template/basicModel new file mode 100755 index 0000000..bb39cc7 --- /dev/null +++ b/src/Model/template/basicModel @@ -0,0 +1,8 @@ +db =& $db; + } +} diff --git a/src/Model/template/model b/src/Model/template/model new file mode 100755 index 0000000..7b4b8e0 --- /dev/null +++ b/src/Model/template/model @@ -0,0 +1,23 @@ +