Menu systém - Core třídy
Dokumentace hlavních tříd pro práci s menu systémem. Menu systém se skládá ze dvou hlavních tříd: Menu pro správu celých menu a MenuNode pro práci s jednotlivými uzly.
- Třída Menu - správa celých menu struktur
- Třída MenuNode - práce s jednotlivými uzly
Třída Menu
Namespace: Petrovo\Menu\Menu
Třída pro správu celých menu struktur. Hlavní funkcionalita je duplikace kompletního menu včetně všech uzlů a jazykových dat.
Klíčové metody
Menu::duplicate(int $menuId): ?array
Vytvoří kompletní kopii celého menu včetně všech uzlů a jazykových variant.
Parametry:
$menuId- ID menu k duplikaci
Návratová hodnota:
array|null- pole s informacemi o novém menu nebonullpři chybě
Struktura návratového pole:
php [
'new_menu_id' => 123, // ID nového menu
'new_base_node_id' => 456, // ID základního uzlu
'name' => 'Hlavní menu (copy 20.07.2025 14:30:15)'
]
Příklad použití:
php use Petrovo\Menu\Menu;
result = Menu::duplicate(5);
if (result) {
echo "Nové menu vytvořeno s ID: " . result['new_menu_id'];
echo "Základní uzel: " .result['new_base_node_id'];
} else {
echo "Duplikace se nezdařila";
}
Vnitřní metody
generateMenuAndBaseNode(object $menu): array
Vytvoří nový záznam menu a jeho základní uzel (base_node).
Důležité:
- Každé menu má základní uzel (base_node), který nemá jazykové překlady
- Základní uzel slouží jako kotva pro
parent_idprvků první úrovně - Umožňuje snadné přesouvání a řazení položek první úrovně
- Základní uzel se nikdy nezobrazuje ve frontend výstupu
Proces vytvoření:
- Vytvoří nový záznam v tabulce
menu - Vytvoří základní uzel (
parent_id = null) - Aktualizuje closure table procedurou
menu_add_node - Propojí menu se základním uzlem (
base_node_id)
Použití v administraci
MenusController
Třída Menu se používá v administračním rozhraní prostřednictvím MenusController.php.
Základní operace
Vytvoření nového menu:
public function new(): void {
// Vytvoří nové menu
$sql = "INSERT INTO menu (web_id, name) VALUES (?, ?)";
DB::query(sql, [WEB, name]);
$menuId = DB::$insertId;
// Vytvoří základní uzel
$baseNodeId = MenuNode::create($menuId, null);
// Propojí menu se základním uzlem
$sql = "UPDATE menu SET base_node_id = ? WHERE id = ?";
DB::query($sql, [$baseNodeId, $menuId]);
}
Duplikace menu:
public function duplicate(): void {
$menuId = array_get_int(_GET, 'id', 0);
$result = Menu::duplicate($menuId);
if ($result) {
Message::success('{S Menu was duplicated}');
} else {
Message::error('{S Menu could not be duplicated}');
}
redirect($this->urlListing());
}
Smazání menu:
public function delete(): void {
$menuId = array_get_int(_GET, 'id', 0);
// Jednoduché SQL DELETE - databáze řeší CASCADE
$sql = "DELETE FROM menu WHERE id = ?";
DB::query($sql, [$menuId]);
if (DB::$affectedRows > 0) {
Message::success('{S Menu was deleted}');
} else {
Message::error('{S Menu could not be deleted}');
}
}
Jak funguje duplikace menu
1. Načtení zdrojového menu
- Načte základní informace o menu (web_id, name, base_node_id)
- Pokud menu neexistuje, vrátí
null
2. Vytvoření nové struktury
- Vytvoří nový záznam v
menus timestampem - Vytvoří nový základní uzel
- Propojí menu se základním uzlem
3. Duplikace stromu uzlů
- Načte kompletní strom pomocí
menu_get_tree_all() - Projde všechny uzly a vytvoří jejich kopie
- Mapuje staré ID na nové ID (
$nodeMap) - Zachovává hierarchickou strukturu
4. Duplikace jazykových dat
- Pro každý uzel zkopíruje všechny jazykové varianty
- Zachovává JSON data v
menu_node_lang.data - Kopíruje viditelnost (
is_hide) pro každý jazyk
5. Aktualizace closure table
- Používá proceduru
menu_add_node()pro správnou hierarchii - Automaticky spočítá všechny cesty v
menu_node_path
Transakční bezpečnost
Celá operace duplikace probíhá v databázové transakci:
DB::beginTransaction();
try {
// Duplikace menu...
DB::commit();
return result;
} catch (Exceptione) {
DB::rollback();
throw $e;
}
Pokud dojde k chybě v jakékoli části, všechny změny se vrátí zpět.
Konvence pojmenování
- Původní menu: "Hlavní menu"
- Duplikát: "Hlavní menu (copy 20.07.2025 14:30:15)"
Timestamp zajišťuje jedinečnost názvů při více duplikacích.
Vztah k ostatním třídám
Menu (správa celých menu)
├── MenuNode (správa jednotlivých uzlů)
├── MenusController (admin rozhraní)
└── DB (databázové operace)
Třída Menu je vysokoúrovňové API pro práci s celými menu strukturami, zatímco MenuNode se zaměřuje na detailní operace s jednotlivými uzly.
MenuNode - Správa uzlů menu
MenuNode třída poskytuje kompletní API pro práci s jednotlivými uzly menu systému. Zahrnuje CRUD operace, manipulaci se stromovou strukturou a vícejazyčnou podporu.
Namespace: Petrovo\Menu\MenuNode
Hlavní metody pro práci s uzly
MenuNode::get(int $nodeId, string $lang = DEFAULT_LANG_WEB): ?array
Načte jeden uzel menu s jeho jazykovými daty.
Parametry:
$nodeId- ID uzlu$lang- kód jazyka (výchozí DEFAULT_LANG_WEB)
Návratová hodnota:
array|null- formátovaná data uzlu nebonullpokud uzel neexistuje
Struktura návratového pole:
[
'id' => 123,
'parent_id' => 45,
'level' => 2,
'order' => 3,
'name' => 'Název položky',
'is_hide' => false,
'breadcrumbs' => [1, 45],
'title' => 'Alternativní název',
'href' => '/cesta-na-stranku',
'href_same' => false,
'new_window' => false,
'attr_class' => 'css-trida',
'attr_id' => 'css-id',
'seo_title' => 'SEO titulek',
'seo_keywords' => 'klíčová, slova',
'seo_description' => 'SEO popis',
'text' => 'Obsah stránky',
'multilingual' => ['name', 'title', 'is_hide', 'href', ...]
]
MenuNode::create(int $menuId, ?int $parentId, array $langData = []): int
Vytvoří nový uzel menu s vícejazyčnými daty.
Parametry:
$menuId- ID menu$parentId- ID rodiče (null pro první úroveň pod base_node)$langData- pole jazykových dat indexované kódem jazyka
Struktura $langData:
$langData = [
'cs' => [
'name' => 'Český název',
'is_hide' => false,
'data' => [
'title' => 'Český titulek',
'href' => '/ceska-cesta',
'seo_title' => 'Český SEO titulek'
// další data...
]
],
'en' => [
'name' => 'English name',
'is_hide' => false,
'data' => [
'title' => 'English title',
'href' => '/english-path',
'seo_title' => 'English SEO title',
...
]
]
];
Návratová hodnota:
int- ID nově vytvořeného uzlu
Příklad použití:
use Petrovo\Menu\MenuNode;
$langData = [
'cs' => [
'name' => 'O nás',
'is_hide' => false,
'data' => ['href' => '/o-nas',
'title' => 'Informace o společnosti']
]
];
nodeId = MenuNode::create(5, 12,langData);
echo "Vytvořen uzel s ID: $nodeId";
MenuNode::update(int $nodeId, array $langData = []): bool
Aktualizuje existující uzel s novými jazykovými daty.
Pozor: Base node (základní uzel) se nikdy neaktualizuje jazykovými daty!
MenuNode::move(int $nodeId, ?int $newParentId): bool
Přesune uzel pod nového rodiče. Automaticky aktualizuje closure table.
MenuNode::delete(int $nodeId): bool
Smaže uzel a všechny jeho potomky (CASCADE DELETE).
Metody pro manipulaci s pořadím
MenuNode::changeOrder(int $nodeId, float $newOrder): bool
Změní pořadí uzlu mezi sourozenci a automaticky přeřadí všechny sourozence.
MenuNode::moveUp(int $nodeId): bool / MenuNode::moveDown(int $nodeId): bool
Posune uzel o jednu pozici nahoru/dolů mezi sourozenci.
Metody pro viditelnost
MenuNode::setVisibility(int $nodeId, string $lang, bool $isHidden): bool
Nastaví viditelnost uzlu a všech jeho potomků v konkrétním jazyce.
Pomocné metody
MenuNode::formatNode(object $node): array
Formátuje surová data z databáze do standardizovaného pole s rozdělenými JSON daty.
Důležité vlastnosti:
- Parsuje JSON z
menu_node_lang.data - Definuje vícejazyčná pole v
multilingualklíči - Převádí typy dat (int, bool)
- Zpracovává breadcrumbs jako pole integerů
MenuNode::getParentId(int $nodeId): ?int
Vrací ID rodiče uzlu nebo null pro uzly první úrovně.
MenuNode::reorderSiblings(?int $parentId): void
Přeřadí všechny sourozence pod stejným rodičem (odstraní mezery v číslování).
Administrační struktura - Data endpoint
Menus/structure endpoint
Speciální datový endpoint pro načtení kompletní struktury menu pro administraci.
URL: Data\get('Menus/structure?' . http_build_query($query))
Parametry:
id- ID menu
Použití v MenusNodesController:
query['id'] = this->menuId;
items = Json\decode(Data\get('Menus/structure?' . http_build_query(query)));
MenuTreeBuilder třída
Pomocná třída pro sestavení administrační struktury menu.
MenuTreeBuilder::fetchRawTree(int $menuId): array
Načte surová data pomocí CALL menu_get_tree_all(?).
MenuTreeBuilder::groupNodesByLanguage(array $rawData): array
Seskupí plochá data podle ID uzlu a připojí všechny jazykové varianty.
MenuTreeBuilder::enrichNodeForDisplay(array $node): array
Obohacuje uzel o data potřebná pro zobrazení v administraci:
Přidané vlastnosti:
level_visual- vizuální odsazení (bullet pointy)name_default- název v hlavním jazycetranslations- přehled překladůid_class- CSS třídy a IDactive_languages- jazyky kde je uzel viditelnýhref_same- zda má stejný href ve všech jazycíchisPage/pageExists- zda odkazuje na existující stránkushowHref/showPage- zkrácené URL pro zobrazeníactions- dostupné akce (up, down, before, after, child)
Akce dostupné v administraci
MenusNodesController poskytuje tyto operace:
listing()
Zobrazí strukturu menu s všemi jazykovými variantami a dostupnými akcemi.
new() / edit()
Formuláře pro vytváření/editaci uzlů s podporou všech jazyků.
delete()
Smazání uzlu včetně všech potomků.
moveUp() / moveDown()
Přesunutí uzlu mezi sourozenci.
toggleVisibility()
Přepnutí viditelnosti uzlu v konkrétním jazyce.
Vícejazyčná pole
Systém automaticky rozpoznává vícejazyčná pole podle seznamu v formatNode():
$multilingualFields = 'name|title|is_hide|href|seo_title|seo_keywords|seo_description|text';
V administraci se pak pole zpracovávají s suffixem jazyka:
- name_cs, name_en
- title_cs, title_en
- href_cs, href_en (pokud není href_same)
Speciální funkce
Automatické vytváření stránek
Pokud je při ukládání uzlu zaškrtnuto create_page, systém automaticky vytvoří odpovídající stránku s stejným názvem a href.
Konverze href
Metoda convertHref() automaticky převádí názvy na URL-friendly formát:
- Převod na ASCII
- Odstranění nepovolených znaků
- Zpracování GET parametrů
- Zachování externích URL a JavaScriptu
Base node koncept
- Každé menu má base_node (základní uzel)
- Base node se nikdy nezobrazuje na frontendu
- Slouží jako kotva pro
parent_idprvků první úrovně - Nemá jazykové překlady v
menu_node_lang - Umožňuje snadné přesouvání a řazení první úrovně
Tento koncept zajišťuje konzistentní strukturu a umožňuje efektivní manipulaci se stromem menu.