diff .cms/mod/template.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/template.mod.php	Fri Oct 11 22:40:23 2024 +0000
@@ -0,0 +1,531 @@
+<?php
+
+$cms["modules"]["template.mod.php"] = array(
+    "name"        => "template_module_name",
+    "description" => "template_module_description",
+    "files"       => array(
+        ".cms/mod/template.mod.php",
+        ".cms/css/template.css",
+        ".cms/js/template.js",
+        ".cms/lang/ru_RU.UTF-8/template.mod.php",
+        ".cms/lang/en_US.UTF-8/template.mod.php",
+        ".cms/lang/uk_UA.UTF-8/template.mod.php",
+    ),
+);
+
+// Return if module disabled
+if ( ! empty( $cms["config"]["template.mod.php"]["disabled"] ) ) {
+
+    return;
+
+} else {
+
+    // Install
+    if ( empty( $cms["config"]["template.mod.php"]["template"] ) ) {
+        $cms["config"]["template.mod.php"]["template"] = "mini";
+    }
+    if ( empty( $cms["config"]["template.mod.php"]["scripts"] ) ) {
+        $cms["config"]["template.mod.php"]["scripts"] = "";
+    }
+
+    $cms["template"] = $cms["config"]["template.mod.php"]["template"];
+
+    if ( ! isset( $cms["config"]["template.mod.php"]["disable_write_to_disk"] ) ) {
+        $cms["config"]["template.mod.php"]["disable_write_to_disk"] = true;
+    }
+    
+    if ( ! isset( $cms["config"]["template.mod.php"]["headers"] ) ) {
+        $cms["config"]["template.mod.php"]["headers"] = "cache-control: max-age=0";
+    }
+
+    if ( is_admin() ) {
+        hook_add_fn( "admin", "cms_template_admin" );
+        hook_add_fn( "admin_header",  "cms_template_admin_header" );
+        hook_add_fn( "api", "cms_template_api" );
+    }
+    // Вызов функции cms_template_template сделаем пораньше,
+    // чтобы в других модулях не нужно было ставить 20
+    hook_add_fn( "template", "cms_template_template", 5 );
+    hook_add_fn( "echo", "cms_template_echo" );
+    hook_add_fn( "write", "cms_template_write" );
+
+}
+
+function cms_template_admin_header() {
+    global $cms;
+    $conf = $cms["config"]["template.mod.php"]["menu"]["template"];
+    if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) {
+        echo "<link rel=stylesheet href='{$cms['base_path']}css/template.css'>";
+        echo "<script src='{$cms['base_path']}js/template.js'></script>";
+    }
+}
+
+function cms_template_admin() {
+    global $cms;
+
+    $conf = $cms["config"]["template.mod.php"]["menu"]["template"];
+    if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) {
+
+    // Save settings
+    if ( ! empty( $_POST["save_template"] ) ) {
+        $cms["config"]["template.mod.php"]["template"] = $_POST["template"];
+        $cms["config"]["template.mod.php"]["disable_write_to_disk"] = empty( $_POST["enable_cache"] );
+        cms_save_config();
+        cms_clear_cache();
+        header( "Location: {$cms['base_path']}{$cms['config']['admin.mod.php']['admin_url']}" );
+        $cms["hooks"]["admin"]["next"] = ""; // Предотвратить выдачу админки
+        return;
+    }
+    
+    // Save template headers
+    if ( ! empty( $_POST["save_template_headers"] ) ) {
+        $cms["config"]["template.mod.php"]["headers"] = $_POST["template_headers"];
+        cms_save_config();
+        header( "Location: {$cms['base_path']}{$cms['config']['admin.mod.php']['admin_url']}" );
+        $cms["hooks"]["admin"]["next"] = ""; // Предотвратить выдачу админки
+        return;
+    }
+
+    // Create menu item
+    if ( empty( $cms["config"]["template.mod.php"]["menu"]["template"] ) ) {
+        $cms["config"]["template.mod.php"]["menu"]["template"] = array(
+            "title"    => "template_module_name",
+            "sort"     => 70,
+            "section"  => "settings",
+        );
+        cms_save_config();
+    }
+
+    $options = "";
+    foreach( glob( "{$cms['cms_dir']}/*/html.php" ) as $path_html_php ) {
+        $template = preg_replace( "/.*\/([^\/]+)\/html\.php/u", "$1", $path_html_php );
+        if ( substr( $template, 0, 6 ) !== "admin." ) {
+            $options .= "<div class=option value='{$template}'>{$template}</div>";
+        }
+    }
+
+    cms_template_load_settings();
+    $template_files_title = "<div class=title>" . __( "editable_files" ) . "</div>";
+    $template_files = "";
+    if ( isset( $cms["templates"] ) && is_array( $cms["templates"] ) ) {
+        foreach( $cms["templates"][ $cms["config"]["template.mod.php"]["template"] ]["files"] as $file ) {
+            $template_files .= "<div class=file>{$file}</div>";
+        }
+    }
+    if ( empty( $template_files ) ) {
+        $template_files = "<div class=no-files>" . __( "no_editable_files" ) . "</div>";
+    }
+    
+    $tr_title   = __( "help" );
+    $tr_current = __( "current_template" );
+    $tr_save    = __( "save" );
+    $tr_upl     = __( "install_template" );
+    if ( $cms["config"]["template.mod.php"]["disable_write_to_disk"] ) {
+        $enable_cache = "";
+    } else {
+        $enable_cache = "checked";
+    }
+    $headers_title = __( "headers_title" );
+
+    // Справка для шаблона определяется в файле template.settings.php
+    $help = __( "help", $cms["config"]["template.mod.php"]["template"] );
+    if ( $help === "help" ) $help = "";
+
+    // Display settings
+    $page = "
+<div class=settings>
+    <div class=template-install>
+        <div class=upload_dnd>
+            <input id=template-upload type=file name='myfile[]' multiple class=files>
+            {$tr_upl}
+        </div>
+    </div>
+    <div class=template>
+        <form method=post>
+            <div>{$tr_current}</div>
+            <input name=template autocomplete=off type=hidden value='{$cms["config"]["template.mod.php"]["template"]}'>
+
+            <div class=template-select-grid>
+                <div class=field-select>
+                    <div class=value>{$cms["config"]["template.mod.php"]["template"]}</div>
+                    <div class=icon></div>
+                </div>
+                <div class=field-options>
+                    {$options}
+                </div>
+            </div>
+
+            <label>
+                <input type=checkbox name=enable_cache {$enable_cache}>
+                <span class=enable-cache>" . __( "enable_cache" ) . "</span>
+            </label>
+            
+            <button name=save_template value=save>{$tr_save}</button>
+        </form>
+    </div>
+    <form method=post class=template-headers>
+        <div class=template-headers-title>{$headers_title}</div>
+        <textarea name=template_headers>{$cms['config']['template.mod.php']['headers']}</textarea>
+        <button name=save_template_headers value=save>{$tr_save}</button>
+    </form>
+    <div class=template-manual>
+        <div>{$tr_title}</div>
+        {$help}
+    </div>
+    <div class=template-files>
+        {$template_files_title}
+        {$template_files}
+    </div>
+</div>
+
+<div class='template-editor-bg hidden'>
+    <div class=template-editor-grid>
+        <div class=template-editor-header>
+            <div class=close-template-button></div>
+            <div class=save-template-button></div>
+            <span class=template-editor-title></span>
+        </div>
+        <div class=template-editor>
+            <textarea></textarea>
+        </div>
+        <div class=snip-grid>
+            <div class=css>
+                <div data-type=snip data-otag='@media (min-width: px) and (max-width: px) {\n' data-ctag='\n}'>@media (min) and (max)</div>
+                <div data-type=snip data-otag='/* ' data-ctag=' */'>/* comment */</div>
+                <a href='{$cms['base_path']}man/{$cms['config']['locale']}/hint_css.html' target=_blank>" . __( "hint_css" ) . "</a>
+            </div>
+            <div class=php>
+                <a href='{$cms['base_path']}man/{$cms['config']['locale']}/hint_php.html' target=_blank>" . __( "hint_php" ) . "</a>
+            </div>
+            <div class=html>
+                <a href='{$cms['base_path']}man/{$cms['config']['locale']}/hint_html.html' target=_blank>" . __( "hint_html" ) . "</a>
+            </div>
+        </div>
+    </div>
+</div>
+";
+
+    $cms["admin_pages"]["template"] = $page;
+
+    }
+
+}
+
+// Load template settings
+function cms_template_load_settings() {
+    global $cms;
+    $settings = "{$cms['cms_dir']}/{$cms['config']['template.mod.php']['template']}/template.settings.php";
+    if ( file_exists( $settings ) ) {
+        include( $settings );
+    }
+}
+
+
+function cms_template_api() {
+    global $cms;
+    
+    if ( ! empty( $_POST["fn"] ) ) {
+        
+        switch ( $_POST["fn"] ) {
+
+            case "clear_cache":
+                cms_clear_cache();
+                echo( json_encode( array(
+                    "info_text"  => __( "cache_cleared" ),
+                    "info_class" => "info-success",
+                    "info_time"  => 5000,
+                ) ) );
+                return;
+            break;
+
+            case "get_template_file":
+                $file = file_get_contents( $cms["site_dir"] . "/" . $_POST["file"] );
+                if ( $file !== false ) {
+                    $ok = "true";
+                } else {
+                    $ok = "false";
+                }
+                echo( json_encode( array(
+                    "ok"   => $ok,
+                    "file" => $file,
+                ) ) );
+                return;
+            break;
+
+            case "save_template_file":
+                $file = file_put_contents( $cms["site_dir"] . "/" . $_POST["file"], $_POST["content"] );
+                if ( $file !== false ) {
+                    $ok    = "true";
+                    $msg   = __( "saved" );
+                    $class = "info-success";
+                } else {
+                    $ok    = "false";
+                    $msg   = __( "save_error" );
+                    $class = "info-error";
+                }
+                cms_clear_cache();
+                echo( json_encode( array(
+                    "ok"         => $ok,
+                    "info_text"  => $msg,
+                    "info_class" => $class,
+                    "info_time"  => 5000,
+                ) ) );
+                return;
+            break;
+
+            case "install_template":
+                $success = true;
+                //$text = "dev.coffee-cms.ru";
+                //if ( $cms["url"]["host"] !== $text )
+                foreach ( $_FILES["myfile"]["name"] as $n => $name ) {
+                    if ( $_FILES["myfile"]["error"][$n] ) {
+                        $success = false;
+                        $text = str_replace( "xxx", $name, __( "upload_error_xxx" ) );
+                        break;
+                    } else {
+                        // Unpack Template
+                        // Object Oriented Style for future compability with PHP 8
+                        $zip = new ZipArchive;
+                        if ( $zip->open( $_FILES["myfile"]["tmp_name"][$n] ) === TRUE ) {
+                            $zip->extractTo( $cms["site_dir"] );
+                            $zip->close();
+                            $text = __( "install_success" );
+                        } else {
+                            $success = false;
+                            $text = str_replace( "xxx", $name, __( "cant_unzip_xxx" ) );
+                            break;
+                        }
+                    }
+                }
+
+                if ( $success ) {
+                    echo( json_encode( array(
+                        "info_text"  => $text,
+                        "info_class" => "info-success",
+                        "info_time"  => 5000,
+                    ) ) );
+                    return;
+                } else {
+                    echo( json_encode( array(
+                        "info_text"  => $text,
+                        "info_class" => "info-error",
+                        "info_time"  => 10000,
+                    ) ) );
+                    return;
+                }
+            break;
+
+        }
+    }
+}
+
+
+function cms_template_template() {
+    global $cms;
+    if ( is_file( $cms["cms_file"] ) ) {
+        if ( substr( $cms["cms_file"], -4 ) === ".php" || strpos( substr( $cms["cms_file"], strlen( $cms["cms_dir"] ) ), "/." ) !== false ) {
+            $cms["status"]         = "404";
+        } else {
+            $cms["output"]["from"] = $cms["cms_file"];
+            $cms["output"]["to"]   = $cms["site_dir"] . "/" . $cms["url"]["path"];
+            $cms["status"]         = "200";
+        }
+    } else {
+        ob_start();
+        include( "{$cms['cms_dir']}/{$cms['template']}/html.php" );
+        $cms["output"] = ob_get_clean();
+    }
+}
+
+
+function cms_template_echo() {
+    global $cms;
+
+    $headers = array();
+    if ( substr( $cms["template"], 0, 6 ) !== "admin." ) {
+        $lines = explode( "\n", $cms["config"]["template.mod.php"]["headers"] );
+        foreach ( $lines as $line ) {
+            $line = trim( $line );
+            if ( ! empty( $line ) ) {
+                $headers[] = $line;
+            }
+        }
+    }
+
+    if ( is_array( $cms["output"] ) ) {
+        if ( $cms["status"] === "200" ) {
+            $types = array(
+                "css" => "text/css",
+                "js" => "application/javascript",
+                "svg" => "image/svg+xml",
+            );
+            $ext = preg_replace( "/.*\./u", "", $cms["output"]["to"] );
+            if ( isset( $types[$ext] ) ) {
+                $mime = $types[$ext];
+            } else {
+                $mime = "";
+            }
+            header( "Content-Type: {$mime}" );
+            header( "{$_SERVER['SERVER_PROTOCOL']} 200 OK" ); // fix server 404
+            foreach ( $headers as $header ) {
+                header( $header );
+            }
+            cms_readfile( $cms["output"]["from"], false );
+        } else {
+            header( "{$_SERVER['SERVER_PROTOCOL']} 404 Not Found" );
+        }
+    } else {
+        switch ( $cms["status"] ) {
+            case "200":
+                header( "{$_SERVER['SERVER_PROTOCOL']} 200 OK" ); // fix server 404
+                foreach ( $headers as $header ) {
+                    header( $header );
+                }
+                echo $cms["output"];
+            break;
+            case "404":
+                header( "{$_SERVER['SERVER_PROTOCOL']} 404 Not Found" );
+                echo $cms["output"];
+                // Для админа выводится текст страницы
+                // а для анонима сообщение что не найдена
+            break;
+            case "301":
+                header( "Location: {$cms['status_301_location']}", true, 301 );
+            break;
+            case "302":
+                header( "Location: {$cms['status_302_location']}", true, 302 );
+            break;
+        }
+    }
+}
+
+
+function cms_template_write() {
+    global $cms;
+
+    if ( ! empty( $cms["config"]["template.mod.php"]["disable_write_to_disk"] ) ) {
+        return;
+    }
+
+    if ( $cms["status"] !== "200" ) {
+        return;
+    }
+    
+    // write to disk
+    umask( 0 );
+
+    if ( is_array( $cms["output"] ) ) {
+        
+        $dirs = explode( "/", str_replace( $cms["site_dir"] . "/", "", $cms["output"]["to"] ) );
+        $dir  = $cms["site_dir"];
+        $file_name = array_pop( $dirs );
+        foreach ( $dirs as $path ) {
+            $dir .= "/" . $path;
+            if ( ! is_dir( $dir ) ) {
+                mkdir( $dir, 0777, false );
+            } elseif( is_file( $dir ) ) {
+                unlink( $dir );
+                mkdir( $dir, 0777, false );
+            }
+        }
+
+        if ( ! file_exists( $cms["output"]["to"] ) ) {
+            $tmp_name = $cms["site_dir"] . "/uploads/.tmp_" . cms_uid() . "_" . pathinfo( $cms["output"]["to"], PATHINFO_BASENAME );
+            copy( $cms["output"]["from"], $tmp_name );
+            rename( $tmp_name, $cms["output"]["to"] );
+        }
+
+    } else {
+
+        // create dirs
+        $dirs = explode( "/", $cms["url"]["path"] );
+        $dir  = $cms["site_dir"];
+        $file_name = array_pop( $dirs );
+        foreach ( $dirs as $path ) {
+            $dir .= "/" . $path;
+            if ( ! file_exists( $dir ) ) {
+                mkdir( $dir, 0777, false );
+            } elseif( is_file( $dir ) ) {
+                unlink( $dir );
+                mkdir( $dir, 0777, false );
+            }
+        }
+
+        if ( ! $file_name ) {
+            $file = $dir . "/index.html";
+        } else {
+            $file = $dir . "/" . $file_name;
+        }
+
+        if ( ! file_exists( $file ) ) {
+            $tmp_name = $cms["site_dir"] . "/uploads/.tmp_" . cms_uid() . "_" . pathinfo( $file, PATHINFO_BASENAME );
+            file_put_contents( $tmp_name, $cms["output"], LOCK_EX );
+            chmod( $tmp_name, 0666 );
+            rename( $tmp_name, $file );
+        }
+
+    }
+}
+
+
+function cms_clear_cache() {
+    global $cms;
+
+    do_hook( "clear_cache" );
+
+    // array for delete dirs
+    $dirs = array();
+
+    // search all pages in database
+    if ( ! empty( $cms["base"] ) ) {
+        if ( $res = mysqli_query( $cms["base"], "SELECT `url` FROM `pages`" ) ) {
+            while ( $page = mysqli_fetch_assoc( $res ) ) {
+                if ( $page["url"] === "/" ) $page["url"] = "";
+                $file = $cms["site_dir"] . "/" . $page["url"];
+                if ( substr( $file, -1 ) === "/" ) {
+                    $file .= "index.html";
+                } elseif ( is_dir( $file ) ) {
+                    // for
+                    // /parent/child
+                    // /parent
+                    $file .= "/index.html";
+                }
+                if ( is_file( $file ) ) unlink( $file );
+                // Add dirs to remove queue
+                $dir = "/" . $page["url"];
+                while ( $dir && $dir !== "/" && $dir !== "\\" ) {
+                    $new_dir = $cms["site_dir"] . $dir;
+                    if ( ! in_array( $new_dir, $dirs ) ) {
+                        $dirs[] = $new_dir;
+                    }
+                    $dir = dirname( $dir );
+                }
+            }
+        }
+    }
+
+    // delete template files
+    $queue[] = $cms["cms_dir"];
+    while ( $cur = array_shift( $queue ) ) {
+        if ( is_dir( $cur ) ) {
+            // add current dir to array for delete
+            array_push( $dirs, str_replace( ".cms/", "", $cur ) );
+            // search children files and dirs
+            $queue = array_merge( $queue, glob( $cur . "/*" ) );
+        } else {
+            $file = str_replace( ".cms/", "", $cur );
+            if ( is_file( $file ) ) unlink( $file );
+        }
+    }
+
+    // delete dirs
+    rsort( $dirs );
+    foreach ( $dirs as $dir ) {
+        if ( is_dir( $dir ) && $dir !== $cms["cms_dir"] && $dir !== $cms["site_dir"] ) {
+            if ( is_dir_and_empty( $dir ) ) {
+                rmdir( $dir );
+            }
+        }
+    }
+
+}