diff .cms/mod/menu.mod.php @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.cms/mod/menu.mod.php	Fri Oct 11 22:40:23 2024 +0000
@@ -0,0 +1,749 @@
+<?php
+
+$cms["modules"]["menu.mod.php"] = array(
+    "name"        => "menu_module_name",
+    "description" => "menu_module_description",
+    "files"       => array(
+        ".cms/mod/menu.mod.php",
+        ".cms/css/menu.css",
+        ".cms/js/menu.js",
+        ".cms/lang/ru_RU.UTF-8/menu.mod.php",
+        ".cms/lang/en_US.UTF-8/menu.mod.php",
+        ".cms/lang/uk_UA.UTF-8/menu.mod.php",
+        ".cms/man/ru_RU.UTF-8/menu.mod.php.html",
+    ),
+);
+
+// Return if module disabled
+if ( ! empty( $cms["config"]["menu.mod.php"]["disabled"] ) ) {
+
+    return;
+
+} else {
+
+    if ( is_admin() ) {
+        hook_add_fn( "create_tables", "cms_menu_create_table" );
+        hook_add_fn( "admin",         "cms_menu_admin", 20 );
+        hook_add_fn( "admin_header",  "cms_menu_admin_header" );
+        hook_add_fn( "api",           "cms_menu_api", 20 );
+    }
+
+}
+
+function cms_menu_admin_header() {
+    global $cms;
+    $conf = $cms["config"]["menu.mod.php"]["menu"]["menu"];
+    if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) {
+        echo "<link rel=stylesheet href='{$cms['base_path']}css/menu.css'>";
+        echo "<script src='{$cms['base_path']}js/menu.js'></script>";
+    }
+}
+
+
+function cms_menu_api() {
+    global $cms;
+
+    if ( ! empty( $_POST["fn"] ) ) {
+        
+        switch ( $_POST["fn"] ) {
+
+            case "create_menu_item":
+
+                if ( empty( $cms["base"] ) ) {
+                    echo( json_encode( array(
+                        "info_text"  => __( "no_connect_db" ),
+                        "info_class" => "info-error",
+                        "info_time"  => 5000,
+                    ) ) );
+                    return;
+                }
+
+                $sort = 10;
+                // Пересортировываем имеющиеся
+                $pid = (int) $_POST["pid"];
+                $q = "SELECT mid FROM menu WHERE pid={$pid} ORDER BY `sort`";
+                if ( $r = mysqli_query( $cms["base"], $q ) ) {
+                    while ( $i = mysqli_fetch_assoc( $r ) ) {
+                        $q = "UPDATE menu SET `sort`={$sort} WHERE mid={$i['mid']}";
+                        mysqli_query( $cms["base"], $q );
+                        $sort += 10;
+                    }
+                }
+
+                $q = "INSERT INTO menu SET pid={$pid}, url='', sort={$sort}";
+                if ( $r = mysqli_query( $cms["base"], $q ) ) {
+                    $mid = mysqli_insert_id( $cms["base"] );
+                    echo( json_encode( array(
+                        "info_text"  => __( "created" ),
+                        "info_class" => "info-success",
+                        "info_time"  => 5000,
+                        "list"       => cms_menu_get_items_list(),
+                        "parents"    => cms_menu_get_parents_list(),
+                        "mid"        => $mid,
+                    ) ) );
+                    return;
+                } else {
+                    echo( json_encode( array(
+                        "info_text"  => __( "sql_error" ) . mysqli_error( $cms["base"] ),
+                        "info_class" => "info-error",
+                        "info_time"  => 5000,
+                    ) ) );
+                    return;
+                }
+            break;
+
+            case "get_menu_items":
+
+                if ( empty( $cms["base"] ) ) {
+                    echo( json_encode( array(
+                        "info_text"  => __( "no_connect_db" ),
+                        "info_class" => "info-error",
+                        "info_time"  => 5000,
+                    ) ) );
+                    return;
+                }
+
+                echo( json_encode( array(
+                    "list"       => cms_menu_get_items_list(),
+                    "parents"    => cms_menu_get_parents_list(),
+                ) ) );
+                return;
+
+            break;
+
+            case "del_menu_item":
+
+                if ( $mid = (int) $_POST["mid"] ) {
+                    cms_menu_del( $mid );
+                    
+                    cms_clear_cache();
+                    
+                    echo( json_encode( array(
+                        "info_text"  => __( "deleted" ),
+                        "info_class" => "info-success",
+                        "info_time"  => 5000,
+                        "list"       => cms_menu_get_items_list(),
+                        "parents"    => cms_menu_get_parents_list(),
+                    ) ) );
+                    return;
+                }
+            break;
+
+            case "save_menu_item":
+                
+                $mid       = (int) $_POST["mid"];
+                $pid       = (int) $_POST["pid"];
+                $old_pid   = (int) $_POST["old_pid"];
+                $id        = (int) $_POST["id"];
+                $sort      = (int) $_POST["sort"];
+                $title     = mysqli_real_escape_string( $cms["base"], $_POST["title"] );
+                $tag_title = mysqli_real_escape_string( $cms["base"], $_POST["tag_title"] );
+                $classes   = mysqli_real_escape_string( $cms["base"], $_POST["classes"] );
+                $url       = mysqli_real_escape_string( $cms["base"], $_POST["url"] );
+                $area      = mysqli_real_escape_string( $cms["base"], $_POST["area"] );
+                if ( $_POST["target"] === "true" ) {
+                    $target_blank = 1;
+                } else {
+                    $target_blank = 0;
+                }
+
+                $q = "UPDATE menu SET
+                        pid={$pid},
+                        id={$id},
+                        sort={$sort},
+                        title='{$title}',
+                        tag_title='{$tag_title}',
+                        class='{$classes}',
+                        url='{$url}',
+                        area='{$area}',
+                        target_blank={$target_blank}
+                      WHERE mid={$mid}";
+                if ( $r = mysqli_query( $cms["base"], $q ) ) {
+
+                    cms_clear_cache();
+                    
+                    $r = array(
+                        "ok"         => "true",
+                        "info_text"  => __( "updated" ), // FIXME: never fire
+                        "info_class" => "info-success",
+                        "info_time"  => 5000,
+                        //"list"       => cms_menu_get_items_list(),
+                        "parents"    => cms_menu_get_parents_list(),
+                    );
+                    if ( $pid != $old_pid ) {
+                        $r["list"] = cms_menu_get_items_list();
+                    }
+                    echo ( json_encode( $r ) );
+                    return;
+                } else {
+                    echo( json_encode( array(
+                        "ok"         => "false",
+                        "info_text"  => __( "update_properties_error" ),
+                        "info_class" => "info-error",
+                        "info_time"  => 5000,
+                    ) ) );
+                    return;
+                }
+
+            break;
+
+            case "get_search_pages_list":
+
+                if ( empty( $cms["base"] ) ) {
+                    echo( json_encode( array(
+                        "no_database"  => "<span class=no-database>" . __( "no_connect_db" ) . "</span>",
+                    ) ) );
+                    return;
+                }
+                
+                //$s = mysqli_real_escape_string( $cms["base"], $_POST["search"] );
+                //$s = str_replace( " ", "%", $s );
+                $s = preg_replace( "/\s/u", "", $_POST["search"] );
+                $s = preg_split( '//u', $s, -1, PREG_SPLIT_NO_EMPTY );
+                foreach( $s as $n => $ch ) {
+                    $s[$n] = mysqli_real_escape_string( $cms["base"], $ch );
+                }
+                $s = implode( "%", $s );
+                $html[] = array(
+                    "sort" => 2000000000,
+                    "html" => "<li data-id=0 data-url>" . __( "no_page" ) . "</li>"
+                );
+                // pages without blocks
+                $q = "SELECT id, title, url, pin FROM pages WHERE title LIKE '%{$s}%' OR url LIKE '%{$s}%' ORDER BY ( id + pin * 1000000000 ) DESC LIMIT 10";
+                if ( $res = mysqli_query( $cms["base"], $q ) ) {
+                    while ( $page = mysqli_fetch_assoc( $res ) ) {
+                        $title = htmlspecialchars( $page["title"] );
+                        $html[] = array(
+                            "sort" => $page["id"] + $page["pin"] * 1000000000,
+                            "html" => "<li data-id={$page['id']} data-url='{$page['url']}'>{$title}</li>"
+                        );
+                    }
+                }
+                // pages with blocks
+                $q = "SELECT id, title, url, pin FROM blocks_pages WHERE title LIKE '%{$s}%' OR url LIKE '%{$s}%' ORDER BY ( id + pin * 1000000000 ) DESC LIMIT 10";
+                if ( $res = mysqli_query( $cms["base"], $q ) ) {
+                    while ( $page = mysqli_fetch_assoc( $res ) ) {
+                        $title = htmlspecialchars( $page["title"] );
+                        $html[] = array(
+                            "sort" => $page["id"] + $page["pin"] * 1000000000,
+                            "html" => "<li data-id={$page['id']} data-url='{$page['url']}'>{$title}</li>"
+                        );
+                    }
+                }
+                cms_asort( $html );
+                $html = array_reverse( $html );
+                $list = "";
+                foreach( $html as $item ) {
+                    $list .= $item["html"];
+                }
+                echo( json_encode( array(
+                    "html" => $list,
+                ) ) );
+                return;
+            break;
+
+        }
+    }
+}
+
+function cms_menu_del( $mid ) {
+    global $cms;
+
+    // Recursively delete children items
+    $q = "SELECT mid FROM menu WHERE pid={$mid}";
+    if ( $res = mysqli_query( $cms["base"], $q ) ) {
+        while ( $r = mysqli_fetch_assoc( $res ) ) {
+            cms_menu_del( $r["mid"] );
+        }
+    }
+    
+    mysqli_query( $cms["base"], "DELETE FROM menu WHERE mid=$mid" );
+
+}
+
+function cms_menu_get_items_list( $pid = 0 ) {
+    global $cms;
+
+    if ( empty( $cms["base"] ) ) {
+        echo( json_encode( array(
+            "no_database"  => "<span class=no-database>" . __( "no_connect_db" ) . "</span>",
+        ) ) );
+        return;
+    }
+
+    $list = "";
+
+    $q = "SELECT * FROM menu WHERE pid={$pid} ORDER BY sort, title";
+    if ( ! $res = mysqli_query( $cms["base"], $q ) ) {
+
+        return "<span class=no-tables>" . __( "no_tables_db" ) . "</span>";
+
+    } else {
+
+        // Read template settings
+        cms_template_load_settings();
+
+        // Menu Areas
+        $area_options   = "";
+        $tpl = $cms["config"]["template.mod.php"]["template"];
+        if ( isset( $cms["menu_areas"] ) ) {
+            foreach ( $cms["menu_areas"] as $area => $a ) {
+                //- удалить после перехода на $cms["menu_areas"]["header_en"] = "Header En";
+                if ( is_array( $a ) && isset( $a["title"] ) ) {
+                    $title = $a["title"];
+                } elseif ( is_string( $a ) ) {
+                    $title = $a;
+                }
+                $area_options .= "<div class=option value='{$area}'>{$title}</div>";
+            }
+        }
+
+        // Translations
+        $tr_title              = __( "title" );
+        $tr_area               = __( "area" );
+        $tr_no_area            = __( "no_area" );
+        $tr_classes            = __( "classes" );
+        $tr_sort               = __( "sort" );
+        $tr_save               = __( "save" );
+        $tr_delete             = __( "delete" );
+        $tr_append             = __( "append_item" );
+        $tr_prop               = __( "properties" );
+        $tr_parent             = __( "parent" );
+        $tr_no_parent          = __( "no_parent" );
+        $tr_placeholder        = __( "placeholder_hint" );
+        $tr_no_page            = __( "no_page" );
+        $tr_search             = __( "search" );
+        $tr_tag_title          = __( "hint" );
+        $tr_new_window         = __( "target_blank" );
+        $tr_page               = __( "page" );
+        $tr_page_deleted       = __( "deleted_page" );
+        $tr_menu_item          = __( "no_page" );
+
+        while ( $item = mysqli_fetch_assoc( $res ) ) {
+
+            // Children Items
+            $sublist = cms_menu_get_items_list( $item["mid"] );
+            if ( $sublist ) {
+                $sublist = "<div class=items-grid>{$sublist}</div>";
+            }
+
+            if ( $item["pid"] == 0 ) {
+
+                // area title
+                //- подправить после перехода на $cms["menu_areas"]["header_en"] = "Header En";
+                if ( empty( $item["area"] ) ) {
+                    $area_title = $tr_no_area;
+                } elseif ( isset( $cms["menu_areas"][ $item['area'] ] ) && is_string( $cms["menu_areas"][ $item['area'] ] ) ) {
+                    $area_title = $cms["menu_areas"][ $item['area'] ];
+                } elseif ( isset( $cms["menu_areas"][ $item['area'] ] ) && is_array( $cms["menu_areas"][ $item['area'] ] ) ) {
+                    $area_title = $cms["menu_areas"][ $item['area'] ]['title'];
+                } else {
+                    $area_title = $item['area'];
+                }
+
+                $list   .= "
+<div>
+
+    <div class=menu data-item={$item['mid']}>
+
+        <input name=title type=text value='{$item['title']}'>
+        <input name=sort type=text value='{$item['sort']}' data-sort='{$item['sort']}'>
+
+        <div class=menu-buttons>
+            <div class=prop>{$tr_prop}</div>
+            <div class=append>{$tr_append}</div>
+            <div class=save><span>{$tr_save}</span></div>
+            <div class=del>{$tr_delete}</div>
+        </div>
+
+        <div class=menu-prop>
+            <div class='area title'>{$tr_area}:</div>
+
+            <div class=area-select-grid>
+                <div class=field-select-menu data-menu-area='{$item['area']}'>
+                    <div class=value>{$area_title}</div>
+                    <div class=icon></div>
+                </div>
+                <div class=field-options>
+                    <div class=option value=''>{$tr_no_area}</div>
+                    {$area_options}
+                </div>
+            </div>
+
+            <div class='classes title'>{$tr_classes}:</div>
+            <input name=classes type=text value='{$item['class']}'>
+        </div>
+
+    </div>
+
+    {$sublist}
+
+</div>";
+
+            } else {
+                
+                $disabled_url = "disabled";
+
+                if ( $item["id"] === "0" ) {
+                    $item["select_title"] = $tr_no_page;
+                    $disabled_url = "";
+                    // free item
+                    if ( ! empty( $item["title"] ) ) {
+                        $item["link_title"] = $item["title"];
+                    } else {
+                        $item["link_title"] = $tr_menu_item;
+                    }
+                } else {
+                    // Дернуть модуль страниц и модуль страниц с блоками
+                    // чтобы предоставили информацию
+                    $cms["menu.mod.php"]["item"] = &$item;
+                    do_hook( "mod_menu_item" );
+
+                }
+
+                // Wrap title in URL
+                if ( $item["id"] === "0" && empty( $item['url'] ) ) {
+                    $link = "<a target=_blank>{$item["link_title"]}</a>";
+                } elseif ( $item["id"] === "0" && ! empty( $item['url'] ) ) {
+                    $link = "<a href='{$item['url']}' target=_blank>{$item["link_title"]}</a>";
+                } else {
+                    $link = "<a href='{$cms['base_path']}{$item['url']}' target=_blank>{$item["link_title"]}</a>";
+                }
+
+                // Checkbox "Open in new Tab"
+                if ( $item["target_blank"] ) {
+                    $checked = "checked";
+                } else {
+                    $checked = "";
+                }
+
+                $e_tag_title = htmlspecialchars( $item["tag_title"] );
+
+                $list .= "
+<div>
+
+    <div class=item data-item={$item['mid']}>
+
+        {$link}
+
+        <div class=menu-buttons>
+            <div class=prop>{$tr_prop}</div>
+            <div class=append>{$tr_append}</div>
+            <div class=save><span>{$tr_save}</span></div>
+            <div class=del>{$tr_delete}</div>
+        </div>
+
+        <div class=menu-prop>
+            <div class='title name'>{$tr_title}:</div>
+            <input name=title type=text value='{$item['title']}' placeholder='{$tr_placeholder}'>
+            <div class='sort title'>{$tr_sort}:</div>
+            <input name=sort type=text value='{$item['sort']}'>
+            <div class='parent title'>{$tr_parent}:</div>
+
+            <div class=parent-select-grid>
+                <div class=field-select data-parent='{$item['pid']}' data-old-parent='{$item['pid']}'>
+                    <div class=value></div>
+                    <div class=icon></div>
+                </div>
+                <div class=field-options>
+                    <div class=option value=0>{$tr_no_parent}</div>
+                </div>
+            </div>
+
+            <div class='classes title'>{$tr_classes}:</div>
+            <input name=classes type=text value='{$item['class']}'>
+            <div class='page title'>{$tr_page}:</div>
+            <div class=select-grid>
+                <div class=field-select name=id data-id={$item['id']} data-old-id={$item['id']}>
+                    <div class=value>{$item['select_title']}</div>
+                    <div class=icon></div>
+                </div>
+                <div class=field-options>
+                    <div class=select-dropdown>
+                        <div class=field-search>
+                            <input class=search-field type=text placeholder='{$tr_search}'>
+                        </div>
+                        <ul class=list-search>
+                            <li data-id=0 data-url>{$tr_no_page}</li>
+                        </ul>
+                    </div>
+                </div>
+            </div>
+            <div class='tag title'>{$tr_tag_title}:</div>
+            <input name=tag_title type=text value=\"{$e_tag_title}\">
+            <div class='url title'>URL:</div>
+            <div class=target-blank>
+                <input name=url type=text value='{$item['url']}' {$disabled_url}>
+                <input name=targetblank type=checkbox {$checked} title='{$tr_new_window}'>
+            </div>
+        </div>
+    </div>
+    
+    {$sublist}
+
+</div>";
+            }
+            
+        }
+    }
+    return $list;
+}
+
+function cms_menu_get_parents_list( $pid = 0, $lvl = 0 ) {
+    global $cms;
+    $parents = "";
+    if ( empty( $cms["base"] ) ) {
+        return "";
+    }
+    $q = "SELECT mid, pid, title, id FROM menu WHERE pid={$pid} ORDER BY sort";
+    if ( $res = mysqli_query( $cms["base"], $q ) ) {
+        while ( $item = mysqli_fetch_assoc( $res ) ) {
+            if ( empty( $item["title"] ) and $item["id"] !== "0" ) {
+                $q = "SELECT title FROM pages WHERE id={$item['id']}";
+                if ( $res_page = mysqli_query( $cms["base"], $q ) and $page = mysqli_fetch_assoc( $res_page ) ) {
+                    $item["title"] = $page["title"];
+                } else {
+                    $item["title"] = __( "deleted_page" );
+                }
+            } elseif ( empty( $item["title"] ) ) {
+                $item["title"] = __( "no_page" );
+            }
+            $title = htmlspecialchars( $item["title"] );
+            $ident = str_repeat( "&emsp;", $lvl );
+            $parents .= "<div class=option value={$item['mid']}>{$ident}{$title}</div>";
+            $parents .= cms_menu_get_parents_list( $item["mid"], $lvl + 1 );
+        }
+    }
+    return $parents;
+}
+
+function cms_menu_admin() {
+    global $cms;
+
+    $conf = $cms["config"]["menu.mod.php"]["menu"]["menu"];
+    if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) {
+
+    $page = "
+<div class=main-main>
+    <div class=menu-grid>
+    </div>
+</div>
+<div class=main-footer>
+    <a class=create data-item=0>" . __( "add_menu" ) . "</a>
+</div>";
+
+    // Create menu item if not exists
+    if ( empty( $cms["config"]["menu.mod.php"]["menu"]["menu"] ) ) {
+        $cms["config"]["menu.mod.php"]["menu"]["menu"] = array(
+            "title"    => "menu_module_name",
+            "sort"     => 200,
+            "section"  => "content",
+        );
+        cms_save_config();
+    }
+
+    $cms["admin_pages"]["menu"] = $page;
+
+    }
+}
+
+function cms_menu_create_table() {
+    global $cms;
+
+    mysqli_query( $cms["base"], "
+    CREATE TABLE IF NOT EXISTS `menu` (
+        `mid` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+        `pid` int(11) DEFAULT 0,
+        `id` int(11) NOT NULL DEFAULT 0,
+        `title` varchar(255) NOT NULL DEFAULT '',
+        `tag_title` varchar(255) NOT NULL DEFAULT '',
+        `url` varchar(255) NOT NULL DEFAULT '',
+        `sort` int(11) NOT NULL DEFAULT 1000,
+        `class` varchar(255) NOT NULL DEFAULT '',
+        `area` varchar(32) NOT NULL DEFAULT '',
+        `target_blank` tinyint(1) NOT NULL DEFAULT 0,
+        UNIQUE KEY `mid` (`mid`)
+      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+    ");
+
+}
+
+// One or more Menus
+function menu( $area ) {
+    global $cms;
+    if ( empty( $cms["base"] ) ) { return ""; } // fix php 8.0
+    $area = mysqli_real_escape_string( $cms["base"], $area );
+    $q = "SELECT * FROM menu WHERE pid=0 AND area='{$area}' ORDER BY sort";
+    $html = "";
+    $cms["menu"] = array();
+    if ( $res = mysqli_query( $cms["base"], $q ) ) {
+        while ( $menu = mysqli_fetch_assoc( $res ) ) {
+            $cms["menu.mod.php"]["menu"] = $menu;
+            $html .= menu1( $menu["mid"] );
+        }
+    }
+    return $html;
+}
+
+
+function menu1( $pid = 0 ) {
+    global $cms;
+    
+    $html = "";
+    
+    $q = "SELECT * FROM menu WHERE pid={$pid} ORDER BY sort";
+    // Child Items
+    if ( $res2 = mysqli_query( $cms["base"], $q ) ) {
+        while ( $item = mysqli_fetch_assoc( $res2 ) ) {
+
+            // Совместимость с модулем блоков
+            $q_blocks = "SELECT * FROM blocks_pages WHERE id={$item['id']}";
+            $page = NULL;
+            if ( $res_b = mysqli_query( $cms["base"], $q_blocks ) ) {
+                $page = mysqli_fetch_assoc( $res_b );
+            }
+
+            // Если отработал модуль блоков, то не искать страницы
+            $q_pages = "SELECT * FROM pages WHERE id={$item['id']}";
+            if ( ! $page && $res_p = mysqli_query( $cms["base"], $q_pages ) ) {
+                $page = mysqli_fetch_assoc( $res_p );
+            }
+
+            if ( $item["id"] !== "0" ) {
+                $item["url"] = $cms["base_path"] . $page["url"];
+                if ( empty( $item["title"] ) ) {
+                    if ( empty( $page["title"] ) ) {
+                        $item["title"] = __( "deteled_page" );
+                    } else {
+                        $item["title"] = $page["title"];
+                    }
+                }
+            }
+
+            if ( isset( $cms["page"]["url"] ) && $item["url"] === $cms["base_path"] . $cms["page"]["url"] && !( $item["id"] === "0" && empty( $item['url'] ) ) ) {
+                $class = "active";
+            } else {
+                $class = "";
+            }
+            if ( $item["target_blank"] ) {
+                $target_blank = " target=_blank";
+            } else {
+                $target_blank = "";
+            }
+            if ( $item["tag_title"] ) {
+                $e_tag_title = htmlspecialchars( $item["tag_title"] );
+                $tag_title = " title=\"{$e_tag_title}\"";
+            } else {
+                $tag_title = "";
+            }
+
+            // submenu
+            $sub = menu1( $item["mid"] );
+            if ( ! empty( $sub ) ) {
+                $class .= " has-sub-menu";
+                $has_submenu = true;
+            } else {
+                $has_submenu = false;
+            }
+            if ( ! empty( $class ) || ! empty( $item["class"] ) ) {
+                $class = trim( "{$class} {$item['class']}" );
+            }
+            
+            // Формирование ссылки или span
+            if ( $item["id"] === "0" && empty( $item['url'] ) ) {
+                $link = "<a{$tag_title}>{$item['title']}</a>";
+            } elseif ( $item["id"] !== "0" && isset( $page["published"] ) && $page["published"] === "0" ) {
+                // снята с публикации
+                $link = "<a{$tag_title}>{$item['title']}</a>";
+                $class = trim( "{$class} unpublished" );
+            } else {
+                $link = "<a href='{$item['url']}'{$target_blank}{$tag_title}>{$item['title']}</a>";
+            }
+
+            
+            // Для хука
+            $cms["menu.mod.php"]["item_link"] = array(
+                "link" => $link,
+                "has_submenu" => $has_submenu,
+            );
+            do_hook( "menu_item_link" );
+
+
+            if ( empty( $sub ) && $item["id"] !== "0" && isset( $page["published"] ) &&  $page["published"] === "0" ) {
+                // Если нет дочерних и страница снята с публикации, то не добавлять
+                $item_html = "";
+            } else {
+                if ( ! empty( $class ) ) {
+                    $tag_class = " class='{$class}'";
+                } else {
+                    $tag_class = "";
+                }
+                $item_html = "<li{$tag_class}>{$cms["menu.mod.php"]["item_link"]["link"]}{$sub}</li>";
+            }
+
+
+            // Для хука
+            $cms["menu.mod.php"]["item"] = array(
+                "html" => $item_html,
+                "has_submenu" => $has_submenu,
+            );
+            do_hook( "menu_item" );
+            
+
+            $html .= $cms["menu.mod.php"]["item"]["html"];
+        }
+    }
+
+    $q = "SELECT * FROM menu WHERE mid={$pid}";
+    // If exists childs items
+    if ( ! empty( $html ) and $res = mysqli_query( $cms["base"], $q ) and $menu = mysqli_fetch_assoc( $res ) ) {
+        if ( ! empty( $menu["class"] ) && $menu["pid"] == 0 ) {
+            $class = " class='{$menu['class']}'";
+        } elseif ( $menu["pid"] != 0 ) {
+            $class = " class='sub-menu'";
+        } else {
+            $class = "";
+        }
+        $html = "<ul{$class}>{$html}</ul>";
+    }
+
+    return $html;
+}
+
+
+// Новое меню
+function dyn_menu( $area ) {
+    global $cms;
+
+    if ( empty( $cms["base"] ) ) { return ""; } // fix php 8.0
+//file_put_contents( __DIR__ . "/menu_export.php", "<?php\n" );
+    $cms["menu"] = array();
+    $area = mysqli_real_escape_string( $cms["base"], $area );
+    $q = "SELECT * FROM menu WHERE pid=0 AND area='{$area}' ORDER BY sort";
+    if ( $res = mysqli_query( $cms["base"], $q ) ) {
+        while ( $menu = mysqli_fetch_assoc( $res ) ) {
+            $cms["menu"][ $menu["mid"] ] = $menu;
+            menu_get_items( $menu["mid"], $cms["menu"][ $menu["mid"] ] );
+        }
+    }
+    do_hook( "menu" );
+    
+//file_put_contents( __DIR__ . "/menu_export.php", "\$cms['menu'] = " . var_export( $cms["menu"], true ) . ";\n", FILE_APPEND );
+}
+
+
+function menu_get_items( $pid, &$items ) {
+    global $cms;
+    
+    $items["items"] = array();
+    $q = "SELECT * FROM menu WHERE pid={$pid} ORDER BY sort";
+    if ( $res = mysqli_query( $cms["base"], $q ) ) {
+        while ( $item = mysqli_fetch_assoc( $res ) ) {
+            menu_get_items( $item["mid"], $item );
+            $items["items"][] = $item;
+        }
+    }
+    //file_put_contents( __DIR__ . "/menu_export.php", "\$a = " . var_export( $items, true ) . ";\n", FILE_APPEND );
+
+}
+