За нас

Блоковете в страница са независими части информация, преместваеми в рамките съдържанието на всяка страница, които позволяват вграждането и позиционирането на отделни функционалности и части информация в различните редактируеми елементи на страницата.
Реализацията е свързана с 3 таблици
block_types дефинира глобално наличните типове.
page_blocks казва: този тип блок е разрешен за този сайт/страница.
page_blocks_data казва: този разрешен блок е реално включен в страница X, на позиция Y.
block_typesОписва глобалните типове блокове и техните зависимости.
| Поле | Тип | Описание |
|---|---|---|
block_type_id |
INT AUTO_INCREMENT | Уникален идентификатор на типа блок |
block_key |
VARCHAR(50) | Уникален код на типа (напр. hero, custom, gallery) |
block_name |
VARCHAR(100) | Име за показване в админ панела |
description |
TEXT | Подробно описание на предназначението на типа |
icon_class |
VARCHAR(50) | Bootstrap икона за визуализация в админ интерфейса |
css_assets |
TEXT | Външни CSS ресурси (от cms_assets.php), разделени със запетая |
js_assets |
TEXT | Външни JS зависимости |
php_init |
TEXT | Глобален PHP код за инициализация на типа блок |
editable_fields |
JSON | Определя кои полета поддържа блокът (напр. ["init","html","css","js","php","data"]) |
created_at |
TIMESTAMP | Дата на създаване |
updated_at |
TIMESTAMP |
Последна промяна |
page_blocksОписва кои типове блокове са разрешени за конкретен сайт и/или страница (каталог на достъпните блокове).
| Поле | Тип | Описание |
|---|---|---|
blk_id |
INT AUTO_INCREMENT | Уникален идентификатор на разрешения блок |
site_id |
INT DEFAULT 0 | ID на сайта (0 = публичен, достъпен за всички сайтове) |
page_n |
INT DEFAULT 0 | ID на страницата, за която блокът е разрешен (0 = глобален в сайта) |
block_type_id |
INT NOT NULL | Връзка към block_types |
block_key |
VARCHAR(100) | Уникален ключ за блока (напр. promo_banner, custom_footer) |
block_name |
VARCHAR(100) | Име за админ интерфейса |
config_json |
JSON | Настройки/параметри за блока |
| access_level | INT | Ниво на достъп, необходимо за използване на блока. 0 = общодостъпен (гости), 1+ = минимално ниво на потребителя, което му позволява да вижда/редактира блока. |
sort_order |
INT DEFAULT 0 | Ред на показване в админ списъка (не влияе на рендеринга) |
is_active |
TINYINT DEFAULT 1 | Статус на блока (1 = активен, 0 = неактивен) |
created_at |
TIMESTAMP | Дата на създаване |
updated_at |
TIMESTAMP | Последна промяна |
page_blocks_dataСъдържа реалните инстанции на блокове, включени от потребителя в страниците и определя реда им на визуализация.
| Поле | Тип | Описание |
|---|---|---|
data_id |
INT AUTO_INCREMENT | Уникален идентификатор на инстанцията |
blk_id |
INT NOT NULL | Връзка към page_blocks (кой блок е инстанциран) |
site_id |
INT NOT NULL | ID на сайта |
page_n |
INT NOT NULL | ID на страницата |
lang_id |
INT DEFAULT 0 | Езикова версия |
data_json |
JSON | Съдържание на блока (init, css, html, php, js, data и др.) |
sort_order |
INT NOT NULL | Редът, в който блокът се визуализира в рамките на страницата. |
block_types , page_blocks и page_blocks_data .Таблицата block_types дефинира глобалните типове блокове и техните зависимости (CSS, JS, init PHP, template файлове и конфигурационни полета).
Таблицата page_blocks описва кои блокове от даден тип са разрешени за конкретен сайт или страница и служи като каталог, от който потребителят избира.
Таблицата page_blocks_data съдържа реалните инстанции на блоковете, които потребителят е включил на страница, с техните данни (data), параметри и позиция (sort_order).
При визуализация CMS-ът зарежда активните инстанции от page_blocks_data, изпълнява init логиката и преобразува всеки запис в стандартен SSR блок със структура:
$block = array(
'id' => ...,
'type' => 'block_type',
'data' => array(...)
);
Всички блокове се подават към темата чрез $page['blocks'] и са достъпни и в основния поток:
$page['streams']['main']['items']
В темата всеки блок се достъпва чрез обхождане:
foreach ($page['streams']['main']['items'] as $block) {
if ($block['type'] === 'experience') {
$data = $block['data'];
echo $data['title'];
echo $data['items'][0]['value'];
}
}
HTML визуализацията се извършва чрез template файлове (напр. blocks/experience.php), които получават директен достъп до $block['data'].
Наличен е универсален loader render_engine_file(), който рендерира template файлове (HTML/PHP) с подадените данни и поддържа {{placeholders}}.
...Блокове в страница (page_blocks)
Функция fetch извлича стойността на заявката query съответно като обект, асоциативен масив и стандартен масив с числови и асоциативни стойности.
function fetch($type, $db_query=false){Максофт е основа на headless CMS система. Целта на новия рендерер на теми е да осигури лесна адаптация и визуализация на сайтове, създадени както за legacy Maksoft CMS, така и за нови дизайни и теми, писани за Maksoft CMS, WordPress, Joomla и други системи.
Темите работят върху стандартизиран слой от данни (ViewData), предоставен от CMS. Темата не комуникира директно с базата данни или CMS класове.
Създаването на нова тема започва със създаване на директория в /themes/ms/... и записване на основния index.php файл в нея.
index.php зарежда engine bootstrap файла /themes/ms/_bootstrap.php, получава готовите ViewData променливи и използва предоставения обект $o_page за достъп до CMS hooks.
Темата се регистрира в CMS чрез запис в таблица Templates. Това я прави достъпна за конкретен сайт (SiteID) или за всички сайтове (SiteID = 0).
CSS/JS активите се управляват централизирано чрез cms_assets.php, което предотвратява дублиране на зависимости и осигурява контрол на версиите.
/themes/themes е стандартният слой за рендериране на Maksoft CMS.
/themes не заменя legacy /Templates, а съществува паралелно с него за backward compatibility.
CMS подава ViewData → Theme engine рендерира → Theme определя структурата
view ├ context ├ auth ├ user ├ user_context ├ site ├ page │ └ streams │ ├ main │ │ └ items[] │ └ subpages │ └ items[] └ theme
streams.main.items съдържа основните content blocks на страницата.
streams.subpages съдържа relation stream с подстраниците. Темата решава къде да го визуализира.
/themes
/ms
/wp
/joomla
Всеки engine определя:
/themes/ms/themes/ms
_bootstrap.php
theme.json
cms_assets.php
functions.php
/helpers
block_dom.php
meta_tags.php
footer_inc.php
breadcrumbs.php
/blocks
text.php
image.php
/components
menu.php
navigation.php
subpages.php
/base
theme.json
/none
theme.json
index.php
meta_tags.php
footer_inc.php
/blocks
text.php
image.php
/components
menu.php
navigation.php
subpages.php
/layout
head.php
header.php
footer.php
scripts.php
/partials
menu.php
breadcrumbs.php
banners.php
/assets
/css
/js
theme.js
/blocks
text.js
image.js
/components
subpages.js
/images
README.md
Blocks са основните content елементи на страницата.
Те се намират в:
$page['streams']['main']['items']
Всеки block съдържа:
[
'id' => 1,
'type' => 'text',
'data' => [...],
'dom' => [
'data-block' => 'text',
'data-id' => '1',
'data-editable' => '0'
]
]
Blocks се рендерират чрез:
BlockResolver чете $page['streams']['main']['items'], намира подходящия template и връща HTML.
theme/blocks/{pageType}/{block}.php
theme/blocks/{block}.php
themes/ms/blocks/{pageType}/{block}.php
themes/ms/blocks/{block}.php
Components са визуални елементи, които не са задължително част от основния body content.
Примери:
Components позволяват на темата да контролира къде точно се рендерира даден елемент.
Subpages не се добавят автоматично в streams.main.items.
Официалният source за подстраници е:
$page['streams']['subpages']
Примерна структура:
$page['streams']['subpages'] = [
'id' => 'children',
'name' => 'subpages',
'kind' => 'relation',
'binding' => 'strong',
'role' => 'subpages',
'display' => [
'enabled' => 1,
'layout' => 'auto',
'columns' => 3,
'elements' => ['image', 'title', 'excerpt'],
'links' => 'full',
'limit' => null,
'order' => 'manual'
],
'items' => [...]
];
Темата рендерира subpages чрез:
Това позволява на темата да избере дали подстраниците да се покажат:
Default renderer-ът за subpages се намира в:
/themes/ms/components/subpages.php
Темата може да го презапише чрез:
theme/components/subpages.php
main_content и sub_pages са отделни render hooks.
Препоръчителна структура в тема:
<main>
<?= $o_page->hook('main_content') ?>
<?= $o_page->hook('phpcode') ?>
<?= $o_page->hook('sub_pages') ?>
<?= $o_page->hook('pageurl') ?>
</main>
Така темата запазва контрол върху реда и мястото на отделните секции.
CMS добавя стандартни DOM markers:
data-block data-id data-editable
DOM markers се генерират чрез helper:
block_dom($block)
Пример:
<section<?= block_dom($block) ?>>
...
</section>
Резултат:
<section data-block="text" data-id="1" data-editable="0">
...
</section>
DOM markers са официалният JS API между CMS и темата.
Темите могат да инициализират JS поведение чрез DOM markers.
document.querySelectorAll("[data-block]").forEach(function(el) {
var type = el.getAttribute("data-block");
if (window.Theme && Theme.blocks && typeof Theme.blocks[type] === "function") {
Theme.blocks[type](el);
}
});
Пример:
window.Theme = window.Theme || {};
Theme.blocks = Theme.blocks || {};
Theme.blocks.text = function(el) {
console.log("Text block init", el.getAttribute("data-id"));
};
За components може да се използва отделен namespace:
window.Theme = window.Theme || {};
Theme.components = Theme.components || {};
Theme.components.subpages = function(el) {
console.log("Subpages component init", el.getAttribute("data-id"));
};
Assets се управляват на две нива.
/themes/ms/cms_assets.php
Дефинира споделени зависимости:
theme/assets/css theme/assets/js theme/assets/images
Темите не трябва да enqueue-ват assets директно в templates. Те използват asset registry и hooks.
theme.jsontheme.json е незадължителен конфигурационен файл. CMS използва overwrite cascade.
Използва се първият намерен theme.json, тръгвайки от директорията на темата нагоре.
/themes/ms/base/none/theme.json /themes/ms/base/theme.json /themes/ms/theme.json /themes/theme.json
Maksoft Template Language (MTL) е compatibility и extension слой върху стандартните PHP templates.
MTL позволява legacy PHP include файлове като edit.php, PageURL и phpCode да декларират JavaScript, CSS и други embedded code blocks без да нарушават нормалното PHP изпълнение.
MTL не заменя PHP. Legacy Maksoft CMS PHP остава валиден execution layer.
<!-- @push('js') -->
<script>
$j(document).ready(function(){
// Legacy JavaScript code
});
</script>
<!-- @endpush -->
MTL-aware engine премества този блок към:
<!-- @asset('jquery') -->
<!-- @asset('jquery-alias-j') -->
<!-- @asset('fancybox') -->
Engine behavior:
$o_page->add_asset('jquery');
$o_page->add_asset('jquery-alias-j');
$o_page->add_asset('fancybox');
/themes/ms/....index.php./themes/ms/_bootstrap.php.$o_page->hook('main_content') за основните blocks.$o_page->hook('sub_pages'), ако темата трябва да показва подстраници./blocks само за основни content blocks./components за menu, navigation, subpages и други relation/render components.block_dom($block) за DOM markers.Theme.blocks и/или Theme.components.streams.main.items.streams.subpages.HTTP Request
↓
page.php
↓
loader.php
↓
$o_page->init_page_blocks()
↓
PageData
↓
ThemeMapper
↓
ViewData
↓
resolveTheme()
↓
include theme/index.php
↓
$o_page->hook('main_content')
↓
BlockResolver
↓
block templates
↓
$o_page->hook('sub_pages')
↓
Subpages component renderer
↓
HTML output
↓
page cache
Основният принцип остава:
CMS управлява данните → Theme управлява HTML и визуализацията...Създаване на теми (темплейти)
page | post | product | offer | testimonial | faq | system | stream_itemhtmlsections е асоциативен масив със стандартни и разширяеми semantic slots. Секциите се извличат от HTML блокове с класове:
<section class="section section-hero">...</section>
<section class="section section-solution">...</section>
<section class="section section-faq">...</section>
Примерна структура:
$page['content']['sections'] = [
'hero' => '',
'main' => '',
'intro' => '',
'problem' => '',
'solution' => '',
'benefits' => '',
'features' => '',
'proof' => '',
'offer' => '',
'action' => '',
'faq' => '',
'summary' => '',
'content' => '',
'related' => '',
'gallery' => '',
'specs' => '',
'price' => '',
'delivery' => '',
'testimonial' => '',
'reviews' => '',
'logos' => '',
'notice' => '',
'error' => '',
'success' => ''
];
section-* блоковете.content.html остава наличен непроменен за обратна съвместимост.Пример за ползване в тема:
<?= $page['content']['sections']['hero'] ?>
<?= $page['content']['sections']['main'] ?>
<?= $page['content']['sections']['solution'] ?>
<?= $page['content']['sections']['action'] ?>
local | external | proxyМасив с ценови обекти.
Масив от:
Масив от Stream обекти.
Потоците се рендерират последователно от темата.
relation | group | feed | search | customstrong | weak | virtualsubpages | group_pages | feed_items | search_results | related | customМасив от StreamFeed.
db | http | apiВсички items в streams използват единен модел Card.
page | article | product | place | customdb | httpstrong | weak | virtualEngine-specific данни (например extensions.ms)
Поле в PAGE, което указва асоциирана група.
Темата може да пропуска, но редът е препоръчителен.
content.html остава пълният HTML източникcontent.sections е semantic extraction layer за темитеfeed.map.json съдържа дефиниции за всяка таблица, от която се подава информация чрез Feed API. Позволява настройка на полетата, връзките (JOIN), TTL, филтри и изчисляеми стойности.
{
"pages": {
"table": "pages",
"site_key": "SiteID",
"ttl": 120,
"access_filter": "pages.SecLevel <= {ACCESS_LEVEL}",
"fields": [
"*",
"CONCAT('/page.php?n=', n, '') AS long_url",
"date_modified AS updated_at"
],
"fields_to_exclude": [
"PageURL"
],
"computed": {
"url": "feed_pageurl(n)",
"lastmod": "feed_date('Y-m-d', date_modified)"
},
"joins": {
"+text": {
"type": "LEFT",
"table": "pages_text",
"on": "pages.n = pages_text.n",
"fields": ["lang_id", "title", "content"],
"nested": true
}
},
"order": {
"field": "sort_n",
"direction": "ASC"
}
}
}
| Ключ | Тип | Описание |
|---|---|---|
| table | string | Име на основната таблица в базата данни. |
| site_key | string | Име на полето, което идентифицира сайта (например SiteID). |
| ttl | integer | Време за живот на кеша (в секунди). |
| access_filter | string | Филтър за ниво на достъп, използващ променливата {ACCESS_LEVEL}. |
| fields | array | Списък от полета, които ще бъдат включени в SELECT заявката. Поддържа * за всички полета. |
| fields_to_exclude | array | Списък от полета, които ще бъдат премахнати от резултата. |
| computed | object | Дефинира изчисляеми полета чрез функции от feed.safe.func.php. |
| joins | object | Дефинира JOIN връзки с други таблици (LEFT, INNER, RIGHT). Поддържа вложени резултати. |
| order | object | Дефинира сортиране по подразбиране. |
{
"articles": {
"table": "articles",
"site_key": "SiteID",
"fields": ["*", "author", "date_published"],
"computed": {
"url": "feed_concat('/articles/', slug)"
}
},
"gallery": {
"table": "gallery",
"site_key": "SiteID",
"fields": ["*", "image_path", "caption"],
"order": { "field": "sort_n", "direction": "ASC" }
}
}
/feed/pages /feed/pages?status=1 /feed/pages?preview>100 /feed/pages?title~услуги /feed/pages?order_by=date_modified&order_dir=DESC /feed/pages?debug=1
{
"meta": {
"table": "pages",
"site_id": 2,
"limit": 50,
"offset": 0,
"count": 2,
"access_level": 0,
"result": "ok",
"debug_sql": "SELECT * FROM `pages` WHERE `SiteID`=2 ..."
},
"data": [
{
"n": "2",
"name": "Начало",
"url": "https://www.maksoft.bg/",
"lastmod": "2025-07-26"
}
]
}
<?php
$json = file_get_contents('https://maksoft.net/feed/pages?limit=10');
$data = json_decode($json, true);
foreach ($data['data'] as $row) {
echo $row['name'] . " - " . $row['url'] . "<br>";
}
?>
...Feed Конфигурационен файлMaksoft CMS – Theme v1 Architecture дефинира ясна граница между engine логиката и theme представянето. Архитектурата гарантира:
Maksoft CMS – Theme v1 Pipeline
/engine
/app
/runtime
ThemeRuntime.php
LegacyExecution.php
/render
ShortcodeEngine.php
/extensions
LegacyPageUrlExtension.php
/theme
(future: ThemeBootstrap.php)
/themes
/ms
_bootstrap.php
/base
/none
index.php
/blocks
gallery.php
hero.php
cta.php
cms_assets.php
functions.php
page.php
↓
resolveTheme()
↓
load theme.json
↓
include theme index.php
↓
ThemeRuntime::boot()
↓
$o_page->hook(...)
↓
render_assets()
loader.php
↓
init_page_blocks()
↓
PageData
↓
ThemeMapper
↓
ViewData
↓
theme/index.php
↓
block templates
↓
HTML
↓
page cache
view ├ context ├ auth ├ user ├ user_context ├ site ├ page │ └ streams │ └ main │ └ blocks[] └ theme
foreach ($view['page']['streams']['main']['blocks'] as $block) {
include $view['theme']['dir'].'/blocks/'.$block['type'].'.php';
}
ThemeMapper добавя стандартни DOM markers за JS lifecycle:
data-block data-id data-editable
Theme JavaScript инициализира функционалност чрез:
document.querySelectorAll("[data-block]")
Semantic sections позволяват на редактора да маркира части от съдържанието според тяхната роля, без да променя структурата на страницата.
Редакторът продължава да работи в основното HTML съдържание на страницата, но при нужда може да огради важен блок със:
<section class="section section-hero">
<h1>Основно обещание на страницата</h1>
<p>Кратко пояснение за кого е страницата и какъв резултат предлага.</p>
</section>
Всеки section има две CSS class стойности:
section section-{име}
Пример:
<section class="section section-solution">
<h2>Нашето решение</h2>
<p>Описание на продукта, услугата или подхода.</p>
</section>
<section class="section section-hero">
<h1>Бърза поддръжка на компютри за малък бизнес</h1>
<p>Помагаме ви да работите спокойно, без забавяния и технически прекъсвания.</p>
</section>
<section class="section section-problem">
<h2>Кога имате нужда от сервиз?</h2>
<ul>
<li>Компютрите работят бавно.</li>
<li>Софтуерът често блокира.</li>
<li>Нямате човек, който да реагира бързо.</li>
</ul>
</section>
<section class="section section-solution">
<h2>Как помагаме?</h2>
<p>Предлагаме диагностика, ремонт, профилактика и абонаментна поддръжка.</p>
</section>
<section class="section section-action">
<h2>Имате нужда от помощ?</h2>
<p>Свържете се с нас за бърза консултация.</p>
</section>
Вътре в секциите могат да се използват стандартни HTML елементи:
h1, h2, h3pul, ol, listrong, bem, iaimgАко темата поддържа semantic sections, тя може да изведе отделни секции на специални места — например section-hero в hero зона, section-action до форма за контакт или section-faq преди финалния CTA.
Ако темата не ги поддържа, съдържанието пак остава валиден HTML и може да се покаже като обикновен текст на страницата.
...Семантични секции в страница (page semantic secionts)
Максофт е дигитална агенция със собствени продукти за изработка, поддръжка, SEO оптимизация и маркетинг на интернет сайтове от 1999 година. Ние сме SEO фирма със собствени продукти и услуги за управление на съдържание, SEO оптимизация, дигитален маркетинг и реклама на фирми от различни браншове.
Максофт има над 25 години опит в печатна и интернет реклама. Компанията е водещ вносител на рекламни материали.
...НачалоКакво е Максофт Нет система за управление на съдържанието на уеб сайт. Може ли да се инсталира, Как се прехвърля. Колко струва?
...Въпроси и коментари за Максофт Нет CMS
Настоящият раздел регламентира задълженията и правата на Максофт като Изпълнител и на клиента като Възложител по направени поръчки, както и правила за поддръжка.
Този сайт е предназначен само за юридически лица- фирми регистрирани на територията на страна члена на Европейския съюз или извън него.
Разглеждайки този сайт Вие декларирате, че представлявате законно регистрирана компания (фирма).
В хода на работа с този сайта, за изготвяне на калкулации и оферти, ще Ви бъде изискан уникален идентификационен номер (булстат) на компанията (фирмата), която представлявате.
Този сайт не събира информация по смисъла на чл.2, ал.1 от Закона за защита на личните данни и не работи с частни лица.
Поръчките в този сайт се изпълняват съгласно Закона за задълженията и договорите.
...Общи условияМаксофт е дигитална агенция със собствени продукти за изработка, поддръжка, SEO оптимизация и маркетинг на интернет сайтове от 1999 година. Ние сме SEO фирма със собствени продукти и услуги за управление на съдържание, SEO оптимизация, дигитален маркетинг и реклама на фирми от различни браншове.
Максофт има над 25 години опит в печатна и интернет реклама. Компанията е водещ вносител на рекламни материали.