diff --git a/app/modules/module_shop/views/index.php b/app/modules/module_shop/views/index.php index 21de1cb..7e1748c 100644 --- a/app/modules/module_shop/views/index.php +++ b/app/modules/module_shop/views/index.php @@ -24,8 +24,8 @@ $table->columns([ } ]); $table->beforePrint(function () { - $btn = PrimaryBtn::create("Добавить модуль", "/admin/module_shop/module/create")->fetch(); - $btn .= PrimaryBtn::create("Добавить ядро", "/admin/module_shop/kernel/create")->fetch(); + $btn = PrimaryBtn::create("Добавить модуль", "/admin/module_shop/module/create", width: '200px')->fetch(); + $btn .= PrimaryBtn::create("Добавить ядро", "/admin/module_shop/kernel/create", '400px')->fetch(); return $btn; }); $table->addAction(ViewActionColumn::class); diff --git a/bootstrap/secure.php b/bootstrap/secure.php index a8baf09..b57765e 100644 --- a/bootstrap/secure.php +++ b/bootstrap/secure.php @@ -1,7 +1,7 @@ 'email_code', // login_password, email_code + 'web_auth_type' => 'login_password', // login_password, email_code 'token_type' => 'hash', // random_bytes, md5, crypt, hash, JWT 'token_expired_time' => "+30 days", // +1 day ]; diff --git a/kernel/IGTabel/btn/PrimaryBtn.php b/kernel/IGTabel/btn/PrimaryBtn.php index 31a43c3..b389401 100644 --- a/kernel/IGTabel/btn/PrimaryBtn.php +++ b/kernel/IGTabel/btn/PrimaryBtn.php @@ -6,9 +6,9 @@ class PrimaryBtn { protected string $btn = ''; - public function __construct(string $title, string $url) + public function __construct(string $title, string $url, $width) { - $this->btn = "$title"; + $this->btn = "$title"; } public function fetch(): string @@ -16,9 +16,9 @@ class PrimaryBtn return $this->btn; } - public static function create(string $title, string $url): PrimaryBtn + public static function create(string $title, string $url, $width = '150px'): PrimaryBtn { - return new self($title, $url); + return new self($title, $url, $width); } } \ No newline at end of file diff --git a/kernel/console/controllers/KernelController.php b/kernel/console/controllers/KernelController.php index 13efa75..e6a3a2a 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(ROOT_DIR . $this->argv['path'], $tmpKernelDirFull); + $this->files->copyKernelFolder(ROOT_DIR . $this->argv['path'], $tmpKernelDirFull); $this->out->r("Ядро скопировано во временную папку", 'green'); } else { $this->out->r("Ядро не найдено", 'red'); @@ -35,7 +35,7 @@ class KernelController extends ConsoleController if (file_exists(ROOT_DIR . '/bootstrap')) { $tmpBootstrapDirFull = RESOURCES_DIR . '/tmp/ad/kernel/bootstrap'; - $this->files->copy_folder(ROOT_DIR . '/bootstrap', $tmpBootstrapDirFull); + $this->files->copyKernelFolder(ROOT_DIR . '/bootstrap', $tmpBootstrapDirFull); $this->out->r("/bootstrap скопирован во временную папку", 'green'); } else { $this->out->r("/bootstrap не найден", 'red'); @@ -99,11 +99,11 @@ class KernelController extends ConsoleController $zip->extractTo($tmpKernelDirFull); $zip->close(); $this->files->recursiveRemoveKernelDir(); - $this->files->copy_folder($tmpKernelDirFull . 'kernel' , ROOT_DIR . "/kernel"); + $this->files->copyKernelFolder($tmpKernelDirFull . 'kernel' , ROOT_DIR . "/kernel"); if (isset($this->argv['bootstrap'])) { $this->files->recursiveRemoveDir(ROOT_DIR . '/bootstrap'); - $this->files->copy_folder($tmpKernelDirFull . 'bootstrap' , ROOT_DIR . '/bootstrap'); + $this->files->copyKernelFolder($tmpKernelDirFull . 'bootstrap' , ROOT_DIR . '/bootstrap'); copy($tmpKernelDirFull . '/bootstrap.php' , ROOT_DIR . '/bootstrap.php'); } diff --git a/kernel/controllers/ModuleController.php b/kernel/controllers/ModuleController.php index e0fc983..8ce4d4e 100644 --- a/kernel/controllers/ModuleController.php +++ b/kernel/controllers/ModuleController.php @@ -6,13 +6,9 @@ use DirectoryIterator; use JetBrains\PhpStorm\NoReturn; use Josantonius\Session\Facades\Session; use kernel\AdminController; -use kernel\EntityRelation; use kernel\helpers\Debug; 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/helpers/Files.php b/kernel/helpers/Files.php index e05a3a1..2360dd7 100644 --- a/kernel/helpers/Files.php +++ b/kernel/helpers/Files.php @@ -7,11 +7,38 @@ use ZipArchive; class Files { - public function copy_folder($d1, $d2): void + public function copy_folder($d1, $d2, int $permissions = 0775, bool $recursive = true): void { if (is_dir($d1)) { if (!file_exists($d2)){ - $_d2 = mkdir($d2, permissions: 0774, recursive: true); + $old_mask = umask(0); + $_d2 = mkdir($d2, permissions: $permissions, recursive: $recursive); + umask($old_mask); + if (!$_d2) { + return; + } + } + + $d = dir($d1); + while (false !== ($entry = $d->read())) { + if ($entry != '.' && $entry != '..') { + $this->copy_folder("$d1/$entry", "$d2/$entry"); + } + } + $d->close(); + } else { + copy($d1, $d2); + chmod($d2, permissions: $permissions); + } + } + + public function copyKernelFolder($d1, $d2, int $permissions = 0775, bool $recursive = true): void + { + if (is_dir($d1)) { + if (!file_exists($d2)){ + $old_mask = umask(0); + $_d2 = mkdir($d2, permissions: $permissions, recursive: $recursive); + umask($old_mask); if (!$_d2) { return; } @@ -20,12 +47,13 @@ class Files $d = dir($d1); while (false !== ($entry = $d->read())) { if ($entry != '.' && $entry != '..' && $entry != 'app_modules') { - $this->copy_folder("$d1/$entry", "$d2/$entry"); + $this->copyKernelFolder("$d1/$entry", "$d2/$entry"); } } $d->close(); } else { copy($d1, $d2); + chmod($d2, permissions: $permissions); } } diff --git a/kernel/helpers/Version.php b/kernel/helpers/Version.php new file mode 100644 index 0000000..3380436 --- /dev/null +++ b/kernel/helpers/Version.php @@ -0,0 +1,16 @@ + intval($version) * 100, + 2 => intval($version) * 10, + 3 => intval($version), + }; + } +} \ No newline at end of file diff --git a/kernel/manifest.json b/kernel/manifest.json index 3cccfd0..6521135 100644 --- a/kernel/manifest.json +++ b/kernel/manifest.json @@ -1,6 +1,6 @@ { "name": "Kernel", - "version": "0.1", + "version": "0.1.1", "author": "ITGuild", "slug": "kernel", "type": "kernel", diff --git a/kernel/modules/module_shop_client/controllers/ModuleShopClientController.php b/kernel/modules/module_shop_client/controllers/ModuleShopClientController.php index a83f465..d4d4102 100644 --- a/kernel/modules/module_shop_client/controllers/ModuleShopClientController.php +++ b/kernel/modules/module_shop_client/controllers/ModuleShopClientController.php @@ -12,8 +12,9 @@ use kernel\helpers\Files; use kernel\helpers\RESTClient; use kernel\helpers\SMTP; use kernel\Mailing; -use kernel\modules\module_shop_client\services\ModuleShopClientService; use kernel\Request; +use kernel\services\AdminThemeService; +use kernel\services\KernelService; use kernel\services\ModuleService; use kernel\services\ModuleShopService; use kernel\services\TokenService; @@ -24,6 +25,7 @@ class ModuleShopClientController extends AdminController protected Client $client; protected ModuleService $moduleService; + protected KernelService $kernelService; protected function init(): void { @@ -32,6 +34,7 @@ class ModuleShopClientController extends AdminController $this->client = new Client(); $this->moduleService = new ModuleService(); + $this->kernelService = new KernelService(); } /** @@ -55,6 +58,8 @@ class ModuleShopClientController extends AdminController 'page_number' => $page_number, 'module_count' => $module_count, 'per_page' => $per_page, + 'kernelService' => new KernelService(), + 'adminThemeService' => new AdminThemeService(), ]); } else { $this->cgView->render("module_shop_error_connection.php"); @@ -112,6 +117,35 @@ class ModuleShopClientController extends AdminController $this->redirect('/admin/module_shop_client', 302); } + public function actionRenderKernelUpdateForm(): void + { + $this->cgView->render("kernel_update.php"); + } + + #[NoReturn] public function actionKernelUpdate(): void + { + $modules_info = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/gb_slug'); + + $modules_info = json_decode($modules_info->getBody()->getContents(), true); + foreach ($modules_info as $module) { + if ($module['slug'] === 'kernel') { + $path = $module['path_to_archive']; + } + } + if (isset($path)) { + Files::uploadByUrl($_ENV['MODULE_SHOP_URL'] . $path, RESOURCES_DIR . "/tmp/kernel"); + if ($this->kernelService->updateKernel('/resources/tmp/kernel/' . basename($path))) { + Flash::setMessage("success", "Ядро успешно обновлено."); + } else { + Flash::setMessage("error", "Ошибка обновления ядра."); + } + } else { + Flash::setMessage("error", "Ошибка обновления ядра."); + } + + $this->redirect('/admin/module_shop_client', 302); + } + #[NoReturn] public function actionDelete(): void { $request = new Request(); @@ -123,6 +157,47 @@ class ModuleShopClientController extends AdminController $this->redirect('/admin/module_shop_client', 302); } + public function actionSearch(int $page_number = 1): void + { + $request = new Request(); + $filters = $request->get(); + if ($this->moduleService->issetModuleShopToken()) { + if ($this->moduleService->isServerAvailable()) { + $modules_info = []; + $per_page = 8; + $modules = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/gb_slug'); + $modules = json_decode($modules->getBody()->getContents(), true); + foreach ($modules as $module) { + foreach ($filters as $key => $value) { + if ($value === '') continue; + if ($module[$key] !== $value) { + break; + } + + $modules_info[] = $module; + } + } + $module_count = count($modules_info); + $modules_info = array_slice($modules_info, $per_page * ($page_number - 1), $per_page); + + $this->cgView->render("index.php", [ + 'modules_info' => $modules_info, + 'moduleService' => $this->moduleService, + 'page_number' => $page_number, + 'module_count' => $module_count, + 'per_page' => $per_page, + 'kernelService' => new KernelService(), + 'adminThemeService' => new AdminThemeService(), + ]); + } else { + $this->cgView->render("module_shop_error_connection.php"); + } + + } else { + $this->cgView->render("login_at_module_shop.php"); + } + } + /** * @throws Exception */ @@ -131,13 +206,6 @@ class ModuleShopClientController extends AdminController $request = new Request(); $address = $request->post("email"); -// $mailing = new Mailing(); -// $mailing->send_html("login_by_code.php", ['code' => mt_rand(100000, 999999)], [ -// 'address' => $address, -// 'subject' => "Код авторизации", -// "from_name" => $_ENV['APP_NAME'] -// ]); - $moduleShopService = new ModuleShopService(); $result = $moduleShopService->email_auth($address); @@ -153,13 +221,6 @@ class ModuleShopClientController extends AdminController $request = new Request(); $code = $request->post("code"); -// $mailing = new Mailing(); -// $mailing->send_html("login_by_code.php", ['code' => mt_rand(100000, 999999)], [ -// 'address' => $address, -// 'subject' => "Код авторизации", -// "from_name" => $_ENV['APP_NAME'] -// ]); - $moduleShopService = new ModuleShopService(); $result = $moduleShopService->code_check($code); diff --git a/kernel/modules/module_shop_client/routs/module_shop_client.php b/kernel/modules/module_shop_client/routs/module_shop_client.php index 5004486..945ccd2 100644 --- a/kernel/modules/module_shop_client/routs/module_shop_client.php +++ b/kernel/modules/module_shop_client/routs/module_shop_client.php @@ -15,8 +15,17 @@ App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){ App::$collector->get('/view/{id}', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionView']); App::$collector->get('/delete', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionDelete']); App::$collector->get('/update', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionUpdate']); + App::$collector->get('/search', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionSearch']); App::$collector->post('/auth', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionAuth']); App::$collector->post('/code_check', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionCodeCheck']); + App::$collector->group(["prefix" => "kernel"], function (RouteCollector $router) { + App::$collector->get('/update_form', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionRenderKernelUpdateForm']); + App::$collector->post('/update', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionKernelUpdate']); + }); + App::$collector->group(["prefix" => "admin_theme"], function (RouteCollector $router) { + App::$collector->get('/install', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionAdminThemeInstall']); + App::$collector->post('/update', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionAdminThemeUpdate']); + }); }); }); }); \ No newline at end of file diff --git a/kernel/modules/module_shop_client/views/index.php b/kernel/modules/module_shop_client/views/index.php index bfe766d..aa5ae3e 100644 --- a/kernel/modules/module_shop_client/views/index.php +++ b/kernel/modules/module_shop_client/views/index.php @@ -5,6 +5,8 @@ * @var int $page_number * @var int $per_page * @var \kernel\services\ModuleService $moduleService + * @var \kernel\services\KernelService $kernelService + * @var \kernel\services\AdminThemeService $adminThemeService */ use Itguild\Tables\ListJsonTable; @@ -15,6 +17,7 @@ $meta['columns'] = [ "name" => "Название", "author" => "Автор", "version" => "Версия", + "type" => "Тип", "description" => "Описание", "installations" => "Установки", "views" => "Просмотры" @@ -27,6 +30,7 @@ $meta['total'] = $module_count; $info_to_table['meta'] = $meta; $info_to_table['data'] = $modules_info; +$info_to_table['filters'] = ['type']; $table = new ListJsonTable(json_encode($info_to_table, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); @@ -37,21 +41,23 @@ $table->addAction(function ($row, $url) use ($moduleService) { }); $table->addAction(function ($row, $url) use ($moduleService){ - if ($moduleService->isInstall($row['slug'])){ - $url = "$url/delete/?slug=" . $row['slug']; + if ($row['slug'] !== 'kernel') { + if ($moduleService->isInstall($row['slug'])) { + $url = "$url/delete/?slug=" . $row['slug']; - return \kernel\widgets\IconBtn\IconBtnDeleteWidget::create(['url' => $url])->run(); - } - else { - $url = "$url/install/?id=" . $row['id']; + return \kernel\widgets\IconBtn\IconBtnDeleteWidget::create(['url' => $url])->run(); + } else { + $url = "$url/install/?id=" . $row['id']; - return \kernel\widgets\IconBtn\IconBtnInstallWidget::create(['url' => $url])->run(); + return \kernel\widgets\IconBtn\IconBtnInstallWidget::create(['url' => $url])->run(); + } } + return null; }); -$table->addAction(function ($row, $url) use ($moduleService){ +$table->addAction(function ($row, $url) use ($moduleService) { $slug = $row['slug']; - if ($moduleService->isInstall($slug)){ + if ($moduleService->isInstall($slug)) { if (!$moduleService->isLastVersion($slug)) { $url = "$url/update/?slug=" . $slug; @@ -62,6 +68,39 @@ $table->addAction(function ($row, $url) use ($moduleService){ return false; }); +$table->addAction(function ($row, $url) use ($kernelService) { + $slug = $row['slug']; + if ($slug === 'kernel') { + if (!$kernelService->isLastVersion()) { + $url = "$url/kernel/update_form/"; + + return \kernel\widgets\IconBtn\IconBtnUpdateWidget::create(['url' => $url])->run(); + } + } + + return false; +}); + +$table->addAction(function ($row, $url) use ($adminThemeService) { + $type = $row['type']; + $slug = $row['slug']; + if ($type === 'admin_theme') { + if ($adminThemeService->isInstall($slug)) { + if (!$adminThemeService->isLastVersion($slug)) { + $url = "$url/admin_theme/update/"; + + return \kernel\widgets\IconBtn\IconBtnUpdateWidget::create(['url' => $url])->run(); + } + } + } + + return false; +}); + +$table->afterPrint(function () { + return \kernel\IGTabel\btn\PrimaryBtn::create('Сбросить все фильтры', '/admin/module_shop_client')->fetch(); +}); + \kernel\widgets\ModuleTabsWidget::create()->run(); $table->create(); diff --git a/kernel/modules/module_shop_client/views/kernel_update.php b/kernel/modules/module_shop_client/views/kernel_update.php new file mode 100644 index 0000000..ca520f4 --- /dev/null +++ b/kernel/modules/module_shop_client/views/kernel_update.php @@ -0,0 +1,39 @@ +run(); + +echo \kernel\helpers\Html::h(2, "Выберите нужные файлы для обновления"); + +$form = new ActiveForm(); +$form->beginForm("/admin/module_shop_client/kernel/update/", enctype: 'multipart/form-data'); + +$form->field(\itguild\forms\inputs\Select::class, "files[]", [ + 'class' => "form-control", + 'multiple' => "multiple", +]) + ->setLabel("Дополнительные файлы") + ->setOptions([ + 'env.example' => 'env.example', + 'bootstrap.php' => 'bootstrap', + 'composer.json' => 'composer.json', + ]) + ->render(); +?> + +