diff --git a/app/modules/tag/TagModule.php b/app/modules/tag/TagModule.php new file mode 100644 index 0000000..ee01d77 --- /dev/null +++ b/app/modules/tag/TagModule.php @@ -0,0 +1,33 @@ +menuService = new MenuService(); + } + + /** + * @throws \Exception + */ + public function init(): void + { + $this->menuService->createItem([ + "label" => "Тэги", + "url" => "/admin/tag", + "slug" => "tag", + ]); + } + + public function deactivate(): void + { + $this->menuService->removeItemBySlug("tag"); + } +} \ No newline at end of file diff --git a/app/modules/tag/manifest.json b/app/modules/tag/manifest.json index 2612837..7372b40 100644 --- a/app/modules/tag/manifest.json +++ b/app/modules/tag/manifest.json @@ -4,5 +4,6 @@ "author": "ITGuild", "slug": "tag", "description": "Tags module", - "module_class": "TagModule" + "module_class": "app\\modules\\tag\\TagModule", + "module_class_file": "{APP}/modules/tag/TagModule.php" } \ No newline at end of file diff --git a/kernel/Module.php b/kernel/Module.php index cd094e7..f24d4a3 100644 --- a/kernel/Module.php +++ b/kernel/Module.php @@ -6,4 +6,5 @@ namespace kernel; abstract class Module { abstract public function init(); + abstract public function deactivate(); } \ No newline at end of file diff --git a/kernel/console/controllers/MigrationController.php b/kernel/console/controllers/MigrationController.php index 8e4bdd6..e167fe1 100644 --- a/kernel/console/controllers/MigrationController.php +++ b/kernel/console/controllers/MigrationController.php @@ -13,10 +13,18 @@ use Illuminate\Database\Migrations\MigrationCreator; use Illuminate\Database\Migrations\Migrator; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; +use kernel\services\ModuleService; class MigrationController extends ConsoleController { + protected ModuleService $moduleService; + public function __construct() + { + parent::__construct(); + $this->moduleService = new ModuleService(); + } + //create migrations table public function actionCreateMigrationTable(): void { @@ -63,8 +71,8 @@ class MigrationController extends ConsoleController $dmr = new DatabaseMigrationRepository(App::$db->capsule->getDatabaseManager(), 'migration'); $m = new Migrator($dmr, App::$db->capsule->getDatabaseManager(), new Filesystem()); - //$migrationPaths = array_merge(App::$migrationsPaths, [ROOT_DIR . '/migrations']); - $migrationPaths = [ROOT_DIR . '/migrations']; + $migrationPaths = array_merge($this->moduleService->getModulesMigrationsPaths(), [ROOT_DIR . '/migrations']); + //$migrationPaths = [ROOT_DIR . '/migrations']; $res = $m->run($migrationPaths); foreach ($res as $re){ $this->out->r(basename($re), 'green'); diff --git a/kernel/controllers/ModuleController.php b/kernel/controllers/ModuleController.php index f5a8dd9..e8524e8 100644 --- a/kernel/controllers/ModuleController.php +++ b/kernel/controllers/ModuleController.php @@ -52,8 +52,17 @@ class ModuleController extends AdminController { $request = new Request(); $this->moduleService->setActiveModule($request->get("slug")); + $mod_info = $this->moduleService->getModuleInfoBySlug($request->get('slug')); - $this->cgView->render("view.php", ['data' => $this->moduleService->getModuleInfo($this->moduleService->getModuleDir($request->get("slug")))]); + $this->cgView->render("view.php", ['data' => $mod_info]); + } + + public function actionView(): void + { + $request = new Request(); + $mod_info = $this->moduleService->getModuleInfoBySlug($request->get('slug')); + + $this->cgView->render("view.php", ['data' => $mod_info]); } } \ No newline at end of file diff --git a/kernel/models/Menu.php b/kernel/models/Menu.php index 4e6b802..343fca3 100644 --- a/kernel/models/Menu.php +++ b/kernel/models/Menu.php @@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Model; * @property string label * @property string url * @property int status + * @property string slug * @method static find($id) */ @@ -21,7 +22,7 @@ class Menu extends Model const ACTIVE_STATUS = 1; protected $table = 'menu'; - protected $fillable = ['parent_id', 'icon_file', 'icon_font', 'label', 'url', 'status']; + protected $fillable = ['parent_id', 'icon_file', 'icon_font', 'label', 'url', 'status', 'slug']; protected array $dates = ['deleted_at']; public static function labels(): array @@ -33,6 +34,7 @@ class Menu extends Model 'icon_font' => 'Иконка', 'url' => 'URL', 'status' => 'Статус', + 'slug' => 'Slug', ]; } diff --git a/kernel/modules/menu/models/Menu.php b/kernel/modules/menu/models/Menu.php index 71ea48f..fce307b 100644 --- a/kernel/modules/menu/models/Menu.php +++ b/kernel/modules/menu/models/Menu.php @@ -21,7 +21,7 @@ class Menu extends Model const ACTIVE_STATUS = 1; protected $table = 'menu'; - protected $fillable = ['parent_id', 'icon_file', 'icon_font', 'label', 'url', 'status']; + protected $fillable = ['parent_id', 'icon_file', 'icon_font', 'label', 'url', 'status', 'slug']; protected array $dates = ['deleted_at']; public static function labels(): array @@ -33,6 +33,7 @@ class Menu extends Model 'icon_font' => 'Иконка', 'url' => 'URL', 'status' => 'Статус', + 'slug' => 'Slug', ]; } diff --git a/kernel/modules/menu/models/forms/CreateMenuForm.php b/kernel/modules/menu/models/forms/CreateMenuForm.php index deaae43..4e3424e 100644 --- a/kernel/modules/menu/models/forms/CreateMenuForm.php +++ b/kernel/modules/menu/models/forms/CreateMenuForm.php @@ -5,12 +5,14 @@ namespace kernel\modules\menu\models\forms; use kernel\FormModel; /** - * @property $parent_id - * @property $icon_file - * @property $icon_font - * @property $label - * @property $url - * @property $status + * @property int $parent_id + * @property string $icon_file + * @property string $icon_font + * @property string $label + * @property string $url + * @property int $status + * @property string $slug + * @property string $parent_slug */ class CreateMenuForm extends FormModel { @@ -22,7 +24,9 @@ class CreateMenuForm extends FormModel 'icon_font' => '', 'label' => 'required|min-str-len:1|max-str-len:50', 'url' => 'required|min-str-len:1', - 'status' => '' + 'status' => '', + 'slug' => 'required|min-str-len:1|max-str-len:50', + 'parent_slug' => '' ]; } } \ No newline at end of file diff --git a/kernel/modules/menu/service/MenuService.php b/kernel/modules/menu/service/MenuService.php index 6101f63..dc61c51 100644 --- a/kernel/modules/menu/service/MenuService.php +++ b/kernel/modules/menu/service/MenuService.php @@ -2,8 +2,11 @@ namespace kernel\modules\menu\service; +use Exception; use kernel\FormModel; +use kernel\helpers\Debug; use kernel\models\Menu; +use kernel\modules\menu\models\forms\CreateMenuForm; use kernel\Request; class MenuService @@ -11,12 +14,13 @@ class MenuService public function create(FormModel $form_model): false|Menu { $model = new Menu(); - $model->parent_id = $form_model->getItem('parent_id'); + $model->parent_id = $form_model->getItem('parent_id') ?? 0; $model->icon_file = $form_model->getItem('icon_file'); $model->icon_font = $form_model->getItem('icon_font'); $model->label = $form_model->getItem('label'); $model->url = $form_model->getItem('url'); - $model->status = $form_model->getItem('status'); + $model->status = $form_model->getItem('status') ?? 1; + $model->slug = $form_model->getItem('slug'); if ($model->save()){ return $model; } @@ -24,6 +28,39 @@ class MenuService return false; } + /** + * @throws Exception + */ + public function createItem(array $item): false|Menu + { + $model = new CreateMenuForm(); + $model->load($item); + if (!$model->validate()){ + throw new Exception('Ошибка создания пункта меню'); + } + if ($model->getItem("parent_slug")){ + $parent = $this->getBySlug($model->getItem("parent_slug")); + if ($parent){ + $model->setItem("parent_id", $parent->id); + } + else { + $model->setItem("parent_id", 0); + } + } + + return $this->create($model); + } + + public function removeItemBySlug(string $slug) + { + return Menu::where("slug", $slug)->delete(); + } + + public function getBySlug(string $slug) + { + return Menu::where("slug", $slug)->first(); + } + public function update(FormModel $form_model, Menu $menuItem): false|Menu { $menuItem->parent_id = $form_model->getItem('parent_id'); @@ -32,6 +69,7 @@ class MenuService $menuItem->label = $form_model->getItem('label'); $menuItem->url = $form_model->getItem('url'); $menuItem->status = $form_model->getItem('status'); + $menuItem->slug = $form_model->getItem('slug'); if ($menuItem->save()){ return $menuItem; } diff --git a/kernel/modules/menu/views/form.php b/kernel/modules/menu/views/form.php index 2f4bb5b..38fdc4a 100644 --- a/kernel/modules/menu/views/form.php +++ b/kernel/modules/menu/views/form.php @@ -48,6 +48,13 @@ $form->field(class: \itguild\forms\inputs\TextInput::class, name: "url", params: ->setLabel("URL") ->render(); +$form->field(class: \itguild\forms\inputs\TextInput::class, name: "slug", params: [ + 'class' => "form-control", + 'value' => $model->slug ?? '' +]) + ->setLabel("Slug") + ->render(); + $form->field(class: \itguild\forms\inputs\Select::class, name: "status", params: [ 'class' => "form-control", 'value' => $model->status ?? '1' diff --git a/kernel/modules/post/PostModule.php b/kernel/modules/post/PostModule.php index ac8168b..b56971c 100644 --- a/kernel/modules/post/PostModule.php +++ b/kernel/modules/post/PostModule.php @@ -2,13 +2,29 @@ namespace kernel\modules\post; +use kernel\helpers\Debug; use kernel\Module; +use kernel\modules\menu\service\MenuService; class PostModule extends Module { - - public function init() + public MenuService $menuService; + public function __construct() { - // TODO: Implement init() method. + $this->menuService = new MenuService(); + } + + public function init(): void + { + $this->menuService->createItem([ + "label" => "Посты", + "url" => "/admin/post", + "slug" => "post", + ]); + } + + public function deactivate(): void + { + $this->menuService->removeItemBySlug("post"); } } \ No newline at end of file diff --git a/kernel/modules/post/manifest.json b/kernel/modules/post/manifest.json index 330d3e9..fb2c610 100644 --- a/kernel/modules/post/manifest.json +++ b/kernel/modules/post/manifest.json @@ -4,5 +4,8 @@ "author": "ITGuild", "slug": "post", "description": "Post module", - "module_class": "PostModule" + "module_class": "kernel\\modules\\post\\PostModule", + "module_class_file": "{KERNEL_MODULES}/post/PostModule.php", + "routs": "routs/post.php", + "migration_path": "migrations" } \ No newline at end of file diff --git a/kernel/modules/post/migrations/2024_09_23_092858_create_post_table.php b/kernel/modules/post/migrations/2024_09_23_092858_create_post_table.php new file mode 100644 index 0000000..0bc4747 --- /dev/null +++ b/kernel/modules/post/migrations/2024_09_23_092858_create_post_table.php @@ -0,0 +1,29 @@ +schema->create('post', function (Blueprint $table) { + $table->increments('id'); + $table->text('content')->nullable(false); + $table->integer('user_id'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + \kernel\App::$db->schema->dropIfExists('post'); + } +}; diff --git a/kernel/modules/post/routs/post.php b/kernel/modules/post/routs/post.php new file mode 100644 index 0000000..3c48150 --- /dev/null +++ b/kernel/modules/post/routs/post.php @@ -0,0 +1,20 @@ +group(["prefix" => "admin"], function (RouteCollector $router){ + App::$collector->group(["prefix" => "post"], function (RouteCollector $router){ + App::$collector->get('/', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); + App::$collector->get('/page/{page_number}', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); + App::$collector->get('/create', [\kernel\modules\post\controllers\PostController::class, 'actionCreate']); + App::$collector->post("/", [\kernel\modules\post\controllers\PostController::class, 'actionAdd']); + App::$collector->get('/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionView']); + App::$collector->any('/update/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionUpdate']); + App::$collector->any("/edit/{id}", [\kernel\modules\post\controllers\PostController::class, 'actionEdit']); + App::$collector->get('/delete/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionDelete']); + }); +}); \ No newline at end of file diff --git a/kernel/modules/user/UserModule.php b/kernel/modules/user/UserModule.php index 4907b00..e3897f1 100644 --- a/kernel/modules/user/UserModule.php +++ b/kernel/modules/user/UserModule.php @@ -3,13 +3,46 @@ namespace kernel\modules\user; use kernel\Module; +use kernel\modules\menu\service\MenuService; class UserModule extends Module { - public function init() + public MenuService $menuService; + public function __construct() { - // TODO: Implement init() method. + $this->menuService = new MenuService(); + } + + /** + * @throws \Exception + */ + public function init(): void + { + $this->menuService->createItem([ + "label" => "Пользователи", + "url" => "/admin/user", + "slug" => "user", + ]); + $this->menuService->createItem([ + "label" => "Список", + "url" => "/admin/user", + "slug" => "user_list", + "parent_slug" => "user", + ]); + $this->menuService->createItem([ + "label" => "Создать", + "url" => "/admin/user/create", + "slug" => "user_create", + "parent_slug" => "user", + ]); + } + + public function deactivate(): void + { + $this->menuService->removeItemBySlug("user_create"); + $this->menuService->removeItemBySlug("user_list"); + $this->menuService->removeItemBySlug("user"); } } \ No newline at end of file diff --git a/kernel/modules/user/manifest.json b/kernel/modules/user/manifest.json index f3972e1..10ae6d8 100644 --- a/kernel/modules/user/manifest.json +++ b/kernel/modules/user/manifest.json @@ -4,6 +4,7 @@ "author": "ITGuild", "slug": "user", "description": "User module", - "module_class": "UserModule", + "module_class": "kernel\\modules\\user\\UserModule", + "module_class_file": "{KERNEL_MODULES}/user/UserModule.php", "routs": "routs/user.php" } \ No newline at end of file diff --git a/kernel/routs/admin.php b/kernel/routs/admin.php index 74738b7..79ad811 100644 --- a/kernel/routs/admin.php +++ b/kernel/routs/admin.php @@ -10,16 +10,7 @@ App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ App::$collector->group(["prefix" => "module"], function (RouteCollector $router){ App::$collector->get('/', [\kernel\controllers\ModuleController::class, 'actionIndex']); App::$collector->get('/activate', [\kernel\controllers\ModuleController::class, 'actionActivate']); - }); - App::$collector->group(["prefix" => "post"], function (RouteCollector $router){ - App::$collector->get('/', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); - App::$collector->get('/page/{page_number}', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); - App::$collector->get('/create', [\kernel\modules\post\controllers\PostController::class, 'actionCreate']); - App::$collector->post("/", [\kernel\modules\post\controllers\PostController::class, 'actionAdd']); - App::$collector->get('/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionView']); - App::$collector->any('/update/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionUpdate']); - App::$collector->any("/edit/{id}", [\kernel\modules\post\controllers\PostController::class, 'actionEdit']); - App::$collector->get('/delete/{id}', [\kernel\modules\post\controllers\PostController::class, 'actionDelete']); + App::$collector->get('/view', [\kernel\controllers\ModuleController::class, 'actionView']); }); App::$collector->group(["prefix" => "settings"], function (RouteCollector $router){ App::$collector->group(["prefix" => "menu"], function (RouteCollector $router){ diff --git a/kernel/services/ModuleService.php b/kernel/services/ModuleService.php index d9d0364..5a56020 100644 --- a/kernel/services/ModuleService.php +++ b/kernel/services/ModuleService.php @@ -17,12 +17,18 @@ class ModuleService if (file_exists($module . "/manifest.json")) { $manifest = file_get_contents($module . "/manifest.json"); $manifest = Manifest::getWithVars($manifest); + $manifest = getConst($manifest); $info = array_merge($info, $manifest); } return $info; } + public function getModuleInfoBySlug(string $slug): false|array|string + { + return $this->getModuleInfo($this->getModuleDir($slug)); + } + public function isActive(string $slug): bool { $active_modules = Option::where("key", "active_modules")->first(); @@ -45,8 +51,10 @@ class ModuleService if (in_array($module, $path->modules)) { unset($path->modules[array_search($module, $path->modules)]); $path->modules = array_values($path->modules); + $this->runDeactivateScript($this->getModuleInfoBySlug($module)); } else { $path->modules[] = $module; + $this->runInitScript($this->getModuleInfoBySlug($module)); } $active_modules->value = json_encode($path, JSON_UNESCAPED_UNICODE); $active_modules->save(); @@ -73,6 +81,28 @@ class ModuleService return false; } + public function runInitScript($mod_info): void + { + if (isset($mod_info['module_class'])){ + if (isset($mod_info['module_class_file'])){ + require_once $mod_info['module_class_file']; + } + $moduleClass = new $mod_info['module_class'](); + $moduleClass->init(); + } + } + + public function runDeactivateScript($mod_info): void + { + if (isset($mod_info['module_class'])){ + if (isset($mod_info['module_class_file'])){ + require_once $mod_info['module_class_file']; + } + $moduleClass = new $mod_info['module_class'](); + $moduleClass->deactivate(); + } + } + public function getActiveModules(): array { $modules = []; @@ -108,4 +138,17 @@ class ModuleService return $routs; } + public function getModulesMigrationsPaths(): array + { + $migrationsPaths = []; + $modules = $this->getActiveModules(); + foreach ($modules as $module){ + if (isset($module['migration_path'])){ + $migrationsPaths[] = $module['path'] . "/" . $module['migration_path']; + } + } + + return $migrationsPaths; + } + } \ No newline at end of file diff --git a/kernel/views/module/index.php b/kernel/views/module/index.php index 0239174..7d69978 100644 --- a/kernel/views/module/index.php +++ b/kernel/views/module/index.php @@ -36,6 +36,10 @@ $table->addAction(function ($row, $url) use ($moduleService){ return $btn; }); +$table->addAction(function ($row, $url) use ($moduleService){ + $slug = $row['slug']; + return "Просмотр"; +}); $table->create(); $table->render(); diff --git a/migrations/2024_09_13_163221_add_slug_column_at_menu_table.php b/migrations/2024_09_13_163221_add_slug_column_at_menu_table.php new file mode 100644 index 0000000..65e0f1d --- /dev/null +++ b/migrations/2024_09_13_163221_add_slug_column_at_menu_table.php @@ -0,0 +1,28 @@ +schema->table('menu', function (Blueprint $table) { + $table->string('slug')->unique(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + \kernel\App::$db->schema->table('menu', function (Blueprint $table) { + $table->dropColumn(['slug']); + }); + } +};