<?php
 namespace TCMS\Gen;
 class TCMSGenModel {
 public function createModel($options) {
 if(isset($options['help'])) {
 $this->showHelpCreateModel();
 return true;
 }
 $modelName = $this->formatModelName($options);
 if(!$modelName) {
 showLogError("Vui lòng nhập tên model.");
 showLogInfo("Nhập --help để xem hướng dẫn tạo model.");
 return false;
 }
 $isPrivate = false;
 $namespaceName = "Model";
 if(isset($options['private'])) {
 $appId = readAppId();
 $modelPath = ROOT_PATH . 'apps' . DIRECTORY_SEPARATOR . $appId . DIRECTORY_SEPARATOR . 'models';
 if(!file_exists($modelPath)) {
 mkdir($modelPath);
 }
 $modelPath .= DIRECTORY_SEPARATOR . $modelName . ".php";
 $namespaceName = $this->formatAppNamespace($appId) . "\Model";
 $isPrivate = true;
 }
 else {
 if(isset($options['module'])) {
 $appId = false;
 $modulePath = ROOT_PATH . 'modules' . DIRECTORY_SEPARATOR . $options['module'];
 if(!file_exists($modulePath)) {
 showLogError("Module $modulePath không tồn tại");
 exit();
 }
 else {
 $moduleName = basename($modulePath);
 if(!file_exists($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php')) {
 showLogError("Module $modulePath không tồn tại");
 exit();
 }
 $namespaceName = $this->readNamespace($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php');
 $modelPath = $modulePath . DIRECTORY_SEPARATOR . 'models';
 if(!file_exists($modelPath)) {
 mkdir($modelPath);
 }
 $modelPath = $modelPath . DIRECTORY_SEPARATOR . $modelName . ".php";
 }
 }
 else {
 if(isset($options['p-module'])) {
 $appId = readAppId();
 $modulePath = ROOT_PATH . 'apps' . DIRECTORY_SEPARATOR . $appId . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . $options['p-module'];
 if(!file_exists($modulePath)) {
 showLogError("Module $modulePath không tồn tại");
 exit();
 }
 else {
 $moduleName = basename($modulePath);
 if(!file_exists($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php')) {
 showLogError("Module $modulePath không tồn tại");
 exit();
 }
 $namespaceName = $this->readNamespace($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php');
 $modelPath = $modulePath . DIRECTORY_SEPARATOR . 'models';
 if(!file_exists($modelPath)) {
 mkdir($modelPath);
 }
 $modelPath = $modelPath . DIRECTORY_SEPARATOR . $modelName . ".php";
 }
 }
 else {
 if(isset($options['p-extension'])) {
 $appId = readAppId();
 $modulePath = ROOT_PATH . 'apps' . DIRECTORY_SEPARATOR . $appId . DIRECTORY_SEPARATOR . 'extensions' . DIRECTORY_SEPARATOR . $options['p-extension'];
 if(!file_exists($modulePath)) {
 showLogError("Extension $modulePath không tồn tại");
 exit();
 }
 else {
 $moduleName = basename($modulePath);
 if(!file_exists($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php')) {
 showLogError("Extension $modulePath không tồn tại");
 exit();
 }
 $namespaceName = $this->readNamespace($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php');
 $modelPath = $modulePath . DIRECTORY_SEPARATOR . 'models';
 if(!file_exists($modelPath)) {
 mkdir($modelPath);
 }
 $modelPath = $modelPath . DIRECTORY_SEPARATOR . $modelName . ".php";
 }
 }
 else {
 if(isset($options['extension'])) {
 $appId = false;
 $modulePath = ROOT_PATH . 'extensions' . DIRECTORY_SEPARATOR . $options['extension'];
 if(!file_exists($modulePath)) {
 showLogError("Extension $modulePath không tồn tại");
 exit();
 }
 else {
 $moduleName = basename($modulePath);
 if(!file_exists($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php')) {
 showLogError("Extension $modulePath không tồn tại");
 exit();
 }
 $namespaceName = $this->readNamespace($modulePath . DIRECTORY_SEPARATOR . $moduleName . '.php');
 $modelPath = $modulePath . DIRECTORY_SEPARATOR . 'models';
 if(!file_exists($modelPath)) {
 mkdir($modelPath);
 }
 $modelPath = $modelPath . DIRECTORY_SEPARATOR . $modelName . ".php";
 }
 }
 else {
 $appId = false;
 $modelPath = ROOT_PATH . 'models' . DIRECTORY_SEPARATOR . $modelName . ".php";
 }
 }
 }
 }
 }
 if(file_exists($modelPath)) {
 showLogError("Model $modelName đã tồn tại");
 return false;
 }
 $this->createModelFile($modelPath, $modelName, isset($options['table']) ? $options['table'] : '', $namespaceName, $isPrivate, $appId);
 showLogSuccess("Tạo thành công model $modelPath");
 }
 private function readNamespace($file) {
 $lines = readConfigFile($file);
 $moduleNamespace = false;
 $moduleClassName = false;
 foreach($lines as $line) {
 $l = trim($line);
 if(strpos($l, "namespace") === 0) {
 $moduleNamespace = trim(substr($l, 9));
 $moduleNamespace = str_replace(";", "", $moduleNamespace);
 }
 if(strpos($l, "class") === 0 && strpos($l, "extends") !== false) {
 $endIndex = strpos($l, "extends");
 $moduleClassName = substr($l, 0, $endIndex);
 $moduleClassName = trim(substr($moduleClassName, 5));
 break;
 }
 }
 if(!$moduleNamespace) {
 showLogError("Không tìm thấy namespace trong file module " . $options['module'] . '.php');
 return false;
 }
 if(!$moduleClassName) {
 showLogError("Không tìm thấy module class name trong file module " . $options['module'] . '.php');
 return false;
 }
 return $moduleClassName . "\\Model";
 }
 private function createModelFile($modelPath, $modelName, $tableName, $namespaceName, $isPrivate, $appId) {
 $controllerContent = "<?php\n\n";
 $controllerContent .= "namespace $namespaceName;\n";
 $controllerContent .= "use TCMS\Model;\n";
 $controllerContent .= "use TCMS\FieldModel;\n";
 $controllerContent .= "use FIELD_DATA_TYPE;\n\n";
 $controllerContent .= "class $modelName extends Model {\n";
 $controllerContent .= "\tpublic \$tableName = '$tableName';\n\n";
 $controllerContent .= "\tpublic \$timestamp = true;\n\n";
 $controllerContent .= "\tpublic function registerField() {\n";
 $controllerContent .= "\t\t\$this->addField('id', FIELD_DATA_TYPE::INTEGER);\n\n";
 $controllerContent .= "\t\t\$this->addField('name', FIELD_DATA_TYPE::STRING, function(FieldModel \$field) {\n\t\t\t\$field->required = true;\n\t\t});\n";
 $controllerContent .= "\t}\n\n";
 $controllerContent .= "}";
 $fp2 = fopen($modelPath, 'w');
 fwrite($fp2, $controllerContent);
 fclose($fp2);
 }
 private function formatAppNamespace($appId) {
 $arrItem = preg_split("/(_|-|\.| )+/", $appId);
 $namespaceName = "";
 foreach($arrItem as $v) {
 $a = strtolower($v);
 if($a !== "0" && !$a) {
 continue;
 }
 $namespaceName .= strtoupper(substr($a, 0, 1)) . substr($a, 1);
 }
 return $namespaceName;
 }
 private function formatModelName($options) {
 if(!isset($options['make:model'])) {
 return false;
 }
 $modelName = $options['make:model'];
 $modelName = preg_replace('/[^a-zA-Z0-9]/i', '', $modelName);
 $modelName = str_replace('.php', '', $modelName);
 $modelName = strtoupper(substr($modelName, 0, 1)) . substr($modelName, 1);
 if(strripos($modelName, "model") !== false) {
 $modelName = str_replace("model", "Model", $modelName);
 }
 if(strripos($modelName, "Model") === false) {
 $modelName .= "Model";
 }
 return $modelName;
 }
 public function showHelpCreateModel() {
 drawLine();
 echo "Description:\n";
 showLogInfo("  Tự động tạo một model mới");
 echo "\nFormat:\n";
 echo "  make:model [model-name] [options]\n\n";
 echo "Required:\n";
 showHelpTextColor("[model-name]", "Tên model cần tạo. VD: UserModel");
 echo "\nOptions:\n";
 showHelpTextColor("-tb, --table", "Tên table trong database.\n");
 showHelpTextColor("-p, --private", "\tTạo private model.\n");
 showHelpTextColor("-m, --module", "Tạo module model, truyền cả area module vào. VD: admin\product.\n");
 showHelpTextColor("-pm, --p-module", "Tạo module model, với module là private, truyền cả area module vào. VD: admin\product.\n");
 showHelpTextColor("-e, --extension", "Tạo extension model.\n");
 showHelpTextColor("-pe, --p-extension", "Tạo extension model, với extension là private.\n");
 drawLine();
 }
 public function showHelpRemoveModel() {
 drawLine();
 echo "Description:\n";
 showLogInfo("  Xóa model");
 echo "\nFormat:\n";
 echo "  remove:model [model-path]\n\n";
 echo "Required:\n";
 showHelpTextColor("[model-path]", "Đường dẫn đến model cần xóa. VD: models\\UserModel");
 drawLine();
 }
 public function removeModel($options) {
 if(empty($options['an-remove-model'])) {
 showLogError("Vui lòng nhập đường dẫn đến model cần xóa.");
 exit(1);
 }
 if(empty($options['app'])) {
 showLogError("Không tìm thấy app.");
 exit(1);
 }
 $options['an-remove-model'] = str_replace("/", DIRECTORY_SEPARATOR, $options['an-remove-model']);
 $modelPath = ROOT_PATH . $options['an-remove-model'];
 if(substr($modelPath, strlen($modelPath) - 4) != ".php") {
 $modelPath .= ".php";
 }
 if(!file_exists($modelPath)) {
 showLogError("Không tìm thấy model $modelPath");
 exit(1);
 }
 define("APP_ID", $options['app']);
 define("APP_PATH", ROOT_PATH . 'apps' . DIRECTORY_SEPARATOR . APP_ID . DIRECTORY_SEPARATOR);
 define("CONFIG_PATH", APP_PATH . 'config' . DIRECTORY_SEPARATOR);
 define("MODULE_PATH", ROOT_PATH . 'modules' . DIRECTORY_SEPARATOR);
 define("PUBLISH_PATH_2", true);
 define("REMOVE_MODEL_CMD", true);
 include_once(LIB_PATH . 'global.class.php');
 include_once(LIB_PATH . 'modules' . DIRECTORY_SEPARATOR . 'TCmsModule.php');
 include_once(LIB_PATH . 'models' . DIRECTORY_SEPARATOR . 'TCmsModel.php');
 include_once(LIB_PATH . 'extensions' . DIRECTORY_SEPARATOR . 'TCmsExtension.php');
 include_once(APP_PATH . 'bootstrap.php');
 $appBootstrap = new \AppBootstrap();
 $appBootstrap->boot();
 $moduleConfigs = $this->getModuleConfigs();
 foreach ($moduleConfigs as $mmmmName => $moduleConfig) {
 $areaKey = $moduleConfig['area'];
 if(isset($moduleConfig['nat_name'])) {
 $moduleName = $moduleConfig['nat_name'];
 }
else {
 $moduleName = $mmmmName;
 }
 $m = $this->includeAndNewModule($moduleName, $moduleConfig);
 $m->registerComponent();
 }
 $extensions = $this->getExtensionConfigs();
 $filePaths = [];
 foreach($extensions as $area => $aextensions) {
 foreach($aextensions as $k => $exts) {
 foreach($exts as $lastKey => $ext) {
 if(is_string($ext)) {
 $enamespace = $ext;
 $filePath = ROOT_PATH . 'extensions' . DIRECTORY_SEPARATOR . $lastKey . DIRECTORY_SEPARATOR . $lastKey . '.php';
 }
 else {
 if(empty($ext['namespace'])) continue;
 $enamespace = $ext['namespace'];
 if(isset($ext['path'])) {
 $filePath = $ext['path'];
 }
 else {
 if(isset($ext['private'])) {
 $filePath = APP_PATH . 'extensions' . DIRECTORY_SEPARATOR . $lastKey . DIRECTORY_SEPARATOR . $lastKey . '.php';
 }
 else {
 $filePath = ROOT_PATH . 'extensions' . DIRECTORY_SEPARATOR . $lastKey . DIRECTORY_SEPARATOR . $lastKey . '.php';
 }
 }
 }
 if(isset($filePaths[$filePath])) {
 continue;
 }
 $filePaths[$filePath] = true;
 if(file_exists($filePath)) {
 include($filePath);
 try {
 $extCls = new $enamespace();
 }
catch(\Exception $ex) {
 }
 }
 }
 }
 }
 foreach(\GlobalVars::$models as $k => $m) {
 if($m[1] == $modelPath) {
 showLogError("Model ". $k ." đã được sử dụng tại " . $m[2]);
 exit(1);
 }
 }
 exit(2);
 }
 private function includeAndNewModule($moduleName, $moduleConfig) {
 if(isset($moduleConfig['path'])) {
 $moduleFilePath = $moduleConfig['path'] . $moduleName . DIRECTORY_SEPARATOR . $moduleName . '.php';
 }
 else {
 $areaPath = $moduleConfig['area'] == '*' ? 'all' : $moduleConfig['area'];
 if (empty($moduleConfig['private'])) {
 $moduleFilePath = MODULE_PATH . $areaPath . DIRECTORY_SEPARATOR . $moduleName . DIRECTORY_SEPARATOR . $moduleName . '.php';
 }
 else {
 $moduleFilePath = APP_PATH . 'modules' . DIRECTORY_SEPARATOR . $areaPath . DIRECTORY_SEPARATOR . $moduleName . DIRECTORY_SEPARATOR . $moduleName . '.php';
 }
 }
 if (!file_exists($moduleFilePath)) {
 return false;
 }
 include_once($moduleFilePath);
 $moduleCls = "\\" . $moduleConfig['namespace'];
 return new $moduleCls();
 }
 private function getExtensionConfigs() {
 $areaCfg = include(CONFIG_PATH . "app.php");
 $_areas = $areaCfg['areas'];
 $extensionConfigs = [];
 $tIndex = 0;
 foreach($_areas as $a => $v) {
 if(file_exists(CONFIG_PATH . $a . ".extension.php")) $extensionConfigs[$a] = include(CONFIG_PATH . $a . ".extension.php");
 }
 return $extensionConfigs;
 }
 private function getModuleConfigs() {
 $areaCfg = include(CONFIG_PATH . "app.php");
 $_areas = $areaCfg['areas'];
 $moduleConfigs = [];
 $tIndex = 0;
 foreach($_areas as $a => $v) {
 if(!file_exists(CONFIG_PATH . $a . ".module.php")) continue;
 $modules = include(CONFIG_PATH . $a . ".module.php");
 foreach($modules as $k => $m) {
 if(isset($moduleConfigs[$k])) {
 $mct = $moduleConfigs[$k];
 if($mct['area'] != $a) {
 $m['area'] = $a;
 $m['nat_name'] = $k;
 $moduleConfigs[$k . '-' . (++$tIndex)] = $m;
 continue;
 }
 }
 $m['area'] = $a;
 $moduleConfigs[$k] = $m;
 }
 }
 return $moduleConfigs;
 }
 }
 