From 4ff9fa9ad35d5c45464d1ad367b8e8f5324c679a Mon Sep 17 00:00:00 2001 From: stasbilay02 Date: Wed, 18 Dec 2024 12:46:57 +0300 Subject: [PATCH] kernel update --- .env.example | 1 - app/modules/module_shop/ModuleShopModule.php | 5 + .../controllers/KernelShopController.php | 84 ++++++++++++++++ .../controllers/KernelShopRestController.php | 27 +++++ .../controllers/ModuleShopController.php | 16 ++- .../controllers/ModuleShopRestController.php | 2 +- ..._10_15_135454_create_module_shop_table.php | 1 + app/modules/module_shop/models/ModuleShop.php | 4 +- .../models/forms/CreateModuleShopForm.php | 26 +++-- app/modules/module_shop/routs/ms.php | 28 ++++-- .../services/ModuleShopService.php | 2 + app/modules/module_shop/views/form.php | 2 +- app/modules/module_shop/views/index.php | 5 +- app/modules/module_shop/views/kernel/form.php | 53 ++++++++++ bootstrap.php | 3 +- bootstrap/secure.php | 2 +- composer.json | 4 +- kernel/CgRouteCollector.php | 12 ++- kernel/CgView.php | 33 ++++++- kernel/admin_themes/default/layout/main.php | 5 +- kernel/console/Out.php | 19 ++++ .../console/controllers/KernelController.php | 16 ++- kernel/console/controllers/MainController.php | 23 +++++ .../console/controllers/ModuleController.php | 29 ++++++ .../console/migrations/stubs/migration.stub | 1 + kernel/console/routs/cli.php | 87 +++++++++++++--- kernel/controllers/ModuleController.php | 1 + kernel/manifest.json | 8 ++ .../2024_09_23_125545_create_menu_table.php | 1 + .../views/login_at_module_shop.php | 2 +- .../2024_09_23_125716_create_option_table.php | 1 + kernel/modules/post/PostModule.php | 6 ++ .../2024_09_23_130017_create_post_table.php | 2 + kernel/modules/post/views/index.php | 10 +- kernel/modules/post/views/view.php | 3 - .../controllers/SecureRestController.php | 18 ++-- ..._12_09_081420_create_secret_code_table.php | 2 + .../2024_09_23_125827_create_user_table.php | 2 + kernel/services/ConsoleService.php | 21 ++++ kernel/services/MigrationService.php | 21 ++++ kernel/services/ModuleService.php | 70 +++++++++++-- kernel/services/TokenService.php | 10 +- .../controllers/app_controller_template | 8 ++ .../controllers/kernel_controller_template | 98 +++++++++++++++++++ kernel/templates/manifests/manifest_template | 11 +++ .../models/forms/create_form_template | 25 +++++ kernel/templates/models/model_template | 47 +++++++++ .../module_files/app_module_file_template | 8 ++ .../module_files/kernel_module_file_template | 31 ++++++ kernel/templates/routs/app_routs_template | 2 + kernel/templates/routs/kernel_routs_template | 20 ++++ kernel/templates/services/service_template | 39 ++++++++ kernel/templates/views/form_template | 55 +++++++++++ kernel/templates/views/index_template | 68 +++++++++++++ kernel/templates/views/view_template | 25 +++++ kernel/views/module/index.php | 2 + 56 files changed, 1023 insertions(+), 84 deletions(-) create mode 100644 app/modules/module_shop/controllers/KernelShopController.php create mode 100644 app/modules/module_shop/controllers/KernelShopRestController.php create mode 100644 app/modules/module_shop/views/kernel/form.php create mode 100644 kernel/manifest.json create mode 100644 kernel/services/ConsoleService.php create mode 100644 kernel/templates/controllers/app_controller_template create mode 100644 kernel/templates/controllers/kernel_controller_template create mode 100644 kernel/templates/manifests/manifest_template create mode 100644 kernel/templates/models/forms/create_form_template create mode 100644 kernel/templates/models/model_template create mode 100644 kernel/templates/module_files/app_module_file_template create mode 100644 kernel/templates/module_files/kernel_module_file_template create mode 100644 kernel/templates/routs/app_routs_template create mode 100644 kernel/templates/routs/kernel_routs_template create mode 100644 kernel/templates/services/service_template create mode 100644 kernel/templates/views/form_template create mode 100644 kernel/templates/views/index_template create mode 100644 kernel/templates/views/view_template diff --git a/.env.example b/.env.example index 3fd1ecb..ffddf4b 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,6 @@ DB_USER={db_user} DB_DRIVER=mysql DB_PASSWORD={db_password} DB_NAME={db_name} - DB_CHARSET=utf8mb4 DB_COLLATION=utf8mb4_unicode_ci DB_PREFIX='' diff --git a/app/modules/module_shop/ModuleShopModule.php b/app/modules/module_shop/ModuleShopModule.php index a5c6be8..908e9ec 100644 --- a/app/modules/module_shop/ModuleShopModule.php +++ b/app/modules/module_shop/ModuleShopModule.php @@ -30,8 +30,13 @@ class ModuleShopModule extends Module ]); } + /** + * @throws \Exception + */ public function deactivate(): void { $this->menuService->removeItemBySlug("module_shop"); + $this->migrationService->rollbackAtPath("{APP}/modules/module_shop/migrations"); + } } \ No newline at end of file diff --git a/app/modules/module_shop/controllers/KernelShopController.php b/app/modules/module_shop/controllers/KernelShopController.php new file mode 100644 index 0000000..6142226 --- /dev/null +++ b/app/modules/module_shop/controllers/KernelShopController.php @@ -0,0 +1,84 @@ +cgView->viewPath = APP_DIR . "/modules/module_shop/views/kernel/"; + $this->moduleShopService = new ModuleShopService(); + $this->files = new Files(); + } + + public function actionCreate(): void + { + $this->cgView->render("form.php"); + } + + /** + * @throws \Exception + */ + #[NoReturn] public function actionAdd(): void + { + $moduleShopForm = new CreateModuleShopForm(); + $moduleShopForm->load($_REQUEST); + + if (isset($_FILES['path_to_archive']) && $_FILES['path_to_archive']['error'] === UPLOAD_ERR_OK) { + $file = new FileUpload($_FILES['path_to_archive'], ['zip', 'rar', 'igk']); + $file->upload(); + $moduleShopForm->setItem('path_to_archive', $file->getUploadFile()); + } + + $tmpKernelDir = md5(time()); + $zip = new ZipArchive; + $res = $zip->open(ROOT_DIR . $moduleShopForm->getItem('path_to_archive')); + if ($res === TRUE) { + if (!is_dir(RESOURCES_DIR . '/tmp/ms/')) { + mkdir(RESOURCES_DIR . '/tmp/ms/'); + } + $tmpModuleShopDirFull = RESOURCES_DIR . '/tmp/ms/' . $tmpKernelDir . "/"; + $zip->extractTo($tmpModuleShopDirFull); + $zip->close(); + + if (file_exists($tmpModuleShopDirFull . "kernel/manifest.json")){ + $kernelInfo = $this->moduleShopService->getModuleInfo($tmpModuleShopDirFull . "kernel"); + $moduleShopForm->load($kernelInfo); + } + else { + throw new \Exception("Manifest.json file not found"); + } + $this->files->recursiveRemoveDir($tmpModuleShopDirFull); + + } + else { + throw new \Exception("zip not found"); + } + + if ($moduleShopForm->validate()) { + $kernel = $this->moduleShopService->create($moduleShopForm); + if ($kernel) { + Flash::setMessage("success", "Ядро добавлено."); + $this->redirect("/admin/module_shop/view/" . $kernel->id); + } + } + Flash::setMessage("error", "Ошибка добавления ядра:
" . $moduleShopForm->getErrorsStr()); + $this->redirect("/admin/module_shop/kernel/create"); + } +} \ No newline at end of file diff --git a/app/modules/module_shop/controllers/KernelShopRestController.php b/app/modules/module_shop/controllers/KernelShopRestController.php new file mode 100644 index 0000000..9ce085f --- /dev/null +++ b/app/modules/module_shop/controllers/KernelShopRestController.php @@ -0,0 +1,27 @@ +model = new ModuleShop(); + } + + #[NoReturn] public function actionUpdate($id): void + { + $model = $this->model->where("id", $id)->first(); + $model->installations++; + $model->save(); + $this->renderApi($model->toArray()); + } + +} \ No newline at end of file diff --git a/app/modules/module_shop/controllers/ModuleShopController.php b/app/modules/module_shop/controllers/ModuleShopController.php index 6316bec..02d48aa 100644 --- a/app/modules/module_shop/controllers/ModuleShopController.php +++ b/app/modules/module_shop/controllers/ModuleShopController.php @@ -11,18 +11,21 @@ use kernel\app_modules\tag\services\TagService; use kernel\FileUpload; use kernel\Flash; use kernel\helpers\Debug; +use kernel\helpers\Files; use kernel\services\ModuleService; use ZipArchive; class ModuleShopController extends AdminController { protected ModuleShopService $moduleShopService; + protected Files $files; protected function init(): void { parent::init(); $this->cgView->viewPath = APP_DIR . "/modules/module_shop/views/"; $this->moduleShopService = new ModuleShopService(); + $this->files = new Files(); } public function actionCreate(): void @@ -44,14 +47,14 @@ class ModuleShopController extends AdminController $moduleShopForm->setItem('path_to_archive', $file->getUploadFile()); } - $tmpThemeDir = md5(time()); + $tmpModuleDir = md5(time()); $zip = new ZipArchive; $res = $zip->open(ROOT_DIR . $moduleShopForm->getItem('path_to_archive')); if ($res === TRUE) { if (!is_dir(RESOURCES_DIR . '/tmp/ms/')) { mkdir(RESOURCES_DIR . '/tmp/ms/'); } - $tmpModuleShopDirFull = RESOURCES_DIR . '/tmp/ms/' . $tmpThemeDir . "/"; + $tmpModuleShopDirFull = RESOURCES_DIR . '/tmp/ms/' . $tmpModuleDir . "/"; $zip->extractTo($tmpModuleShopDirFull); $zip->close(); @@ -62,6 +65,8 @@ class ModuleShopController extends AdminController else { throw new \Exception("Manifest.json file not found"); } + $this->files->recursiveRemoveDir($tmpModuleShopDirFull); + } else { throw new \Exception("zip not found"); @@ -71,11 +76,11 @@ class ModuleShopController extends AdminController $module = $this->moduleShopService->create($moduleShopForm); if ($module) { Flash::setMessage("success", "Модуль " . $moduleShopForm->getItem("name") . " добавлен."); - $this->redirect("/admin/module_shop/" . $module->id); + $this->redirect("/admin/module_shop/view/" . $module->id); } } Flash::setMessage("error", "Ошибка добавления модуля:
" . $moduleShopForm->getErrorsStr()); - $this->redirect("/admin/module_shop/create"); + $this->redirect("/admin/module_shop/module/create"); } public function actionIndex(int $page_number = 1): void @@ -101,6 +106,9 @@ class ModuleShopController extends AdminController throw new \Exception("The module not found"); } $name = $module->name; + $dir = $module->path_to_archive; + $this->files->recursiveRemoveDir(ROOT_DIR . dirname($dir, 2)); + $module->delete(); Flash::setMessage("success", "Модуль " . $name . " удален."); diff --git a/app/modules/module_shop/controllers/ModuleShopRestController.php b/app/modules/module_shop/controllers/ModuleShopRestController.php index 19bee88..8d59687 100644 --- a/app/modules/module_shop/controllers/ModuleShopRestController.php +++ b/app/modules/module_shop/controllers/ModuleShopRestController.php @@ -97,7 +97,7 @@ class ModuleShopRestController extends RestController $this->renderApi($res); } - public function actionInstall($id): void + #[NoReturn] public function actionInstall($id): void { $model = $this->model->where("id", $id)->first(); $model->installations++; diff --git a/app/modules/module_shop/migrations/2024_10_15_135454_create_module_shop_table.php b/app/modules/module_shop/migrations/2024_10_15_135454_create_module_shop_table.php index aaec4ab..8804886 100644 --- a/app/modules/module_shop/migrations/2024_10_15_135454_create_module_shop_table.php +++ b/app/modules/module_shop/migrations/2024_10_15_135454_create_module_shop_table.php @@ -14,6 +14,7 @@ return new class extends Migration { $table->increments('id'); $table->string("name", 255)->nullable(false); $table->string("slug", 255)->nullable(false); + $table->string("type", 255)->nullable(false); $table->text("description")->nullable(false); $table->string("version", 255)->nullable(false); $table->string("author", 255)->nullable(false); diff --git a/app/modules/module_shop/models/ModuleShop.php b/app/modules/module_shop/models/ModuleShop.php index 54b1a2e..17ce8b4 100644 --- a/app/modules/module_shop/models/ModuleShop.php +++ b/app/modules/module_shop/models/ModuleShop.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Model; * @property int $id * @property string $name * @property string $slug + * @property string $type * @property string $version * @property string $description * @property string $author @@ -24,7 +25,7 @@ class ModuleShop extends Model protected $table = "module_shop"; - protected $fillable = ['name', 'slug', 'version', 'description', 'author', 'status', 'dependence', 'installations', 'views']; + protected $fillable = ['name', 'slug', 'type', 'version', 'description', 'author', 'status', 'dependence', 'installations', 'views']; public static function labels(): array { @@ -35,6 +36,7 @@ class ModuleShop extends Model 'author' => 'Автор', 'status' => 'Статус', 'slug' => 'Slug', + 'type' => 'Тип', 'dependence' => 'Зависимости', 'installations' => 'Установки', 'views' => 'Просмотры', diff --git a/app/modules/module_shop/models/forms/CreateModuleShopForm.php b/app/modules/module_shop/models/forms/CreateModuleShopForm.php index 2271820..2c1d5db 100644 --- a/app/modules/module_shop/models/forms/CreateModuleShopForm.php +++ b/app/modules/module_shop/models/forms/CreateModuleShopForm.php @@ -8,14 +8,26 @@ class CreateModuleShopForm extends FormModel { public function rules(): array { +// return [ +// 'name' => 'required|min-str-len:3', +// 'version' => 'required', +// 'description' => 'required|min-str-len:10', +// 'author' => 'required', +// 'status' => 'required', +// 'slug' => 'required', +// 'type' => 'required', +// 'path_to_archive' => 'required', +// 'dependence' => '', +// ]; return [ - 'name' => 'required|min-str-len:3', - 'version' => 'required', - 'description' => 'required|min-str-len:10', - 'author' => 'required', - 'status' => 'required', - 'slug' => 'required', - 'path_to_archive' => 'required', + 'name' => '', + 'version' => '', + 'description' => '', + 'author' => '', + 'status' => '', + 'slug' => '', + 'type' => '', + 'path_to_archive' => '', 'dependence' => '', ]; } diff --git a/app/modules/module_shop/routs/ms.php b/app/modules/module_shop/routs/ms.php index 1d28a30..c97c2c9 100644 --- a/app/modules/module_shop/routs/ms.php +++ b/app/modules/module_shop/routs/ms.php @@ -6,24 +6,34 @@ use kernel\CgRouteCollector; App::$collector->filter('bearer', [\kernel\modules\secure\middlewares\BearerAuthMiddleware::class, "handler"]); App::$collector->group(["prefix" => "admin"], function (CgRouteCollector $router) { - App::$collector->group(["prefix" => "module_shop"], function (CgRouteCollector $router){ + App::$collector->group(["prefix" => "module_shop"], function (CgRouteCollector $router) { App::$collector->get('/', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionIndex']); App::$collector->get('/page/{page_number}', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionIndex']); - App::$collector->get('/create', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionCreate']); - App::$collector->post("/", [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionAdd']); - App::$collector->get('/{id}', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionView']); + App::$collector->get('/view/{id}', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionView']); App::$collector->any('/update/{id}', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionUpdate']); App::$collector->any("/edit/{id}", [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionEdit']); App::$collector->get('/delete/{id}', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionDelete']); App::$collector->get('/pack/{id}', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionPack']); + + App::$collector->group(["prefix" => "module"], function (CgRouteCollector $router) { + App::$collector->get('/create', [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionCreate']); + App::$collector->post("/", [\app\modules\module_shop\controllers\ModuleShopController::class, 'actionAdd']); + }); + App::$collector->group(["prefix" => "kernel"], function (CgRouteCollector $router) { + App::$collector->get('/create', [\app\modules\module_shop\controllers\KernelShopController::class, 'actionCreate']); + App::$collector->post("/", [\app\modules\module_shop\controllers\KernelShopController::class, 'actionAdd']); + }); }); }); -App::$collector->group(["prefix" => "api"], function (CgRouteCollector $router){ - App::$collector->group(['before' => 'bearer'], function (CgRouteCollector $router){ - App::$collector->group(["prefix" => "module_shop"], function (CgRouteCollector $router){ - App::$collector->get('/gb_slug', [\app\modules\module_shop\controllers\ModuleShopRestController::class, 'actionIndexGroupBySlug']); - App::$collector->get('/install/{id}', [\app\modules\module_shop\controllers\ModuleShopRestController::class, 'actionInstall']); +App::$collector->group(["prefix" => "api"], function (CgRouteCollector $router) { + App::$collector->group(['before' => 'bearer'], function (CgRouteCollector $router) { + App::$collector->group(["prefix" => "module_shop"], function (CgRouteCollector $router) { + App::$collector->get('/gb_slug', [\app\modules\module_shop\controllers\ModuleShopRestController::class, 'actionIndexGroupBySlug']); + App::$collector->get('/install/{id}', [\app\modules\module_shop\controllers\ModuleShopRestController::class, 'actionInstall']); + App::$collector->group(["prefix" => "kernel"], function (CgRouteCollector $router) { + App::$collector->get('/update/{id}', [\app\modules\module_shop\controllers\KernelShopRestController::class, 'actionUpdate']); + }); }); $router->rest("module_shop", [\app\modules\module_shop\controllers\ModuleShopRestController::class]); }); diff --git a/app/modules/module_shop/services/ModuleShopService.php b/app/modules/module_shop/services/ModuleShopService.php index bd34262..65efd90 100644 --- a/app/modules/module_shop/services/ModuleShopService.php +++ b/app/modules/module_shop/services/ModuleShopService.php @@ -23,6 +23,7 @@ class ModuleShopService extends ModuleService $model->path_to_archive = $form_model->getItem("path_to_archive"); $model->dependence = $form_model->getItem("dependence"); $model->slug = $form_model->getItem("slug"); + $model->type = $form_model->getItem("type"); if ($model->save()) { return $model; @@ -41,6 +42,7 @@ class ModuleShopService extends ModuleService $model->path_to_archive = $form_model->getItem("path_to_archive"); $model->dependence = $form_model->getItem("dependence"); $model->slug = $form_model->getItem("slug"); + $model->type = $form_model->getItem("type"); if ($model->save()) { return $model; diff --git a/app/modules/module_shop/views/form.php b/app/modules/module_shop/views/form.php index a5a6a20..a87d543 100644 --- a/app/modules/module_shop/views/form.php +++ b/app/modules/module_shop/views/form.php @@ -6,7 +6,7 @@ use app\modules\module_shop\models\ModuleShop; $form = new \itguild\forms\ActiveForm(); -$form->beginForm("/admin/module_shop", enctype: 'multipart/form-data'); +$form->beginForm("/admin/module_shop/module", enctype: 'multipart/form-data'); diff --git a/app/modules/module_shop/views/index.php b/app/modules/module_shop/views/index.php index c2898b3..21de1cb 100644 --- a/app/modules/module_shop/views/index.php +++ b/app/modules/module_shop/views/index.php @@ -24,8 +24,9 @@ $table->columns([ } ]); $table->beforePrint(function () { - return PrimaryBtn::create("Создать", "/admin/module_shop/create")->fetch(); - //return (new PrimaryBtn("Создать", "/admin/user/create"))->fetch(); + $btn = PrimaryBtn::create("Добавить модуль", "/admin/module_shop/module/create")->fetch(); + $btn .= PrimaryBtn::create("Добавить ядро", "/admin/module_shop/kernel/create")->fetch(); + return $btn; }); $table->addAction(ViewActionColumn::class); $table->addAction(DeleteActionColumn::class); diff --git a/app/modules/module_shop/views/kernel/form.php b/app/modules/module_shop/views/kernel/form.php new file mode 100644 index 0000000..183807b --- /dev/null +++ b/app/modules/module_shop/views/kernel/form.php @@ -0,0 +1,53 @@ +beginForm("/admin/module_shop/kernel", enctype: 'multipart/form-data'); + + + +$form->field(class: \itguild\forms\inputs\File::class, name: "path_to_archive", params: [ + 'class' => "form-control", + 'placeholder' => 'Путь к файлу модуля', + 'value' => $model->path_to_archive ?? '' +]) + ->setLabel("Путь к файлу модуля") + ->render(); + +$form->field(class: \itguild\forms\inputs\Select::class, name: "status", params: [ + 'class' => "form-control", + 'value' => $model->status ?? '' +]) + ->setLabel("Статус") + ->setOptions(ModuleShop::getStatus()) + ->render(); + +?> +
+
+ field(\itguild\forms\inputs\Button::class, name: "btn-submit", params: [ + 'class' => "btn btn-primary ", + 'value' => 'Отправить', + 'typeInput' => 'submit' + ]) + ->render(); + ?> +
+
+ field(\itguild\forms\inputs\Button::class, name: "btn-reset", params: [ + 'class' => "btn btn-warning", + 'value' => 'Сбросить', + 'typeInput' => 'reset' + ]) + ->render(); + ?> +
+
+endForm(); diff --git a/bootstrap.php b/bootstrap.php index 0a85d73..b9b36fc 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -13,7 +13,7 @@ const KERNEL_MODULES_DIR = __DIR__ . "/kernel/modules"; const KERNEL_ADMIN_THEMES_DIR = __DIR__ . "/kernel/admin_themes"; const CONSOLE_DIR = __DIR__ . "/kernel/console"; const RESOURCES_DIR = __DIR__ . "/resources"; - +const KERNEL_TEMPLATES_DIR = __DIR__ . "/kernel/templates"; const KERNEL_APP_MODULES_DIR = KERNEL_DIR . "/app_modules"; const APP_DIR = ROOT_DIR . "/app"; @@ -29,6 +29,7 @@ function getConst($text): array|false|string "{KERNEL}" => KERNEL_DIR, "{KERNEL_MODULES}" => KERNEL_MODULES_DIR, "{KERNEL_APP_MODULES}" => KERNEL_APP_MODULES_DIR, + "{KERNEL_TEMPLATES}" => KERNEL_TEMPLATES_DIR, "{CONSOLE}" => CONSOLE_DIR, "{APP}" => APP_DIR, ]; diff --git a/bootstrap/secure.php b/bootstrap/secure.php index 714beb3..a8baf09 100644 --- a/bootstrap/secure.php +++ b/bootstrap/secure.php @@ -2,7 +2,7 @@ $secure_config = [ 'web_auth_type' => 'email_code', // login_password, email_code - 'token_type' => 'crypt', // random_bytes, md5, crypt, hash, JWT + 'token_type' => 'hash', // random_bytes, md5, crypt, hash, JWT 'token_expired_time' => "+30 days", // +1 day ]; diff --git a/composer.json b/composer.json index ecf8197..84a938a 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,9 @@ "firebase/php-jwt": "^6.10", "k-adam/env-editor": "^2.0", "guzzlehttp/guzzle": "^7.9", - "phpmailer/phpmailer": "^6.9" + "phpmailer/phpmailer": "^6.9", + "zircote/swagger-php": "^4.11", + "doctrine/annotations": "^2.0" }, "autoload": { "psr-4": { diff --git a/kernel/CgRouteCollector.php b/kernel/CgRouteCollector.php index 6c3b6d5..f7bbd49 100644 --- a/kernel/CgRouteCollector.php +++ b/kernel/CgRouteCollector.php @@ -46,8 +46,16 @@ class CgRouteCollector extends RouteCollector //TODO } - public function console($route, $handler, array $filters = []): void + /** + * @param $route + * @param $handler + * @param array $filters + * @param array $additionalInfo + * @return void + */ + public function console($route, $handler, array $filters = [], array $additionalInfo = []): void { - $this->addRoute(Route::GET, $route, $handler, $filters); + $additionalInfo['type'] = "console"; + $this->addRoute(Route::GET, $route, $handler, $filters, $additionalInfo); } } \ No newline at end of file diff --git a/kernel/CgView.php b/kernel/CgView.php index 792c540..5934f82 100644 --- a/kernel/CgView.php +++ b/kernel/CgView.php @@ -10,6 +10,8 @@ class CgView public array $varToLayout = []; public bool|string $layout = false; + protected array $metaArr = []; + public function __construct() { @@ -34,14 +36,37 @@ class CgView $this->varToLayout[$key] = $value; } - private function createContent(string $view, array $data = []): false|string + public function setTitle(string $title): void + { + $this->addVarToLayout('title', $title); + } + + public function setMeta(array $meta): void + { + foreach ($meta as $key => $value){ + $this->metaArr[$key] = $value; + } + } + + public function getMeta(): string + { + $meta = ""; + foreach ($this->metaArr as $key => $value){ + $meta .= ""; + } + + return $meta; + } + + private function createContent(string $viewFile, array $data = []): false|string { ob_start(); + $view = $this; foreach ($data as $key => $datum) { ${"$key"} = $datum; } - include($this->viewPath . $view); + include($this->viewPath . $viewFile); $content = ob_get_contents(); ob_end_clean(); @@ -50,6 +75,10 @@ class CgView $file_content = $content; + if (!isset($title)){ + $title = "No Title"; + } + $layoutPath = $this->viewPath; if ($this->layout) { diff --git a/kernel/admin_themes/default/layout/main.php b/kernel/admin_themes/default/layout/main.php index 5864fb1..db00106 100644 --- a/kernel/admin_themes/default/layout/main.php +++ b/kernel/admin_themes/default/layout/main.php @@ -2,15 +2,18 @@ /** * @var $content * @var string $resources + * @var string $title + * @var \kernel\CgView $view */ \Josantonius\Session\Facades\Session::start(); ?> - Sidebar 01 + <?= $title ?> + getMeta() ?> diff --git a/kernel/console/Out.php b/kernel/console/Out.php index cc08182..ed1441c 100644 --- a/kernel/console/Out.php +++ b/kernel/console/Out.php @@ -4,6 +4,8 @@ namespace kernel\console; +use kernel\helpers\Debug; + class Out { private $foreground_colors = array(); @@ -64,6 +66,11 @@ class Out echo $this->get($string, $foreground_color, $background_color) . "\n"; } + public function inLine($string, $foreground_color = null, $background_color = null): void + { + echo $this->get($string, $foreground_color, $background_color) ; + } + // Returns all foreground color names public function getForegroundColors() { @@ -75,4 +82,16 @@ class Out { return array_keys($this->background_colors); } + +// public function printHeaderTable(): void +// { +// echo "\n+-----------------------------+-----------------------------+-----------------------------+-----------------------------+\n"; +// printf("%-30s", "| Routs"); +// printf("%-30s", "| Description"); +// printf("%-30s", "| Params"); +// printf("%-30s", "| Params description"); +// printf("%-30s", "|"); +// echo "\n+-----------------------------+-----------------------------+-----------------------------+-----------------------------+\n"; +// } + } \ No newline at end of file diff --git a/kernel/console/controllers/KernelController.php b/kernel/console/controllers/KernelController.php index 147d84f..13efa75 100644 --- a/kernel/console/controllers/KernelController.php +++ b/kernel/console/controllers/KernelController.php @@ -27,7 +27,7 @@ class KernelController extends ConsoleController if (file_exists(ROOT_DIR . $this->argv['path'])) { $tmpKernelDirFull = RESOURCES_DIR . '/tmp/ad/kernel/kernel'; - $this->files->copy_folder(KERNEL_DIR, $tmpKernelDirFull); + $this->files->copy_folder(ROOT_DIR . $this->argv['path'], $tmpKernelDirFull); $this->out->r("Ядро скопировано во временную папку", 'green'); } else { $this->out->r("Ядро не найдено", 'red'); @@ -65,11 +65,19 @@ class KernelController extends ConsoleController $this->out->r("/composer.json не найден", 'red'); } - if (!is_dir(RESOURCES_DIR . '/tmp/app')) { - mkdir(RESOURCES_DIR . '/tmp/app'); + if (!is_dir(RESOURCES_DIR . '/tmp/kernel')) { + mkdir(RESOURCES_DIR . '/tmp/kernel'); + } + + if (file_exists(KERNEL_DIR . '/manifest.json')) { + $manifest = json_decode(file_get_contents(KERNEL_DIR . '/manifest.json'), true); + $version = $manifest['version'] ?? ''; + $this->files->pack(RESOURCES_DIR . '/tmp/ad/kernel/', RESOURCES_DIR . '/tmp/kernel/kernel_v' . $version . '.igk'); + } + else { + $this->files->pack(RESOURCES_DIR . '/tmp/ad/kernel/', RESOURCES_DIR . '/tmp/kernel/kernel.igk'); } - $this->files->pack(RESOURCES_DIR . '/tmp/ad/kernel/', RESOURCES_DIR . '/tmp/kernel/kernel.igk'); $this->files->recursiveRemoveDir(RESOURCES_DIR . '/tmp/ad/kernel/'); } diff --git a/kernel/console/controllers/MainController.php b/kernel/console/controllers/MainController.php index eecee1d..31a55bf 100644 --- a/kernel/console/controllers/MainController.php +++ b/kernel/console/controllers/MainController.php @@ -2,7 +2,9 @@ namespace kernel\console\controllers; +use kernel\App; use kernel\console\ConsoleController; +use kernel\helpers\Debug; class MainController extends ConsoleController { @@ -12,4 +14,25 @@ class MainController extends ConsoleController $this->out->r("Привет", "green"); } + public function actionHelp(): void + { + $routs = App::$collector->getData()->getStaticRoutes(); + foreach ($routs as $rout => $data){ + $additionalInfo = $data['GET'][3]; + if (isset($additionalInfo['description']) and $additionalInfo['type'] === "console"){ + $this->out->inLine($rout . " - ", "green"); + $this->out->inLine($additionalInfo['description'], 'yellow'); + $this->out->r(""); + if (isset($additionalInfo['params'])){ + foreach ($additionalInfo['params'] as $key => $param){ + $this->out->inLine($key . " - ", "green"); + $this->out->inLine($param, 'yellow'); + $this->out->r(""); + } + } + $this->out->r(""); + } + } + } + } \ No newline at end of file diff --git a/kernel/console/controllers/ModuleController.php b/kernel/console/controllers/ModuleController.php index db59f58..2898770 100644 --- a/kernel/console/controllers/ModuleController.php +++ b/kernel/console/controllers/ModuleController.php @@ -90,4 +90,33 @@ class ModuleController extends ConsoleController } } + public function actionConstructModule(): void + { + $this->out->r("Введите slug модуля:", 'yellow'); + $slug = substr(fgets(STDIN), 0, -1); + $slug = strtolower($slug); + + $this->out->r("Введите название модуля:", 'yellow'); + $name = substr(fgets(STDIN), 0, -1); + + $this->out->r("Введите автора модуля:", 'yellow'); + $author = substr(fgets(STDIN), 0, -1); + + $this->out->r("Введите название пунтка меню для модуля:", 'yellow'); + $label = substr(fgets(STDIN), 0, -1); + + $moduleService = new ModuleService(); + $moduleService->createDirs($slug); + + $moduleService->createModuleByParams([ + 'slug' => $slug, + 'model' => ucfirst($slug), + 'author' => $author, + 'name' => $name, + 'label' => $label, + ]); + + $this->out->r("Модуль $slug создан", 'green'); + } + } \ No newline at end of file diff --git a/kernel/console/migrations/stubs/migration.stub b/kernel/console/migrations/stubs/migration.stub index 88fa2f3..16abcae 100644 --- a/kernel/console/migrations/stubs/migration.stub +++ b/kernel/console/migrations/stubs/migration.stub @@ -6,6 +6,7 @@ use Illuminate\Support\Facades\Schema; return new class extends Migration { + public string $migration; /** * Run the migrations. */ diff --git a/kernel/console/routs/cli.php b/kernel/console/routs/cli.php index 693ff3c..d0f1032 100644 --- a/kernel/console/routs/cli.php +++ b/kernel/console/routs/cli.php @@ -1,41 +1,96 @@ console("hello", [\kernel\console\controllers\MainController::class, "indexAction"]); +App::$collector->console("help", [\kernel\console\controllers\MainController::class, "actionHelp"]); App::$collector->group(["prefix" => "migration"], callback: function (RouteCollector $router){ - App::$collector->console('run', [\kernel\console\controllers\MigrationController::class, 'actionRun']); - App::$collector->console('init', [\kernel\console\controllers\MigrationController::class, 'actionCreateMigrationTable']); - App::$collector->console('create', [\kernel\console\controllers\MigrationController::class, 'actionCreate']); - App::$collector->console('rollback', [\kernel\console\controllers\MigrationController::class, 'actionRollback']); + App::$collector->console('run', + [MigrationController::class, 'actionRun'], + additionalInfo: ['description' => 'Запуск существующих миграций'] + ); + App::$collector->console('init', + [MigrationController::class, 'actionCreateMigrationTable'], + additionalInfo: ['description' => 'Инициализация миграций'] + ); + App::$collector->console('create', + [MigrationController::class, 'actionCreate'], + additionalInfo: ['description' => 'Создание миграции', 'params' => ['--name' => 'Название миграции', '--path' => 'Путь по которому будет создана миграция']] + ); + App::$collector->console('rollback', + [MigrationController::class, 'actionRollback'], + additionalInfo: ['description' => 'Откатить миграции'] + ); }); App::$collector->group(["prefix" => "admin-theme"], callback: function (RouteCollector $router){ - App::$collector->console('install', [\kernel\console\controllers\AdminThemeController::class, 'actionInstallTheme']); - App::$collector->console('uninstall', [\kernel\console\controllers\AdminThemeController::class, 'actionUninstallTheme']); + App::$collector->console('install', + [\kernel\console\controllers\AdminThemeController::class, 'actionInstallTheme'], + additionalInfo: ['description' => 'Установить тему админ-панели', 'params' => ['--path' => 'Путь к устанавливаемой теме']] + ); + App::$collector->console('uninstall', + [\kernel\console\controllers\AdminThemeController::class, 'actionUninstallTheme'], + additionalInfo: ['description' => 'Удалить тему админ-панели', 'params' => ['--path' => 'Путь к удаляемой теме']] + ); }); App::$collector->group(["prefix" => "secure"], callback: function (RouteCollector $router){ - App::$collector->console('create-secret-key', [\kernel\console\controllers\SecureController::class, 'actionCreateSecretKey']); + App::$collector->console('create-secret-key', + [\kernel\console\controllers\SecureController::class, 'actionCreateSecretKey'], + additionalInfo: ['description' => 'Генерация секрктного ключа и запись его в .env'] + ); }); App::$collector->group(["prefix" => "admin"], callback: function (RouteCollector $router){ - App::$collector->console('init', [\kernel\console\controllers\AdminConsoleController::class, 'actionInit']); + App::$collector->console('init', + [\kernel\console\controllers\AdminConsoleController::class, 'actionInit'], + additionalInfo: ['description' => 'Инициализация админ-панели'] + ); }); App::$collector->group(["prefix" => "module"], callback: function (RouteCollector $router){ - 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']); + App::$collector->console('install', + [\kernel\console\controllers\ModuleController::class, 'actionInstallModule'], + additionalInfo: ['description' => 'Установка модуля', 'params' => ['--path' => 'Путь к устанавливаемому модулю']] + ); + App::$collector->console('uninstall', + [\kernel\console\controllers\ModuleController::class, 'actionUninstallModule'], + additionalInfo: ['description' => 'Удалить модуль', 'params' => ['--path' => 'Путь к удаляемому модулю']] + ); + App::$collector->console('pack', + [\kernel\console\controllers\ModuleController::class, 'actionPackModule'], + additionalInfo: ['description' => 'Заархивировать модуль', 'params' => ['--path' => 'Путь к модулю, который нужно заархивировать']] + ); + App::$collector->console('update', + [\kernel\console\controllers\ModuleController::class, 'actionUpdateModule'], + additionalInfo: ['description' => 'Обновить модуль', 'params' => ['--path' => 'Путь к архиву с модулем']] + ); + App::$collector->console('construct', + [\kernel\console\controllers\ModuleController::class, 'actionConstructModule'], + additionalInfo: ['description' => 'Сгенерировать модуль'] + ); }); App::$collector->group(["prefix" => "kernel"], callback: function (RouteCollector $router){ -// 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\KernelController::class, 'actionPackKernel']); - App::$collector->console('update', [\kernel\console\controllers\KernelController::class, 'actionUpdateKernel']); + App::$collector->console('pack', + [\kernel\console\controllers\KernelController::class, 'actionPackKernel'], + additionalInfo: ['description' => 'Заархивировать ядро', 'params' => ['--path' => 'Путь к ядру']] + ); + App::$collector->console('update', + [\kernel\console\controllers\KernelController::class, 'actionUpdateKernel'], + additionalInfo: [ + 'description' => 'Обновить модуль', + 'params' => + [ + '--path' => 'Путь к архиву ядра', + 'bootstrap' => 'Обновить bootstrap', + 'composer' => 'Обновить composer', + 'env' => 'Обновить .env.example' + ] + ] + ); }); diff --git a/kernel/controllers/ModuleController.php b/kernel/controllers/ModuleController.php index ea08cd4..e0fc983 100644 --- a/kernel/controllers/ModuleController.php +++ b/kernel/controllers/ModuleController.php @@ -12,6 +12,7 @@ use kernel\models\Option; use kernel\modules\module_shop_client\services\ModuleShopClientService; use kernel\modules\user\service\UserService; use kernel\Request; +use kernel\services\MigrationService; use kernel\services\ModuleService; class ModuleController extends AdminController diff --git a/kernel/manifest.json b/kernel/manifest.json new file mode 100644 index 0000000..3cccfd0 --- /dev/null +++ b/kernel/manifest.json @@ -0,0 +1,8 @@ +{ + "name": "Kernel", + "version": "0.1", + "author": "ITGuild", + "slug": "kernel", + "type": "kernel", + "description": "Kernel" +} diff --git a/kernel/modules/menu/migrations/2024_09_23_125545_create_menu_table.php b/kernel/modules/menu/migrations/2024_09_23_125545_create_menu_table.php index 60ee3b6..c27b7a9 100644 --- a/kernel/modules/menu/migrations/2024_09_23_125545_create_menu_table.php +++ b/kernel/modules/menu/migrations/2024_09_23_125545_create_menu_table.php @@ -6,6 +6,7 @@ use Illuminate\Support\Facades\Schema; return new class extends Migration { + public string $migration; /** * Run the migrations. */ diff --git a/kernel/modules/module_shop_client/views/login_at_module_shop.php b/kernel/modules/module_shop_client/views/login_at_module_shop.php index b635740..c68105f 100644 --- a/kernel/modules/module_shop_client/views/login_at_module_shop.php +++ b/kernel/modules/module_shop_client/views/login_at_module_shop.php @@ -9,7 +9,7 @@ echo \kernel\helpers\Html::h(2, "Форма авторизации/регист $form = new ActiveForm(); $form->beginForm("/admin/module_shop_client/auth/"); -$form->field(\itguild\forms\inputs\TextInput::class, 'email', [ +$form->field(\itguild\forms\inputs\EmailInput::class, 'email', [ 'class' => "form-control", 'placeholder' => 'Email', ]) diff --git a/kernel/modules/option/migrations/2024_09_23_125716_create_option_table.php b/kernel/modules/option/migrations/2024_09_23_125716_create_option_table.php index d2468a7..17edd23 100644 --- a/kernel/modules/option/migrations/2024_09_23_125716_create_option_table.php +++ b/kernel/modules/option/migrations/2024_09_23_125716_create_option_table.php @@ -6,6 +6,7 @@ use Illuminate\Support\Facades\Schema; return new class extends Migration { + public string $migration; /** * Run the migrations. */ diff --git a/kernel/modules/post/PostModule.php b/kernel/modules/post/PostModule.php index b56971c..f45e55c 100644 --- a/kernel/modules/post/PostModule.php +++ b/kernel/modules/post/PostModule.php @@ -5,17 +5,22 @@ namespace kernel\modules\post; use kernel\helpers\Debug; use kernel\Module; use kernel\modules\menu\service\MenuService; +use kernel\services\MigrationService; class PostModule extends Module { public MenuService $menuService; + public MigrationService $migrationService; public function __construct() { $this->menuService = new MenuService(); + $this->migrationService = new MigrationService(); } public function init(): void { + $this->migrationService->runAtPath("{KERNEL_MODULES}/post/migrations"); + $this->menuService->createItem([ "label" => "Посты", "url" => "/admin/post", @@ -26,5 +31,6 @@ class PostModule extends Module public function deactivate(): void { $this->menuService->removeItemBySlug("post"); + $this->migrationService->rollbackAtPath("{KERNEL_MODULES}/post/migrations"); } } \ No newline at end of file diff --git a/kernel/modules/post/migrations/2024_09_23_130017_create_post_table.php b/kernel/modules/post/migrations/2024_09_23_130017_create_post_table.php index 6556a6a..4144a14 100644 --- a/kernel/modules/post/migrations/2024_09_23_130017_create_post_table.php +++ b/kernel/modules/post/migrations/2024_09_23_130017_create_post_table.php @@ -6,6 +6,8 @@ use Illuminate\Support\Facades\Schema; return new class extends Migration { + public string $migration; + /** * Run the migrations. */ diff --git a/kernel/modules/post/views/index.php b/kernel/modules/post/views/index.php index d82ecb5..045feb1 100644 --- a/kernel/modules/post/views/index.php +++ b/kernel/modules/post/views/index.php @@ -3,16 +3,13 @@ /** * @var \Illuminate\Database\Eloquent\Collection $contents * @var int $page_number + * @var \kernel\CgView $view */ -use kernel\IGTabel\action_column\DeleteActionColumn; -use kernel\IGTabel\action_column\EditActionColumn; -use kernel\IGTabel\action_column\ViewActionColumn; use kernel\modules\post\models\Post; use kernel\modules\user\models\User; use Itguild\EloquentTable\EloquentDataProvider; use Itguild\EloquentTable\ListEloquentTable; -use kernel\IGTabel\btn\PrimaryBtn; use kernel\widgets\IconBtn\IconBtnCreateWidget; use kernel\widgets\IconBtn\IconBtnDeleteWidget; use kernel\widgets\IconBtn\IconBtnEditWidget; @@ -25,6 +22,11 @@ $table = new ListEloquentTable(new EloquentDataProvider(Post::class, [ 'baseUrl' => "/admin/post" ])); +$view->setTitle("Список постов"); +$view->setMeta([ + 'description' => 'Список постов системы' +]); + $entityRelation = new \kernel\EntityRelation(); $additionals = $entityRelation->getEntityRelationsBySlug("post"); diff --git a/kernel/modules/post/views/view.php b/kernel/modules/post/views/view.php index e3693d1..537ee55 100644 --- a/kernel/modules/post/views/view.php +++ b/kernel/modules/post/views/view.php @@ -7,9 +7,6 @@ use kernel\modules\user\models\User; use Itguild\EloquentTable\ViewEloquentTable; use Itguild\EloquentTable\ViewJsonTableEloquentModel; -use kernel\IGTabel\btn\DangerBtn; -use kernel\IGTabel\btn\PrimaryBtn; -use kernel\IGTabel\btn\SuccessBtn; use kernel\widgets\IconBtn\IconBtnDeleteWidget; use kernel\widgets\IconBtn\IconBtnEditWidget; use kernel\widgets\IconBtn\IconBtnListWidget; diff --git a/kernel/modules/secure/controllers/SecureRestController.php b/kernel/modules/secure/controllers/SecureRestController.php index 7e82699..163964f 100644 --- a/kernel/modules/secure/controllers/SecureRestController.php +++ b/kernel/modules/secure/controllers/SecureRestController.php @@ -36,14 +36,16 @@ class SecureRestController extends RestController $res = []; if ($model) { if (password_verify($data["password"], $model->password_hash)) { - $model->access_token_expires_at = date("Y-m-d H:i:s", strtotime(App::$secure['token_expired_time'])); - $model->access_token = match (App::$secure['token_type']) { - "JWT" => TokenService::JWT($_ENV['SECRET_KEY'], 'HS256'), - "md5" => TokenService::md5(), - "crypt" => TokenService::crypt(), - "hash" => TokenService::hash('sha256'), - default => TokenService::random_bytes(20), - }; + if ($model->access_token_expires_at < date("Y-m-d H:i:s") or $model->access_token === null){ + $model->access_token_expires_at = date("Y-m-d H:i:s", strtotime(App::$secure['token_expired_time'])); + $model->access_token = match (App::$secure['token_type']) { + "JWT" => TokenService::JWT($_ENV['SECRET_KEY'], 'HS256'), + "md5" => TokenService::md5(), + "crypt" => TokenService::crypt(), + "hash" => TokenService::hash('sha256'), + default => TokenService::random_bytes(20), + }; + } $res = [ "access_token" => $model->access_token, diff --git a/kernel/modules/secure/migrations/2024_12_09_081420_create_secret_code_table.php b/kernel/modules/secure/migrations/2024_12_09_081420_create_secret_code_table.php index c5acce1..a6ab989 100644 --- a/kernel/modules/secure/migrations/2024_12_09_081420_create_secret_code_table.php +++ b/kernel/modules/secure/migrations/2024_12_09_081420_create_secret_code_table.php @@ -6,6 +6,8 @@ use Illuminate\Support\Facades\Schema; return new class extends Migration { + public string $migration; + /** * Run the migrations. */ diff --git a/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php b/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php index 774213a..a762579 100644 --- a/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php +++ b/kernel/modules/user/migrations/2024_09_23_125827_create_user_table.php @@ -6,6 +6,8 @@ use Illuminate\Support\Facades\Schema; return new class extends Migration { + public string $migration; + /** * Run the migrations. * diff --git a/kernel/services/ConsoleService.php b/kernel/services/ConsoleService.php new file mode 100644 index 0000000..25c3d5c --- /dev/null +++ b/kernel/services/ConsoleService.php @@ -0,0 +1,21 @@ +capsule->getDatabaseManager(), 'migration'); + + $m = new Migrator($dmr, App::$db->capsule->getDatabaseManager(), $filesystem); + + $migrationFiles = $m->getMigrationFiles($path); + foreach ($migrationFiles as $name => $migrationFile){ + $migrationInstance = $filesystem->getRequire($migrationFile); + $migrationInstance->migration = $name; + $migrationInstance->down(); + $dmr->delete($migrationInstance); + } + } catch (\Exception $e) { + throw new \Exception('Не удалось откатить миграции'); + } + } + } \ No newline at end of file diff --git a/kernel/services/ModuleService.php b/kernel/services/ModuleService.php index 17c6459..542f60c 100644 --- a/kernel/services/ModuleService.php +++ b/kernel/services/ModuleService.php @@ -444,7 +444,7 @@ class ModuleService public function isLastVersion(string $slug): bool { - if ($this->isServerAvailable()){ + if ($this->isServerAvailable()) { $modules_info = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/gb_slug'); $modules_info = json_decode($modules_info->getBody()->getContents(), true); @@ -473,16 +473,20 @@ class ModuleService public function isShopModule(string $slug): bool { - if ($this->isServerAvailable()){ + if ($this->isServerAvailable()) { $modules_info = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/gb_slug'); - if (!$this->issetModuleShopToken()){ + + if (!$this->issetModuleShopToken()) { return false; } + $modules_info = json_decode($modules_info->getBody()->getContents(), true); - $mod_info = $this->getModuleInfoBySlug($slug); - foreach ($modules_info as $mod) { - if ($mod['slug'] === $mod_info['slug']) { - return true; + if (isset($modules_info)) { + $mod_info = $this->getModuleInfoBySlug($slug); + foreach ($modules_info as $mod) { + if ($mod['slug'] === $mod_info['slug']) { + return true; + } } } } @@ -503,7 +507,7 @@ class ModuleService public function isServerAvailable(): bool { - if (null !== $this->serverAvailable){ + if (null !== $this->serverAvailable) { return $this->serverAvailable; } @@ -520,10 +524,58 @@ class ModuleService public function issetModuleShopToken(): bool { - if (!empty($_ENV['MODULE_SHOP_TOKEN'])){ + if (!empty($_ENV['MODULE_SHOP_TOKEN'])) { return true; } return false; } + + public function createDirs(string $slug): void + { + mkdir(KERNEL_APP_MODULES_DIR . "/$slug"); + mkdir(KERNEL_APP_MODULES_DIR . "/$slug/controllers"); + mkdir(KERNEL_APP_MODULES_DIR . "/$slug/migrations"); + mkdir(KERNEL_APP_MODULES_DIR . "/$slug/services"); + mkdir(KERNEL_APP_MODULES_DIR . "/$slug/models"); + mkdir(KERNEL_APP_MODULES_DIR . "/$slug/models/forms"); + mkdir(KERNEL_APP_MODULES_DIR . "/$slug/routs"); + mkdir(KERNEL_APP_MODULES_DIR . "/$slug/views"); + + mkdir(APP_DIR . "/modules/$slug"); + mkdir(APP_DIR . "/modules/$slug/controllers"); + mkdir(APP_DIR . "/modules/$slug/routs"); + } + + public function createModuleByParams(array $params): void + { + $slug = $params['slug']; + $model = $params['model']; + + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/manifests/manifest_template', APP_DIR . "/modules/$slug/manifest.json", $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/controllers/kernel_controller_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/controllers/' . $model . 'Controller.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/controllers/app_controller_template', APP_DIR . '/modules/' . $slug . '/controllers/' . $model . 'Controller.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/routs/kernel_routs_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/routs/' . $slug . '.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/routs/app_routs_template', APP_DIR . '/modules/' . $slug . '/routs/' . $slug . '.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/module_files/kernel_module_file_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/' . $model . 'Module.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/module_files/app_module_file_template', APP_DIR . '/modules/' . $slug . '/' . $model . 'Module.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/models/model_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/models/' . $model . '.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/models/forms/create_form_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/models/forms/Create' . $model . 'Form.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/services/service_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/services/' . $model . 'Service.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/views/index_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/views/index.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/views/view_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/views/view.php', $params); + $this->createModuleFileByTemplate(KERNEL_TEMPLATES_DIR . '/views/form_template', KERNEL_APP_MODULES_DIR . '/' . $slug . '/views/form.php', $params); + } + + public function createModuleFileByTemplate(string $templatePath, string $filePath, array $params): void + { + $data = file_get_contents($templatePath); + + foreach ($params as $key => $param){ + $data = str_replace("{" . $key . "}", $param, $data); + } + + file_put_contents($filePath, $data); + } + } \ No newline at end of file diff --git a/kernel/services/TokenService.php b/kernel/services/TokenService.php index de5a4dd..b24096b 100644 --- a/kernel/services/TokenService.php +++ b/kernel/services/TokenService.php @@ -32,7 +32,7 @@ class TokenService */ public static function md5(): string { - return md5(microtime() . self::getSalt() . time()); + return md5(microtime() . self::getSalt(10) . time()); } /** @@ -40,7 +40,7 @@ class TokenService */ public static function crypt(): string { - return crypt(microtime(), self::getSalt()); + return crypt(microtime(), self::getSalt(20)); } /** @@ -48,15 +48,15 @@ class TokenService */ public static function hash(string $alg): string { - return hash($alg, self::getSalt()); + return hash($alg, self::getSalt(10)); } /** * @throws RandomException */ - public static function getSalt(): string + public static function getSalt(int $length): string { - return bin2hex(random_bytes(10)); + return bin2hex(random_bytes($length)); } } \ No newline at end of file diff --git a/kernel/templates/controllers/app_controller_template b/kernel/templates/controllers/app_controller_template new file mode 100644 index 0000000..03e0772 --- /dev/null +++ b/kernel/templates/controllers/app_controller_template @@ -0,0 +1,8 @@ +cgView->viewPath = KERNEL_APP_MODULES_DIR . "/{slug}/views/"; + $this->{slug}Service = new {model}Service(); + } + + public function actionCreate(): void + { + $this->cgView->render("form.php"); + } + + #[NoReturn] public function actionAdd(): void + { + ${slug}Form = new Create{model}Form(); + ${slug}Form->load($_REQUEST); + if (${slug}Form->validate()){ + ${slug} = $this->{slug}Service->create(${slug}Form); + if (${slug}){ + $this->redirect("/admin/{slug}/view/" . ${slug}->id); + } + } + $this->redirect("/admin/{slug}/create"); + } + + public function actionIndex($page_number = 1): void + { + $this->cgView->render("index.php", ['page_number' => $page_number]); + } + + /** + * @throws Exception + */ + public function actionView($id): void + { + ${slug} = {model}::find($id); + + if (!${slug}){ + throw new Exception(message: "The {slug} not found"); + } + $this->cgView->render("view.php", ['{slug}' => ${slug}]); + } + + /** + * @throws Exception + */ + public function actionUpdate($id): void + { + $model = {model}::find($id); + if (!$model){ + throw new Exception(message: "The {slug} not found"); + } + + $this->cgView->render("form.php", ['model' => $model]); + } + + /** + * @throws Exception + */ + public function actionEdit($id): void + { + ${slug} = {model}::find($id); + if (!${slug}){ + throw new Exception(message: "The {slug} not found"); + } + ${slug}Form = new Create{model}Form(); + ${slug}Service = new {model}Service(); + ${slug}Form->load($_REQUEST); + if (${slug}Form->validate()) { + ${slug} = ${slug}Service->update(${slug}Form, ${slug}); + if (${slug}) { + $this->redirect("/admin/{slug}/view/" . ${slug}->id); + } + } + $this->redirect("/admin/{slug}/update/" . $id); + } + + #[NoReturn] public function actionDelete($id): void + { + ${slug} = {model}::find($id)->first(); + ${slug}->delete(); + $this->redirect("/admin/{slug}/"); + } +} \ No newline at end of file diff --git a/kernel/templates/manifests/manifest_template b/kernel/templates/manifests/manifest_template new file mode 100644 index 0000000..7704dd4 --- /dev/null +++ b/kernel/templates/manifests/manifest_template @@ -0,0 +1,11 @@ +{ + "name": "{name}", + "version": "0.1", + "author": "{author}", + "slug": "{slug}", + "description": "{name} module", + "module_class": "app\\modules\\{slug}\\{model}Module", + "module_class_file": "{APP}/modules/{slug}/{model}Module.php", + "routs": "routs/{slug}.php", + "migration_path": "migrations" +} \ No newline at end of file diff --git a/kernel/templates/models/forms/create_form_template b/kernel/templates/models/forms/create_form_template new file mode 100644 index 0000000..e5b4f2b --- /dev/null +++ b/kernel/templates/models/forms/create_form_template @@ -0,0 +1,25 @@ + 'required|min-str-len:5|max-str-len:30', + // 'entity' => 'required', + // 'slug' => '', + // 'status' => '' + // ]; + return [ + + ]; + } + +} \ No newline at end of file diff --git a/kernel/templates/models/model_template b/kernel/templates/models/model_template new file mode 100644 index 0000000..cc6f55a --- /dev/null +++ b/kernel/templates/models/model_template @@ -0,0 +1,47 @@ + 'Заголовок', + // 'entity' => 'Сущность', + // 'slug' => 'Slug', + // 'status' => 'Статус', + // ] + + return [ + + ]; + } + + /** + * @return string[] + */ + public static function getStatus(): array + { + return [ + self::DISABLE_STATUS => "Не активный", + self::ACTIVE_STATUS => "Активный", + ]; + } + +} \ No newline at end of file diff --git a/kernel/templates/module_files/app_module_file_template b/kernel/templates/module_files/app_module_file_template new file mode 100644 index 0000000..ef58aee --- /dev/null +++ b/kernel/templates/module_files/app_module_file_template @@ -0,0 +1,8 @@ +menuService = new MenuService(); + } + + public function init(): void + { + $this->menuService->createItem([ + "label" => "{label}", + "url" => "/admin/{slug}", + "slug" => "{slug}", + ]); + } + + public function deactivate(): void + { + $this->menuService->removeItemBySlug("{slug}"); + } +} \ No newline at end of file diff --git a/kernel/templates/routs/app_routs_template b/kernel/templates/routs/app_routs_template new file mode 100644 index 0000000..a9558ba --- /dev/null +++ b/kernel/templates/routs/app_routs_template @@ -0,0 +1,2 @@ +group(["prefix" => "admin"], function (CgRouteCollector $router) { + App::$collector->group(["before" => "auth"], function (RouteCollector $router) { + App::$collector->group(["prefix" => "{slug}"], function (CGRouteCollector $router) { + App::$collector->get('/', [\app\modules\{slug}\controllers\{model}Controller::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\app\modules\{slug}\controllers\{model}Controller::class, 'actionIndex']); + App::$collector->get('/create', [\app\modules\{slug}\controllers\{model}Controller::class, 'actionCreate']); + App::$collector->post("/", [\app\modules\{slug}\controllers\{model}Controller::class, 'actionAdd']); + App::$collector->get('/view/{id}', [\app\modules\{slug}\controllers\{model}Controller::class, 'actionView']); + App::$collector->any('/update/{id}', [\app\modules\{slug}\controllers\{model}Controller::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\app\modules\{slug}\controllers\{model}Controller::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\app\modules\{slug}\controllers\{model}Controller::class, 'actionDelete']); + }); + }); +}); \ No newline at end of file diff --git a/kernel/templates/services/service_template b/kernel/templates/services/service_template new file mode 100644 index 0000000..e456e4e --- /dev/null +++ b/kernel/templates/services/service_template @@ -0,0 +1,39 @@ +content = $form_model->getItem('content'); + // $model->user_id = $form_model->getItem('user_id'); + // $model->title = $form_model->getItem('title'); + // $model->slug = Slug::createSlug($form_model->getItem('title'), {model}::class); // Генерация уникального slug + + if ($model->save()){ + return $model; + } + + return false; + } + + public function update(FormModel $form_model, {model} ${slug}): false|{model} + { + // Пример обновления: + // ${slug}->content = $form_model->getItem('content'); + // ${slug}->user_id = $form_model->getItem('user_id'); + + if (${slug}->save()){ + return ${slug}; + } + + return false; + } +} \ No newline at end of file diff --git a/kernel/templates/views/form_template b/kernel/templates/views/form_template new file mode 100644 index 0000000..180618b --- /dev/null +++ b/kernel/templates/views/form_template @@ -0,0 +1,55 @@ +beginForm(isset($model) ? "/admin/{slug}/edit/" . $model->id : "/admin/{slug}", 'multipart/form-data'); + +// Пример формы: + +/* +$form->field(\itguild\forms\inputs\TextInput::class, 'title', [ + 'class' => "form-control", + 'placeholder' => 'Заголовок поста', + 'value' => $model->title ?? '' +]) + ->setLabel("Заголовок") + ->render(); + +$form->field(class: \itguild\forms\inputs\Select::class, name: "user_id", params: [ + 'class' => "form-control", + 'value' => $model->user_id ?? '' +]) + ->setLabel("Пользователи") + ->setOptions(\kernel\modules\user\service\UserService::createUsernameArr()) + ->render(); +*/ + +?> +
+
+ field(\itguild\forms\inputs\Button::class, name: "btn-submit", params: [ + 'class' => "btn btn-primary ", + 'value' => 'Отправить', + 'typeInput' => 'submit' + ]) + ->render(); + ?> +
+
+ field(\itguild\forms\inputs\Button::class, name: "btn-reset", params: [ + 'class' => "btn btn-warning", + 'value' => 'Сбросить', + 'typeInput' => 'reset' + ]) + ->render(); + ?> +
+
+endForm(); diff --git a/kernel/templates/views/index_template b/kernel/templates/views/index_template new file mode 100644 index 0000000..a7a7171 --- /dev/null +++ b/kernel/templates/views/index_template @@ -0,0 +1,68 @@ +setTitle("Список {slug}"); +$view->setMeta([ + 'description' => 'Список {slug} системы' +]); + +//Для использования таблицы с моделью, необходимо создать таблицу в базе данных +//$table = new ListEloquentTable(new EloquentDataProvider({model}::class, [ +// 'currentPage' => $page_number, +// 'perPage' => 8, +// 'params' => ["class" => "table table-bordered", "border" => "2"], +// 'baseUrl' => "/admin/{slug}" +//])); + + +$table = new \Itguild\Tables\ListJsonTable(json_encode( + [ + 'meta' => [ + 'total' => 0, + 'totalWithFilters' => 0, + 'columns' => [ + 'title', + 'slug', + 'status', + ], + 'perPage' => 5, + 'currentPage' => 1, + 'baseUrl' => '/admin/some', + 'params' => [ + 'class' => 'table table-bordered', + 'border' => 2 + ] + ], + 'filters' => [], + 'data' => [], + ] +)); + +$table->beforePrint(function () { + return IconBtnCreateWidget::create(['url' => '/admin/{slug}/create'])->run(); +}); + +$table->addAction(function($row) { + return IconBtnViewWidget::create(['url' => '/admin/{slug}/view/' . $row['id']])->run(); +}); +$table->addAction(function($row) { + return IconBtnEditWidget::create(['url' => '/admin/{slug}/update/' . $row['id']])->run(); +}); +$table->addAction(function($row) { + return IconBtnDeleteWidget::create(['url' => '/admin/{slug}/delete/' . $row['id']])->run(); +}); +$table->create(); +$table->render(); \ No newline at end of file diff --git a/kernel/templates/views/view_template b/kernel/templates/views/view_template new file mode 100644 index 0000000..1ce19c5 --- /dev/null +++ b/kernel/templates/views/view_template @@ -0,0 +1,25 @@ + ["class" => "table table-bordered", "border" => "2"], + 'baseUrl' => "/admin/{slug}", +])); +$table->beforePrint(function () use (${slug}) { + $btn = IconBtnListWidget::create(['url' => '/admin/{slug}'])->run(); + $btn .= IconBtnEditWidget::create(['url' => '/admin/{slug}/update/' . ${slug}->id])->run(); + $btn .= IconBtnDeleteWidget::create(['url' => '/admin/{slug}/delete/' . ${slug}->id])->run(); + return $btn; +}); + +$table->create(); +$table->render(); \ No newline at end of file diff --git a/kernel/views/module/index.php b/kernel/views/module/index.php index d7c1158..8cb34f8 100644 --- a/kernel/views/module/index.php +++ b/kernel/views/module/index.php @@ -79,5 +79,7 @@ if ($moduleService->isActive('module_shop_client')) { ModuleTabsWidget::create()->run(); } + + $table->create(); $table->render();