Mercurial
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 ); + } + } + } + +}