Compare commits

...

5 Commits

Author SHA1 Message Date
84b366908c fix add theme 2025-01-24 14:43:08 +03:00
4cbcc594b6 fix add theme 2025-01-24 14:36:22 +03:00
530908568c kernel update to v0.1.5 2025-01-24 11:33:08 +03:00
4d7a2fbdec some fix 2025-01-23 16:55:02 +03:00
29e0ff327f get all dependencies 2025-01-23 13:33:41 +03:00
17 changed files with 417 additions and 21 deletions

View File

@ -3,6 +3,7 @@
namespace app\modules\module_shop\controllers;
use app\modules\module_shop\models\ModuleShop;
use app\modules\module_shop\services\ModuleShopService;
use JetBrains\PhpStorm\NoReturn;
use kernel\helpers\Debug;
use kernel\Request;
@ -105,4 +106,9 @@ class ModuleShopRestController extends RestController
$this->renderApi($model->toArray());
}
public function actionGetDependenciesBySlug(string $slug)
{
$this->renderApi(ModuleShopService::getAllDependencies($slug));
}
}

View File

@ -58,8 +58,8 @@ class ThemeShopController extends AdminController
$zip->extractTo($tmpModuleShopDirFull);
$zip->close();
if (file_exists($tmpModuleShopDirFull . "meta/manifest.json")){
$themeInfo = $this->moduleShopService->getModuleInfo($tmpModuleShopDirFull . "meta");
if (file_exists($tmpModuleShopDirFull . "meta/app/manifest.json")){
$themeInfo = $this->moduleShopService->getModuleInfo($tmpModuleShopDirFull . "meta/app");
$themeShopForm->load($themeInfo);
}
else {

View File

@ -17,6 +17,7 @@ class CreateThemeShopForm extends FormModel
'slug' => 'required',
'type' => 'required',
'path_to_archive' => 'required',
'dependence' => ''
];
}
}

View File

@ -39,6 +39,7 @@ App::$collector->group(["prefix" => "api"], 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->get('/get_all_dependencies/{slug}', [\app\modules\module_shop\controllers\ModuleShopRestController::class, 'actionGetDependenciesBySlug']);
App::$collector->group(["prefix" => "kernel"], function (CgRouteCollector $router) {
App::$collector->get('/update/{id}', [\app\modules\module_shop\controllers\KernelShopRestController::class, 'actionUpdate']);
});

View File

@ -51,4 +51,40 @@ class ModuleShopService extends ModuleService
return false;
}
public static function getAllDependencies(string $slug, array $depArr = []): array
{
$query = ModuleShop::query();
$query->select('ms1.*')
->from('module_shop as ms1')
->leftJoin('module_shop as ms2', function ($join) {
$join->on('ms1.slug', '=', 'ms2.slug')
->on('ms1.id', '<', 'ms2.id');
})
->where('ms2.slug', '=', null);
$query->where('ms1.slug', $slug);
$module = $query->first();
if ($module){
if ($module->dependence !== null){
$moduleDependencies = explode(",", $module->dependence);
foreach ($moduleDependencies as $dependency){
if (!in_array($dependency, $depArr)){
$depArr[] = $dependency;
$depArrTmp = self::getAllDependencies($dependency, $depArr);
foreach ($depArrTmp as $item){
if (!in_array($item, $depArr)){
$depArr[] = $item;
}
}
}
}
}
}
return array_diff($depArr, [$slug]);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace app\themes\custom\assets;
use kernel\Assets;
class CustomThemesAssets extends Assets
{
protected function createCSS(): void
{
$this->registerCSS(slug: "main", resource: "/css/styles.css");
}
protected function createJS(): void
{
$this->registerJS(slug: "webpack", resource: "/js/scripts.js");
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace app\themes\custom\controllers;
use kernel\Controller;
class MainController extends Controller
{
protected function init(): void
{
parent::init();
$this->cgView->viewPath = APP_DIR . "/themes/custom/views/main/";
$this->cgView->layout = "main.php";
$this->cgView->layoutPath = APP_DIR . "/themes/custom/views/layout/";
$this->cgView->addVarToLayout("resources", "/resources/themes/custom");
}
public function actionIndex(): void
{
$this->cgView->render("index.php");
}
public function actionAbout(): void
{
$this->cgView->render("about.php");
}
}

View File

@ -0,0 +1,12 @@
{
"name": "Custom",
"version": "0.1",
"author": "ItGuild",
"slug": "custom",
"type": "theme",
"description": "Custom theme",
"preview": "preview.png",
"resource": "/resources/themes/custom",
"resource_path": "{RESOURCES}/themes/custom",
"routs": "routs/custom.php"
}

View File

@ -0,0 +1,12 @@
<?php
use kernel\App;
App::$collector->get('/', [\app\themes\custom\controllers\MainController::class, 'actionIndex']);
App::$collector->get('/about', [\app\themes\custom\controllers\MainController::class, 'actionAbout']);
//App::$collector->get('/page/{page_number}', [\app\modules\tag\controllers\TagController::class, 'actionIndex']);
//App::$collector->get('/create', [\app\modules\tag\controllers\TagController::class, 'actionCreate']);

View File

@ -0,0 +1,92 @@
<?php
/**
* @var string $content
* @var string $resources
* @var string $title
* @var \kernel\CgView $view
*/
$assets = new \app\themes\custom\assets\CustomThemesAssets($resources);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
<?php $assets->getCSSAsSTR(); ?>
<meta name="description" content=""/>
<meta name="author" content=""/>
<title><?= $title ?></title>
<?= $view->getMeta() ?>
<link rel="icon" type="image/x-icon" href="<?= $resources ?>/assets/favicon.ico"/>
<!-- Font Awesome icons (free version)-->
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
<!-- Google fonts-->
<link href="https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" rel="stylesheet"
type="text/css"/>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800"
rel="stylesheet" type="text/css"/>
<!-- Core theme CSS (includes Bootstrap)-->
</head>
<body>
<!-- Navigation-->
<nav class="navbar navbar-expand-lg navbar-light" id="mainNav">
<div class="container px-4 px-lg-5">
<a class="navbar-brand" href="/">Custom theme</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive"
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
Menu
<i class="fas fa-bars"></i>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ms-auto py-4 py-lg-0">
<li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="/">На главную</a></li>
<li class="nav-item"><a class="nav-link px-lg-3 py-3 py-lg-4" href="/about">О нас</a></li>
</ul>
</div>
</div>
</nav>
<?= $content ?>
<!-- Footer-->
<footer class="border-top">
<div class="container px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<ul class="list-inline text-center">
<li class="list-inline-item">
<a href="#!">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-twitter fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li class="list-inline-item">
<a href="#!">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-facebook-f fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li class="list-inline-item">
<a href="#!">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-github fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
</ul>
<div class="small text-center text-muted fst-italic">Copyright &copy; IT Guild Micro Framework</div>
</div>
</div>
</div>
</footer>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<?php $assets->getJSAsStr(); ?>
</body>
</html>

View File

@ -0,0 +1,36 @@
<?php
/**
* @var string $resources;
* @var \kernel\CgView $view
*/
$view->setTitle("Старт Bootstrap");
$view->setMeta([
'description' => 'Дефолтная bootstrap тема'
]);
?>
<!-- Page Header-->
<header class="masthead" style="background-image: url('<?= $resources ?>/assets/img/about-bg.jpeg')">
<div class="container position-relative px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<div class="page-heading">
<h1>About Me</h1>
<span class="subheading">This is what I do.</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content-->
<main class="mb-4">
<div class="container px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Saepe nostrum ullam eveniet pariatur voluptates odit, fuga atque ea nobis sit soluta odio, adipisci quas excepturi maxime quae totam ducimus consectetur?</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius praesentium recusandae illo eaque architecto error, repellendus iusto reprehenderit, doloribus, minus sunt. Numquam at quae voluptatum in officia voluptas voluptatibus, minus!</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut consequuntur magnam, excepturi aliquid ex itaque esse est vero natus quae optio aperiam soluta voluptatibus corporis atque iste neque sit tempora!</p>
</div>
</div>
</div>
</main>

View File

@ -0,0 +1,86 @@
<?php
/**
* @var string $resources;
* @var \kernel\CgView $view
*/
$view->setTitle("IT Guild Micro Framework");
$view->setMeta([
'description' => 'Default IT Guild Micro Framework theme'
]);
?>
<!-- Page Header-->
<header class="masthead" style="background-image: url('<?= $resources ?>/assets/img/home-bg.jpeg')">
<div class="container position-relative px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<div class="site-heading">
<h1>Clean Blog</h1>
<span class="subheading">A Blog Theme by IT Guild Micro Framework</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content-->
<div class="container px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<!-- Post preview-->
<div class="post-preview">
<a href="#!">
<h2 class="post-title">Man must explore, and this is exploration at its greatest</h2>
<h3 class="post-subtitle">Problems look mighty small from 150 miles up</h3>
</a>
<p class="post-meta">
Posted by
<a href="#!">Start Bootstrap</a>
on September 24, 2023
</p>
</div>
<!-- Divider-->
<hr class="my-4" />
<!-- Post preview-->
<div class="post-preview">
<a href="#!"><h2 class="post-title">I believe every human has a finite number of heartbeats. I don't intend to waste any of mine.</h2></a>
<p class="post-meta">
Posted by
<a href="#!">Start Bootstrap</a>
on September 18, 2023
</p>
</div>
<!-- Divider-->
<hr class="my-4" />
<!-- Post preview-->
<div class="post-preview">
<a href="#!">
<h2 class="post-title">Science has not yet mastered prophecy</h2>
<h3 class="post-subtitle">We predict too much for the next year and yet far too little for the next ten.</h3>
</a>
<p class="post-meta">
Posted by
<a href="#!">Start Bootstrap</a>
on August 24, 2023
</p>
</div>
<!-- Divider-->
<hr class="my-4" />
<!-- Post preview-->
<div class="post-preview">
<a href="#!">
<h2 class="post-title">Failure is not an option</h2>
<h3 class="post-subtitle">Many say exploration is part of our destiny, but its actually our duty to future generations.</h3>
</a>
<p class="post-meta">
Posted by
<a href="#!">Start Bootstrap</a>
on July 8, 2023
</p>
</div>
<!-- Divider-->
<hr class="my-4" />
<!-- Pager-->
<div class="d-flex justify-content-end mb-4"><a class="btn btn-primary text-uppercase" href="#!">Older Posts →</a></div>
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
{
"name": "Kernel",
"version": "0.1.4",
"version": "0.1.5",
"author": "ITGuild",
"slug": "kernel",
"type": "kernel",

View File

@ -3,18 +3,31 @@
namespace kernel\modules\themes\controllers;
use DirectoryIterator;
use GuzzleHttp\Exception\GuzzleException;
use JetBrains\PhpStorm\NoReturn;
use Josantonius\Session\Exceptions\HeadersSentException;
use Josantonius\Session\Exceptions\SessionNotStartedException;
use Josantonius\Session\Exceptions\SessionStartedException;
use Josantonius\Session\Exceptions\WrongSessionOptionException;
use Josantonius\Session\Facades\Session;
use kernel\AdminController;
use kernel\helpers\Debug;
use kernel\models\Option;
use kernel\Request;
use kernel\services\ModuleService;
use kernel\services\ThemeService;
class ThemeController extends AdminController
{
public ThemeService $themeService;
public ModuleService $moduleService;
protected function init(): void
{
parent::init();
$this->cgView->viewPath = KERNEL_MODULES_DIR . "/themes/views/";
$this->themeService = new ThemeService();
$this->moduleService = new ModuleService();
}
public function actionIndex(): void
@ -62,10 +75,19 @@ class ThemeController extends AdminController
$this->cgView->render("index.php", ['json' => json_encode($infoToTable, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)]);
}
/**
* @throws HeadersSentException
* @throws WrongSessionOptionException
* @throws SessionStartedException
* @throws GuzzleException
* @throws SessionNotStartedException
*/
#[NoReturn] public function actionActivate(): void
{
$request = new Request();
$this->themeService->setActiveTheme($request->get("p"));
if(!$this->themeService->setActiveTheme($request->get("p"))){
$this->redirect("/admin/settings/themes/", 302);
}
$this->cgView->render("view.php", ['data' => $this->themeService->getThemeInfo($request->get("p"))]);
}

View File

@ -21,6 +21,7 @@ class ModuleService
protected null|bool $serverAvailable = null;
public ModuleShopService $moduleShopService;
public function __construct()
{
$this->moduleShopService = new ModuleShopService();
@ -601,11 +602,41 @@ class ModuleService
{
$data = file_get_contents($templatePath);
foreach ($params as $key => $param){
foreach ($params as $key => $param) {
$data = str_replace("{" . $key . "}", $param, $data);
}
file_put_contents($filePath, $data);
}
/**
* @throws GuzzleException
*/
public function recursiveActivateDependencies(array $dependencies): bool
{
$notActiveDependencies = [];
foreach ($dependencies as $depend) {
if (!$this->isInstall($depend)) {
$this->moduleShopService->installModule($depend);
if (!$this->setActiveModule($depend)) {
$notActiveDependencies[] = $depend;
}
} else {
if (!$this->isActive($depend)) {
if (!$this->setActiveModule($depend)) {
$notActiveDependencies[] = $depend;
}
}
}
}
if ($notActiveDependencies) {
if (!$this->recursiveActivateDependencies($notActiveDependencies)) {
return false;
}
}
return true;
}
}

View File

@ -88,4 +88,21 @@ class ModuleShopService
return false;
}
/**
* @param string $slug
* @return bool
* @throws GuzzleException
*/
public function existsInModuleShop(string $slug): bool
{
$modulesInfo = $this->getGroupedBySlugModules();
foreach ($modulesInfo as $module) {
if ($module['slug'] === $slug) {
return true;
}
}
return false;
}
}

View File

@ -3,6 +3,7 @@
namespace kernel\services;
use DirectoryIterator;
use Josantonius\Session\Facades\Session;
use kernel\Flash;
use kernel\helpers\Debug;
use kernel\helpers\Files;
@ -22,6 +23,7 @@ class ThemeService
protected ModuleShopService $moduleShopService;
public function __construct()
{
$this->option = new Option();
@ -58,7 +60,6 @@ class ThemeService
return $this->active_theme;
}
/**
* @param string $theme
* @return bool
@ -69,27 +70,24 @@ class ThemeService
$activeTheme = $this->option::where("key", "active_theme")->first();
$themeInfo = $this->getThemeInfo(getConst($theme));
if (isset($themeInfo['dependence'])) {
$dependence_array = explode(',', $themeInfo['dependence']);
foreach ($dependence_array as $depend) {
if (!$this->moduleService->isInstall($depend)) {
if ($this->moduleService->isShopModule($depend)) {
$this->moduleShopService->installModule($depend);
} else {
Flash::setMessage("error", "Модуль не найден в IT Guild Framework Shop.");
return false;
}
} else {
if (!$this->moduleService->isActive($depend)) {
$this->moduleService->setActiveModule($depend);
}
$dependenceArray = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/get_all_dependencies/' . $themeInfo['slug']);
$dependenceArray = json_decode($dependenceArray->getBody()->getContents(), true);
foreach ($dependenceArray as $depend) {
if (!$this->moduleService->isInstall($depend)) {
if (!$this->moduleShopService->existsInModuleShop($depend)) {
Flash::setMessage('error', "Модуль $depend не найден в IT Guild Framework Shop.");
return false;
}
}
}
if (!$this->moduleService->recursiveActivateDependencies($dependenceArray)){
return false;
}
$activeTheme->value = getConst($theme);
$activeTheme->save();
return true;
}