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 ?>
+ = $view->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();