diff --git a/app/modules/tag/manifest.json b/app/modules/tag/manifest.json index 974f984..456f81c 100644 --- a/app/modules/tag/manifest.json +++ b/app/modules/tag/manifest.json @@ -5,7 +5,6 @@ "slug": "tag", "description": "Tags module", "app_module_path": "{APP}/modules/{slug}", - "kernel_module_path": "{KERNEL_APP_MODULES}/{slug}", "module_class": "app\\modules\\tag\\TagModule", "module_class_file": "{APP}/modules/tag/TagModule.php", "routs": "routs/tag.php" diff --git a/bootstrap.php b/bootstrap.php index afca5a1..da9207e 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -33,6 +33,7 @@ function getConst($text): array|false|string ]; $str = $text; + foreach($constStr as $key => $value) { $str = str_replace($key, $value, $str); diff --git a/kernel/console/controllers/ModuleController.php b/kernel/console/controllers/ModuleController.php index 67417d7..539b687 100644 --- a/kernel/console/controllers/ModuleController.php +++ b/kernel/console/controllers/ModuleController.php @@ -22,31 +22,11 @@ class ModuleController extends ConsoleController throw new \Exception('Missing module path "--path" specified'); } - $zip = new ZipArchive; - $tmpModuleDir = md5(time()); - $res = $zip->open(ROOT_DIR . $this->argv['path']); - if ($res === TRUE) { - $tmpModuleDirFull = RESOURCES_DIR . '/tmp/ad/' . $tmpModuleDir . "/"; - $zip->extractTo($tmpModuleDirFull); - $zip->close(); - $this->out->r('Архив распакован', 'green'); + if (file_exists(ROOT_DIR . $this->argv['path'])) { + $moduleService = new ModuleService(); + $moduleService->installModule($this->argv['path']); } else { - $this->out->r('Message: Ошибка чтения архива', 'red'); - } - - if (file_exists($tmpModuleDirFull . "/app/manifest.json")){ - $manifestJson = getConst(file_get_contents($tmpModuleDirFull . "/app/manifest.json")); - $manifest = Manifest::getWithVars($manifestJson); - $this->out->r('manifest.json инициализирован', 'green'); - - $fileHelper = new Files(); - $fileHelper->copy_folder($tmpModuleDirFull . '/app', $manifest['app_module_path']); - $fileHelper->copy_folder($tmpModuleDirFull . '/kernel', $manifest['kernel_module_path']); - - $this->out->r("Удаляем временные файлы", 'green'); - $fileHelper->recursiveRemoveDir($tmpModuleDirFull); - - $this->out->r("Модуль " . $manifest['name'] . " установлен", 'green'); + $this->out->r("Модуль не найден", 'red'); } } @@ -61,25 +41,15 @@ class ModuleController extends ConsoleController if (file_exists(ROOT_DIR . $this->argv['path'])) { $moduleService = new ModuleService(); - $moduleInfo = $moduleService->getModuleInfo(APP_DIR . '/modules/' . basename($this->argv['path'])); - - if ($moduleService->isActive($moduleInfo['slug'])) { - $moduleService->setActiveModule($moduleInfo['slug']); - } - - $fileHelper = new Files(); - if (file_exists(APP_DIR . '/modules/' . $moduleInfo['slug'])) { - $fileHelper->recursiveRemoveDir(APP_DIR . '/modules/'. $moduleInfo['slug']); - } - if (file_exists(KERNEL_APP_MODULES_DIR . '/' . $moduleInfo['slug'])) { - $fileHelper->recursiveRemoveDir(KERNEL_APP_MODULES_DIR . '/' . $moduleInfo['slug']); - } - $this->out->r("Модуль удален", 'green'); + $moduleService->uninstallModule($this->argv['path']); } else { $this->out->r("Модуль не найден", 'red'); } } + /** + * @throws \Exception + */ public function actionPackModule(): void { if (!isset($this->argv['path'])) { @@ -87,22 +57,24 @@ class ModuleController extends ConsoleController } if (file_exists(ROOT_DIR . $this->argv['path'])) { - $moduleName = basename($this->argv['path']); - - $tmpModuleDirFull = RESOURCES_DIR . '/tmp/ad/' . $moduleName . "/"; - - $fileHelper = new Files(); - $fileHelper->copy_folder(APP_DIR . '/modules/' . $moduleName, $tmpModuleDirFull . 'app/'); - $fileHelper->copy_folder(KERNEL_APP_MODULES_DIR . '/' . $moduleName, $tmpModuleDirFull . 'kernel/'); - - $this->out->r("Модуль собран во временную папку", 'green'); - - $fileHelper->pack($tmpModuleDirFull, RESOURCES_DIR . '/tmp/modules/' . $moduleName . '.itguild'); - - $this->out->r("Архив создан", 'green'); - $fileHelper->recursiveRemoveDir($tmpModuleDirFull); - $this->out->r("Временная папка удалена", 'green'); + $moduleService = new ModuleService(); + $moduleService->packModule($this->argv['path']); + } else { + $this->out->r("Модуль не найден", 'red'); + } + } + /** + * @throws \Exception + */ + public function actionUpdateModule(): void + { + if (!isset($this->argv['path'])) { + throw new \Exception('Missing module path "--path" specified'); + } + if (file_exists(ROOT_DIR . $this->argv['path'])) { + $moduleService = new ModuleService(); + $moduleService->updateModule($this->argv['path']); } } diff --git a/kernel/console/routs/cli.php b/kernel/console/routs/cli.php index ba24d43..537a724 100644 --- a/kernel/console/routs/cli.php +++ b/kernel/console/routs/cli.php @@ -25,5 +25,6 @@ App::$collector->group(["prefix" => "module"], callback: function (RouteCollecto App::$collector->console('install', [\kernel\console\controllers\ModuleController::class, 'actionInstallModule']); App::$collector->console('uninstall', [\kernel\console\controllers\ModuleController::class, 'actionUninstallModule']); App::$collector->console('pack', [\kernel\console\controllers\ModuleController::class, 'actionPackModule']); + App::$collector->console('update', [\kernel\console\controllers\ModuleController::class, 'actionUpdateModule']); }); diff --git a/kernel/controllers/ModuleController.php b/kernel/controllers/ModuleController.php index e8524e8..458671e 100644 --- a/kernel/controllers/ModuleController.php +++ b/kernel/controllers/ModuleController.php @@ -24,10 +24,10 @@ class ModuleController extends AdminController public function actionIndex(): void { - $admin_theme_paths = Option::where("key", "module_paths")->first(); + $module_paths = Option::where("key", "module_paths")->first(); $dirs = []; - if ($admin_theme_paths){ - $path = json_decode($admin_theme_paths->value); + if ($module_paths){ + $path = json_decode($module_paths->value); foreach ($path->paths as $p){ $dirs[] = getConst($p); } @@ -51,7 +51,7 @@ class ModuleController extends AdminController public function actionActivate(): void { $request = new Request(); - $this->moduleService->setActiveModule($request->get("slug")); + $this->moduleService->toggleModule($request->get("slug")); $mod_info = $this->moduleService->getModuleInfoBySlug($request->get('slug')); $this->cgView->render("view.php", ['data' => $mod_info]); diff --git a/kernel/modules/post/manifest.json b/kernel/modules/post/manifest.json index fb2c610..51e2b4a 100644 --- a/kernel/modules/post/manifest.json +++ b/kernel/modules/post/manifest.json @@ -7,5 +7,6 @@ "module_class": "kernel\\modules\\post\\PostModule", "module_class_file": "{KERNEL_MODULES}/post/PostModule.php", "routs": "routs/post.php", - "migration_path": "migrations" + "migration_path": "migrations", + "dependence": "user" } \ No newline at end of file diff --git a/kernel/services/ModuleService.php b/kernel/services/ModuleService.php index f787be5..24b602c 100644 --- a/kernel/services/ModuleService.php +++ b/kernel/services/ModuleService.php @@ -4,8 +4,10 @@ namespace kernel\services; use DirectoryIterator; use kernel\helpers\Debug; +use kernel\helpers\Files; use kernel\helpers\Manifest; use kernel\models\Option; +use ZipArchive; class ModuleService { @@ -44,20 +46,32 @@ class ModuleService return false; } - public function setActiveModule(string $module): void + /** + * @throws \Exception + */ + public function toggleModule(string $module): void { - $active_modules = Option::where("key", "active_modules")->first(); - $path = json_decode($active_modules->value); - if (in_array($module, $path->modules)) { - unset($path->modules[array_search($module, $path->modules)]); - $path->modules = array_values($path->modules); + $active_modules_info = Option::where("key", "active_modules")->first(); + $active_modules = json_decode($active_modules_info->value); + if (in_array($module, $active_modules->modules)) { + unset($active_modules->modules[array_search($module, $active_modules->modules)]); + $active_modules->modules = array_values($active_modules->modules); $this->runDeactivateScript($this->getModuleInfoBySlug($module)); } else { - $path->modules[] = $module; + $module_info = $this->getModuleInfoBySlug($module); + if (isset($module_info['dependence'])) { + $dependence_array = explode(';', $module_info['dependence']); + foreach ($dependence_array as $depend) { + if (!in_array($depend, $active_modules->modules)) { + throw new \Exception("first activate the $depend module"); + } + } + } + $active_modules->modules[] = $module; $this->runInitScript($this->getModuleInfoBySlug($module)); } - $active_modules->value = json_encode($path, JSON_UNESCAPED_UNICODE); - $active_modules->save(); + $active_modules_info->value = json_encode($active_modules, JSON_UNESCAPED_UNICODE); + $active_modules_info->save(); } public function getModuleDir(string $slug) @@ -154,4 +168,126 @@ class ModuleService return $migrationsPaths; } + /** + * @throws \Exception + */ + public function installModule(string $path): void + { + $zip = new ZipArchive; + $tmpModuleDir = md5(time()); + $res = $zip->open(ROOT_DIR . $path); + if ($res === TRUE) { + $tmpModuleDirFull = RESOURCES_DIR . '/tmp/ad/' . $tmpModuleDir . "/"; + $zip->extractTo($tmpModuleDirFull); + $zip->close(); +// $out->out->r('Архив распакован', 'green'); +// } else { +// $this->out->r('Message: Ошибка чтения архива', 'red'); + } else { + $zip->close(); + throw new \Exception("unable to open zip archive"); + } + + if (!file_exists($tmpModuleDirFull . "/app/manifest.json")) { + throw new \Exception('manifest.json not found'); + } + + $manifestJson = getConst(file_get_contents($tmpModuleDirFull . "/app/manifest.json")); + $manifest = Manifest::getWithVars($manifestJson); +// $this->out->r('manifest.json инициализирован', 'green'); + + $fileHelper = new Files(); + $fileHelper->copy_folder($tmpModuleDirFull . '/app', $manifest['app_module_path']); + if (isset($manifest['kernel_module_path'])) { + $fileHelper->copy_folder($tmpModuleDirFull . '/kernel', $manifest['kernel_module_path']); + } else { + $fileHelper->copy_folder($tmpModuleDirFull . '/kernel', KERNEL_APP_MODULES_DIR . '/' . $manifest['slug']); + } + +// $this->out->r("Удаляем временные файлы", 'green'); + $fileHelper->recursiveRemoveDir($tmpModuleDirFull); + var_dump($tmpModuleDirFull); + +// $this->out->r("Модуль " . $manifest['name'] . " установлен", 'green'); + } + + public function uninstallModule(string $path): void + { + $moduleInfo = $this->getModuleInfo(APP_DIR . '/modules/' . basename($path)); + + if ($this->isActive($moduleInfo['slug'])) { + $this->toggleModule($moduleInfo['slug']); + } + + $fileHelper = new Files(); + if (file_exists(APP_DIR . '/modules/' . $moduleInfo['slug'])) { + $fileHelper->recursiveRemoveDir(APP_DIR . '/modules/'. $moduleInfo['slug']); + } + if (file_exists(KERNEL_APP_MODULES_DIR . '/' . $moduleInfo['slug'])) { + $fileHelper->recursiveRemoveDir(KERNEL_APP_MODULES_DIR . '/' . $moduleInfo['slug']); + } + } + + public function packModule(string $path): void + { + $moduleName = basename($path); + + $tmpModuleDirFull = RESOURCES_DIR . '/tmp/ad/' . $moduleName . "/"; + + $fileHelper = new Files(); + $fileHelper->copy_folder(APP_DIR . '/modules/' . $moduleName, $tmpModuleDirFull . 'app/'); + $fileHelper->copy_folder(KERNEL_APP_MODULES_DIR . '/' . $moduleName, $tmpModuleDirFull . 'kernel/'); + +// $this->out->r("Модуль собран во временную папку", 'green'); + + $fileHelper->pack($tmpModuleDirFull, RESOURCES_DIR . '/tmp/modules/' . $moduleName . '.itguild'); + +// $this->out->r("Архив создан", 'green'); + $fileHelper->recursiveRemoveDir($tmpModuleDirFull); + +// $this->out->r("Временная папка удалена", 'green'); + } + + /** + * @throws \Exception + */ + public function updateModule(string $path): void + { + $zip = new ZipArchive; + $tmpModuleDir = md5(time()); + $res = $zip->open(ROOT_DIR . $path); + if ($res === TRUE) { + $tmpModuleDirFull = RESOURCES_DIR . '/tmp/ad/' . $tmpModuleDir . "/"; + $zip->extractTo($tmpModuleDirFull); + $zip->close(); +// $out->out->r('Архив распакован', 'green'); +// } else { +// $this->out->r('Message: Ошибка чтения архива', 'red'); + } else { + $zip->close(); + throw new \Exception("unable to open zip archive"); + } + + if (!file_exists($tmpModuleDirFull . "/app/manifest.json")) { + throw new \Exception('manifest.json not found'); + } + + $manifestJson = getConst(file_get_contents($tmpModuleDirFull . "/app/manifest.json")); + $manifest = Manifest::getWithVars($manifestJson); +// $this->out->r('manifest.json инициализирован', 'green'); + + $fileHelper = new Files(); + if (isset($manifest['kernel_module_path'])) { + $fileHelper->copy_folder($tmpModuleDirFull . '/kernel', $manifest['kernel_module_path']); + } else { + $fileHelper->copy_folder($tmpModuleDirFull . '/kernel', KERNEL_APP_MODULES_DIR . '/' . $manifest['slug']); + } + +// $this->out->r("Удаляем временные файлы", 'green'); + $fileHelper->recursiveRemoveDir($tmpModuleDirFull); + +// $this->out->r("Модуль " . $manifest['name'] . " установлен", 'green'); + + } + } \ No newline at end of file