Compare commits

..

2 Commits

Author SHA1 Message Date
f4971f1c7d merge 2024-09-23 12:53:49 +03:00
9e2f7cd9e3 modules init/deactivate, modules migrations 2024-09-23 12:50:50 +03:00
19 changed files with 284 additions and 23 deletions

View File

@ -0,0 +1,33 @@
<?php
namespace app\modules\tag;
use kernel\Module;
use kernel\modules\menu\service\MenuService;
class TagModule extends Module
{
public MenuService $menuService;
public function __construct()
{
$this->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");
}
}

View File

@ -4,5 +4,6 @@
"author": "ITGuild", "author": "ITGuild",
"slug": "tag", "slug": "tag",
"description": "Tags module", "description": "Tags module",
"module_class": "TagModule" "module_class": "app\\modules\\tag\\TagModule",
"module_class_file": "{APP}/modules/tag/TagModule.php"
} }

View File

@ -6,4 +6,5 @@ namespace kernel;
abstract class Module abstract class Module
{ {
abstract public function init(); abstract public function init();
abstract public function deactivate();
} }

View File

@ -13,10 +13,18 @@ use Illuminate\Database\Migrations\MigrationCreator;
use Illuminate\Database\Migrations\Migrator; use Illuminate\Database\Migrations\Migrator;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder; use Illuminate\Database\Schema\Builder;
use kernel\services\ModuleService;
class MigrationController extends ConsoleController class MigrationController extends ConsoleController
{ {
protected ModuleService $moduleService;
public function __construct()
{
parent::__construct();
$this->moduleService = new ModuleService();
}
//create migrations table //create migrations table
public function actionCreateMigrationTable(): void public function actionCreateMigrationTable(): void
{ {
@ -63,8 +71,8 @@ class MigrationController extends ConsoleController
$dmr = new DatabaseMigrationRepository(App::$db->capsule->getDatabaseManager(), 'migration'); $dmr = new DatabaseMigrationRepository(App::$db->capsule->getDatabaseManager(), 'migration');
$m = new Migrator($dmr, App::$db->capsule->getDatabaseManager(), new Filesystem()); $m = new Migrator($dmr, App::$db->capsule->getDatabaseManager(), new Filesystem());
//$migrationPaths = array_merge(App::$migrationsPaths, [ROOT_DIR . '/migrations']); $migrationPaths = array_merge($this->moduleService->getModulesMigrationsPaths(), [ROOT_DIR . '/migrations']);
$migrationPaths = [ROOT_DIR . '/migrations']; //$migrationPaths = [ROOT_DIR . '/migrations'];
$res = $m->run($migrationPaths); $res = $m->run($migrationPaths);
foreach ($res as $re){ foreach ($res as $re){
$this->out->r(basename($re), 'green'); $this->out->r(basename($re), 'green');

View File

@ -52,8 +52,17 @@ class ModuleController extends AdminController
{ {
$request = new Request(); $request = new Request();
$this->moduleService->setActiveModule($request->get("slug")); $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]);
} }
} }

View File

@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Model;
* @property string label * @property string label
* @property string url * @property string url
* @property int status * @property int status
* @property string slug
* @method static find($id) * @method static find($id)
*/ */
@ -21,7 +22,7 @@ class Menu extends Model
const ACTIVE_STATUS = 1; const ACTIVE_STATUS = 1;
protected $table = 'menu'; 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']; protected array $dates = ['deleted_at'];
public static function labels(): array public static function labels(): array
@ -33,6 +34,7 @@ class Menu extends Model
'icon_font' => 'Иконка', 'icon_font' => 'Иконка',
'url' => 'URL', 'url' => 'URL',
'status' => 'Статус', 'status' => 'Статус',
'slug' => 'Slug',
]; ];
} }

View File

@ -21,7 +21,7 @@ class Menu extends Model
const ACTIVE_STATUS = 1; const ACTIVE_STATUS = 1;
protected $table = 'menu'; 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']; protected array $dates = ['deleted_at'];
public static function labels(): array public static function labels(): array
@ -33,6 +33,7 @@ class Menu extends Model
'icon_font' => 'Иконка', 'icon_font' => 'Иконка',
'url' => 'URL', 'url' => 'URL',
'status' => 'Статус', 'status' => 'Статус',
'slug' => 'Slug',
]; ];
} }

View File

@ -5,12 +5,14 @@ namespace kernel\modules\menu\models\forms;
use kernel\FormModel; use kernel\FormModel;
/** /**
* @property $parent_id * @property int $parent_id
* @property $icon_file * @property string $icon_file
* @property $icon_font * @property string $icon_font
* @property $label * @property string $label
* @property $url * @property string $url
* @property $status * @property int $status
* @property string $slug
* @property string $parent_slug
*/ */
class CreateMenuForm extends FormModel class CreateMenuForm extends FormModel
{ {
@ -22,7 +24,9 @@ class CreateMenuForm extends FormModel
'icon_font' => '', 'icon_font' => '',
'label' => 'required|min-str-len:1|max-str-len:50', 'label' => 'required|min-str-len:1|max-str-len:50',
'url' => 'required|min-str-len:1', 'url' => 'required|min-str-len:1',
'status' => '' 'status' => '',
'slug' => 'required|min-str-len:1|max-str-len:50',
'parent_slug' => ''
]; ];
} }
} }

View File

@ -2,8 +2,11 @@
namespace kernel\modules\menu\service; namespace kernel\modules\menu\service;
use Exception;
use kernel\FormModel; use kernel\FormModel;
use kernel\helpers\Debug;
use kernel\models\Menu; use kernel\models\Menu;
use kernel\modules\menu\models\forms\CreateMenuForm;
use kernel\Request; use kernel\Request;
class MenuService class MenuService
@ -11,12 +14,13 @@ class MenuService
public function create(FormModel $form_model): false|Menu public function create(FormModel $form_model): false|Menu
{ {
$model = new 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_file = $form_model->getItem('icon_file');
$model->icon_font = $form_model->getItem('icon_font'); $model->icon_font = $form_model->getItem('icon_font');
$model->label = $form_model->getItem('label'); $model->label = $form_model->getItem('label');
$model->url = $form_model->getItem('url'); $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()){ if ($model->save()){
return $model; return $model;
} }
@ -24,6 +28,39 @@ class MenuService
return false; 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 public function update(FormModel $form_model, Menu $menuItem): false|Menu
{ {
$menuItem->parent_id = $form_model->getItem('parent_id'); $menuItem->parent_id = $form_model->getItem('parent_id');
@ -32,6 +69,7 @@ class MenuService
$menuItem->label = $form_model->getItem('label'); $menuItem->label = $form_model->getItem('label');
$menuItem->url = $form_model->getItem('url'); $menuItem->url = $form_model->getItem('url');
$menuItem->status = $form_model->getItem('status'); $menuItem->status = $form_model->getItem('status');
$menuItem->slug = $form_model->getItem('slug');
if ($menuItem->save()){ if ($menuItem->save()){
return $menuItem; return $menuItem;
} }

View File

@ -48,6 +48,13 @@ $form->field(class: \itguild\forms\inputs\TextInput::class, name: "url", params:
->setLabel("URL") ->setLabel("URL")
->render(); ->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: [ $form->field(class: \itguild\forms\inputs\Select::class, name: "status", params: [
'class' => "form-control", 'class' => "form-control",
'value' => $model->status ?? '1' 'value' => $model->status ?? '1'

View File

@ -2,13 +2,29 @@
namespace kernel\modules\post; namespace kernel\modules\post;
use kernel\helpers\Debug;
use kernel\Module; use kernel\Module;
use kernel\modules\menu\service\MenuService;
class PostModule extends Module class PostModule extends Module
{ {
public MenuService $menuService;
public function init() 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");
} }
} }

View File

@ -4,6 +4,8 @@
"author": "ITGuild", "author": "ITGuild",
"slug": "post", "slug": "post",
"description": "Post module", "description": "Post module",
"module_class": "PostModule", "module_class": "kernel\\modules\\post\\PostModule",
"routs": "routs/post.php" "module_class_file": "{KERNEL_MODULES}/post/PostModule.php",
"routs": "routs/post.php",
"migration_path": "migrations"
} }

View File

@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
\kernel\App::$db->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');
}
};

View File

@ -3,6 +3,7 @@
use kernel\App; use kernel\App;
use Phroute\Phroute\RouteCollector; use Phroute\Phroute\RouteCollector;
App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){
App::$collector->group(["prefix" => "post"], function (RouteCollector $router){ App::$collector->group(["prefix" => "post"], function (RouteCollector $router){
App::$collector->get('/', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']); App::$collector->get('/', [\kernel\modules\post\controllers\PostController::class, 'actionIndex']);

View File

@ -3,13 +3,46 @@
namespace kernel\modules\user; namespace kernel\modules\user;
use kernel\Module; use kernel\Module;
use kernel\modules\menu\service\MenuService;
class UserModule extends Module 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");
} }
} }

View File

@ -4,6 +4,7 @@
"author": "ITGuild", "author": "ITGuild",
"slug": "user", "slug": "user",
"description": "User module", "description": "User module",
"module_class": "UserModule", "module_class": "kernel\\modules\\user\\UserModule",
"module_class_file": "{KERNEL_MODULES}/user/UserModule.php",
"routs": "routs/user.php" "routs": "routs/user.php"
} }

View File

@ -17,12 +17,18 @@ class ModuleService
if (file_exists($module . "/manifest.json")) { if (file_exists($module . "/manifest.json")) {
$manifest = file_get_contents($module . "/manifest.json"); $manifest = file_get_contents($module . "/manifest.json");
$manifest = Manifest::getWithVars($manifest); $manifest = Manifest::getWithVars($manifest);
$manifest = getConst($manifest);
$info = array_merge($info, $manifest); $info = array_merge($info, $manifest);
} }
return $info; return $info;
} }
public function getModuleInfoBySlug(string $slug): false|array|string
{
return $this->getModuleInfo($this->getModuleDir($slug));
}
public function isActive(string $slug): bool public function isActive(string $slug): bool
{ {
$active_modules = Option::where("key", "active_modules")->first(); $active_modules = Option::where("key", "active_modules")->first();
@ -45,8 +51,10 @@ class ModuleService
if (in_array($module, $path->modules)) { if (in_array($module, $path->modules)) {
unset($path->modules[array_search($module, $path->modules)]); unset($path->modules[array_search($module, $path->modules)]);
$path->modules = array_values($path->modules); $path->modules = array_values($path->modules);
$this->runDeactivateScript($this->getModuleInfoBySlug($module));
} else { } else {
$path->modules[] = $module; $path->modules[] = $module;
$this->runInitScript($this->getModuleInfoBySlug($module));
} }
$active_modules->value = json_encode($path, JSON_UNESCAPED_UNICODE); $active_modules->value = json_encode($path, JSON_UNESCAPED_UNICODE);
$active_modules->save(); $active_modules->save();
@ -73,6 +81,28 @@ class ModuleService
return false; 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 public function getActiveModules(): array
{ {
$modules = []; $modules = [];
@ -111,4 +141,17 @@ class ModuleService
return $routs; 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;
}
} }

View File

@ -36,6 +36,10 @@ $table->addAction(function ($row, $url) use ($moduleService){
return $btn; return $btn;
}); });
$table->addAction(function ($row, $url) use ($moduleService){
$slug = $row['slug'];
return "<a class='btn btn-primary' href='$url/view/?slug=$slug' style='margin: 3px; width: 150px;' >Просмотр</a>";
});
$table->create(); $table->create();
$table->render(); $table->render();

View File

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
\kernel\App::$db->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']);
});
}
};