comparison .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
comparison
equal deleted inserted replaced
-1:000000000000 0:78edf6b517a0
1 <?php
2
3 $cms["modules"]["template.mod.php"] = array(
4 "name" => "template_module_name",
5 "description" => "template_module_description",
6 "files" => array(
7 ".cms/mod/template.mod.php",
8 ".cms/css/template.css",
9 ".cms/js/template.js",
10 ".cms/lang/ru_RU.UTF-8/template.mod.php",
11 ".cms/lang/en_US.UTF-8/template.mod.php",
12 ".cms/lang/uk_UA.UTF-8/template.mod.php",
13 ),
14 );
15
16 // Return if module disabled
17 if ( ! empty( $cms["config"]["template.mod.php"]["disabled"] ) ) {
18
19 return;
20
21 } else {
22
23 // Install
24 if ( empty( $cms["config"]["template.mod.php"]["template"] ) ) {
25 $cms["config"]["template.mod.php"]["template"] = "mini";
26 }
27 if ( empty( $cms["config"]["template.mod.php"]["scripts"] ) ) {
28 $cms["config"]["template.mod.php"]["scripts"] = "";
29 }
30
31 $cms["template"] = $cms["config"]["template.mod.php"]["template"];
32
33 if ( ! isset( $cms["config"]["template.mod.php"]["disable_write_to_disk"] ) ) {
34 $cms["config"]["template.mod.php"]["disable_write_to_disk"] = true;
35 }
36
37 if ( ! isset( $cms["config"]["template.mod.php"]["headers"] ) ) {
38 $cms["config"]["template.mod.php"]["headers"] = "cache-control: max-age=0";
39 }
40
41 if ( is_admin() ) {
42 hook_add_fn( "admin", "cms_template_admin" );
43 hook_add_fn( "admin_header", "cms_template_admin_header" );
44 hook_add_fn( "api", "cms_template_api" );
45 }
46 // Вызов функции cms_template_template сделаем пораньше,
47 // чтобы в других модулях не нужно было ставить 20
48 hook_add_fn( "template", "cms_template_template", 5 );
49 hook_add_fn( "echo", "cms_template_echo" );
50 hook_add_fn( "write", "cms_template_write" );
51
52 }
53
54 function cms_template_admin_header() {
55 global $cms;
56 $conf = $cms["config"]["template.mod.php"]["menu"]["template"];
57 if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) {
58 echo "<link rel=stylesheet href='{$cms['base_path']}css/template.css'>";
59 echo "<script src='{$cms['base_path']}js/template.js'></script>";
60 }
61 }
62
63 function cms_template_admin() {
64 global $cms;
65
66 $conf = $cms["config"]["template.mod.php"]["menu"]["template"];
67 if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) {
68
69 // Save settings
70 if ( ! empty( $_POST["save_template"] ) ) {
71 $cms["config"]["template.mod.php"]["template"] = $_POST["template"];
72 $cms["config"]["template.mod.php"]["disable_write_to_disk"] = empty( $_POST["enable_cache"] );
73 cms_save_config();
74 cms_clear_cache();
75 header( "Location: {$cms['base_path']}{$cms['config']['admin.mod.php']['admin_url']}" );
76 $cms["hooks"]["admin"]["next"] = ""; // Предотвратить выдачу админки
77 return;
78 }
79
80 // Save template headers
81 if ( ! empty( $_POST["save_template_headers"] ) ) {
82 $cms["config"]["template.mod.php"]["headers"] = $_POST["template_headers"];
83 cms_save_config();
84 header( "Location: {$cms['base_path']}{$cms['config']['admin.mod.php']['admin_url']}" );
85 $cms["hooks"]["admin"]["next"] = ""; // Предотвратить выдачу админки
86 return;
87 }
88
89 // Create menu item
90 if ( empty( $cms["config"]["template.mod.php"]["menu"]["template"] ) ) {
91 $cms["config"]["template.mod.php"]["menu"]["template"] = array(
92 "title" => "template_module_name",
93 "sort" => 70,
94 "section" => "settings",
95 );
96 cms_save_config();
97 }
98
99 $options = "";
100 foreach( glob( "{$cms['cms_dir']}/*/html.php" ) as $path_html_php ) {
101 $template = preg_replace( "/.*\/([^\/]+)\/html\.php/u", "$1", $path_html_php );
102 if ( substr( $template, 0, 6 ) !== "admin." ) {
103 $options .= "<div class=option value='{$template}'>{$template}</div>";
104 }
105 }
106
107 cms_template_load_settings();
108 $template_files_title = "<div class=title>" . __( "editable_files" ) . "</div>";
109 $template_files = "";
110 if ( isset( $cms["templates"] ) && is_array( $cms["templates"] ) ) {
111 foreach( $cms["templates"][ $cms["config"]["template.mod.php"]["template"] ]["files"] as $file ) {
112 $template_files .= "<div class=file>{$file}</div>";
113 }
114 }
115 if ( empty( $template_files ) ) {
116 $template_files = "<div class=no-files>" . __( "no_editable_files" ) . "</div>";
117 }
118
119 $tr_title = __( "help" );
120 $tr_current = __( "current_template" );
121 $tr_save = __( "save" );
122 $tr_upl = __( "install_template" );
123 if ( $cms["config"]["template.mod.php"]["disable_write_to_disk"] ) {
124 $enable_cache = "";
125 } else {
126 $enable_cache = "checked";
127 }
128 $headers_title = __( "headers_title" );
129
130 // Справка для шаблона определяется в файле template.settings.php
131 $help = __( "help", $cms["config"]["template.mod.php"]["template"] );
132 if ( $help === "help" ) $help = "";
133
134 // Display settings
135 $page = "
136 <div class=settings>
137 <div class=template-install>
138 <div class=upload_dnd>
139 <input id=template-upload type=file name='myfile[]' multiple class=files>
140 {$tr_upl}
141 </div>
142 </div>
143 <div class=template>
144 <form method=post>
145 <div>{$tr_current}</div>
146 <input name=template autocomplete=off type=hidden value='{$cms["config"]["template.mod.php"]["template"]}'>
147
148 <div class=template-select-grid>
149 <div class=field-select>
150 <div class=value>{$cms["config"]["template.mod.php"]["template"]}</div>
151 <div class=icon></div>
152 </div>
153 <div class=field-options>
154 {$options}
155 </div>
156 </div>
157
158 <label>
159 <input type=checkbox name=enable_cache {$enable_cache}>
160 <span class=enable-cache>" . __( "enable_cache" ) . "</span>
161 </label>
162
163 <button name=save_template value=save>{$tr_save}</button>
164 </form>
165 </div>
166 <form method=post class=template-headers>
167 <div class=template-headers-title>{$headers_title}</div>
168 <textarea name=template_headers>{$cms['config']['template.mod.php']['headers']}</textarea>
169 <button name=save_template_headers value=save>{$tr_save}</button>
170 </form>
171 <div class=template-manual>
172 <div>{$tr_title}</div>
173 {$help}
174 </div>
175 <div class=template-files>
176 {$template_files_title}
177 {$template_files}
178 </div>
179 </div>
180
181 <div class='template-editor-bg hidden'>
182 <div class=template-editor-grid>
183 <div class=template-editor-header>
184 <div class=close-template-button></div>
185 <div class=save-template-button></div>
186 <span class=template-editor-title></span>
187 </div>
188 <div class=template-editor>
189 <textarea></textarea>
190 </div>
191 <div class=snip-grid>
192 <div class=css>
193 <div data-type=snip data-otag='@media (min-width: px) and (max-width: px) {\n' data-ctag='\n}'>@media (min) and (max)</div>
194 <div data-type=snip data-otag='/* ' data-ctag=' */'>/* comment */</div>
195 <a href='{$cms['base_path']}man/{$cms['config']['locale']}/hint_css.html' target=_blank>" . __( "hint_css" ) . "</a>
196 </div>
197 <div class=php>
198 <a href='{$cms['base_path']}man/{$cms['config']['locale']}/hint_php.html' target=_blank>" . __( "hint_php" ) . "</a>
199 </div>
200 <div class=html>
201 <a href='{$cms['base_path']}man/{$cms['config']['locale']}/hint_html.html' target=_blank>" . __( "hint_html" ) . "</a>
202 </div>
203 </div>
204 </div>
205 </div>
206 ";
207
208 $cms["admin_pages"]["template"] = $page;
209
210 }
211
212 }
213
214 // Load template settings
215 function cms_template_load_settings() {
216 global $cms;
217 $settings = "{$cms['cms_dir']}/{$cms['config']['template.mod.php']['template']}/template.settings.php";
218 if ( file_exists( $settings ) ) {
219 include( $settings );
220 }
221 }
222
223
224 function cms_template_api() {
225 global $cms;
226
227 if ( ! empty( $_POST["fn"] ) ) {
228
229 switch ( $_POST["fn"] ) {
230
231 case "clear_cache":
232 cms_clear_cache();
233 echo( json_encode( array(
234 "info_text" => __( "cache_cleared" ),
235 "info_class" => "info-success",
236 "info_time" => 5000,
237 ) ) );
238 return;
239 break;
240
241 case "get_template_file":
242 $file = file_get_contents( $cms["site_dir"] . "/" . $_POST["file"] );
243 if ( $file !== false ) {
244 $ok = "true";
245 } else {
246 $ok = "false";
247 }
248 echo( json_encode( array(
249 "ok" => $ok,
250 "file" => $file,
251 ) ) );
252 return;
253 break;
254
255 case "save_template_file":
256 $file = file_put_contents( $cms["site_dir"] . "/" . $_POST["file"], $_POST["content"] );
257 if ( $file !== false ) {
258 $ok = "true";
259 $msg = __( "saved" );
260 $class = "info-success";
261 } else {
262 $ok = "false";
263 $msg = __( "save_error" );
264 $class = "info-error";
265 }
266 cms_clear_cache();
267 echo( json_encode( array(
268 "ok" => $ok,
269 "info_text" => $msg,
270 "info_class" => $class,
271 "info_time" => 5000,
272 ) ) );
273 return;
274 break;
275
276 case "install_template":
277 $success = true;
278 //$text = "dev.coffee-cms.ru";
279 //if ( $cms["url"]["host"] !== $text )
280 foreach ( $_FILES["myfile"]["name"] as $n => $name ) {
281 if ( $_FILES["myfile"]["error"][$n] ) {
282 $success = false;
283 $text = str_replace( "xxx", $name, __( "upload_error_xxx" ) );
284 break;
285 } else {
286 // Unpack Template
287 // Object Oriented Style for future compability with PHP 8
288 $zip = new ZipArchive;
289 if ( $zip->open( $_FILES["myfile"]["tmp_name"][$n] ) === TRUE ) {
290 $zip->extractTo( $cms["site_dir"] );
291 $zip->close();
292 $text = __( "install_success" );
293 } else {
294 $success = false;
295 $text = str_replace( "xxx", $name, __( "cant_unzip_xxx" ) );
296 break;
297 }
298 }
299 }
300
301 if ( $success ) {
302 echo( json_encode( array(
303 "info_text" => $text,
304 "info_class" => "info-success",
305 "info_time" => 5000,
306 ) ) );
307 return;
308 } else {
309 echo( json_encode( array(
310 "info_text" => $text,
311 "info_class" => "info-error",
312 "info_time" => 10000,
313 ) ) );
314 return;
315 }
316 break;
317
318 }
319 }
320 }
321
322
323 function cms_template_template() {
324 global $cms;
325 if ( is_file( $cms["cms_file"] ) ) {
326 if ( substr( $cms["cms_file"], -4 ) === ".php" || strpos( substr( $cms["cms_file"], strlen( $cms["cms_dir"] ) ), "/." ) !== false ) {
327 $cms["status"] = "404";
328 } else {
329 $cms["output"]["from"] = $cms["cms_file"];
330 $cms["output"]["to"] = $cms["site_dir"] . "/" . $cms["url"]["path"];
331 $cms["status"] = "200";
332 }
333 } else {
334 ob_start();
335 include( "{$cms['cms_dir']}/{$cms['template']}/html.php" );
336 $cms["output"] = ob_get_clean();
337 }
338 }
339
340
341 function cms_template_echo() {
342 global $cms;
343
344 $headers = array();
345 if ( substr( $cms["template"], 0, 6 ) !== "admin." ) {
346 $lines = explode( "\n", $cms["config"]["template.mod.php"]["headers"] );
347 foreach ( $lines as $line ) {
348 $line = trim( $line );
349 if ( ! empty( $line ) ) {
350 $headers[] = $line;
351 }
352 }
353 }
354
355 if ( is_array( $cms["output"] ) ) {
356 if ( $cms["status"] === "200" ) {
357 $types = array(
358 "css" => "text/css",
359 "js" => "application/javascript",
360 "svg" => "image/svg+xml",
361 );
362 $ext = preg_replace( "/.*\./u", "", $cms["output"]["to"] );
363 if ( isset( $types[$ext] ) ) {
364 $mime = $types[$ext];
365 } else {
366 $mime = "";
367 }
368 header( "Content-Type: {$mime}" );
369 header( "{$_SERVER['SERVER_PROTOCOL']} 200 OK" ); // fix server 404
370 foreach ( $headers as $header ) {
371 header( $header );
372 }
373 cms_readfile( $cms["output"]["from"], false );
374 } else {
375 header( "{$_SERVER['SERVER_PROTOCOL']} 404 Not Found" );
376 }
377 } else {
378 switch ( $cms["status"] ) {
379 case "200":
380 header( "{$_SERVER['SERVER_PROTOCOL']} 200 OK" ); // fix server 404
381 foreach ( $headers as $header ) {
382 header( $header );
383 }
384 echo $cms["output"];
385 break;
386 case "404":
387 header( "{$_SERVER['SERVER_PROTOCOL']} 404 Not Found" );
388 echo $cms["output"];
389 // Для админа выводится текст страницы
390 // а для анонима сообщение что не найдена
391 break;
392 case "301":
393 header( "Location: {$cms['status_301_location']}", true, 301 );
394 break;
395 case "302":
396 header( "Location: {$cms['status_302_location']}", true, 302 );
397 break;
398 }
399 }
400 }
401
402
403 function cms_template_write() {
404 global $cms;
405
406 if ( ! empty( $cms["config"]["template.mod.php"]["disable_write_to_disk"] ) ) {
407 return;
408 }
409
410 if ( $cms["status"] !== "200" ) {
411 return;
412 }
413
414 // write to disk
415 umask( 0 );
416
417 if ( is_array( $cms["output"] ) ) {
418
419 $dirs = explode( "/", str_replace( $cms["site_dir"] . "/", "", $cms["output"]["to"] ) );
420 $dir = $cms["site_dir"];
421 $file_name = array_pop( $dirs );
422 foreach ( $dirs as $path ) {
423 $dir .= "/" . $path;
424 if ( ! is_dir( $dir ) ) {
425 mkdir( $dir, 0777, false );
426 } elseif( is_file( $dir ) ) {
427 unlink( $dir );
428 mkdir( $dir, 0777, false );
429 }
430 }
431
432 if ( ! file_exists( $cms["output"]["to"] ) ) {
433 $tmp_name = $cms["site_dir"] . "/uploads/.tmp_" . cms_uid() . "_" . pathinfo( $cms["output"]["to"], PATHINFO_BASENAME );
434 copy( $cms["output"]["from"], $tmp_name );
435 rename( $tmp_name, $cms["output"]["to"] );
436 }
437
438 } else {
439
440 // create dirs
441 $dirs = explode( "/", $cms["url"]["path"] );
442 $dir = $cms["site_dir"];
443 $file_name = array_pop( $dirs );
444 foreach ( $dirs as $path ) {
445 $dir .= "/" . $path;
446 if ( ! file_exists( $dir ) ) {
447 mkdir( $dir, 0777, false );
448 } elseif( is_file( $dir ) ) {
449 unlink( $dir );
450 mkdir( $dir, 0777, false );
451 }
452 }
453
454 if ( ! $file_name ) {
455 $file = $dir . "/index.html";
456 } else {
457 $file = $dir . "/" . $file_name;
458 }
459
460 if ( ! file_exists( $file ) ) {
461 $tmp_name = $cms["site_dir"] . "/uploads/.tmp_" . cms_uid() . "_" . pathinfo( $file, PATHINFO_BASENAME );
462 file_put_contents( $tmp_name, $cms["output"], LOCK_EX );
463 chmod( $tmp_name, 0666 );
464 rename( $tmp_name, $file );
465 }
466
467 }
468 }
469
470
471 function cms_clear_cache() {
472 global $cms;
473
474 do_hook( "clear_cache" );
475
476 // array for delete dirs
477 $dirs = array();
478
479 // search all pages in database
480 if ( ! empty( $cms["base"] ) ) {
481 if ( $res = mysqli_query( $cms["base"], "SELECT `url` FROM `pages`" ) ) {
482 while ( $page = mysqli_fetch_assoc( $res ) ) {
483 if ( $page["url"] === "/" ) $page["url"] = "";
484 $file = $cms["site_dir"] . "/" . $page["url"];
485 if ( substr( $file, -1 ) === "/" ) {
486 $file .= "index.html";
487 } elseif ( is_dir( $file ) ) {
488 // for
489 // /parent/child
490 // /parent
491 $file .= "/index.html";
492 }
493 if ( is_file( $file ) ) unlink( $file );
494 // Add dirs to remove queue
495 $dir = "/" . $page["url"];
496 while ( $dir && $dir !== "/" && $dir !== "\\" ) {
497 $new_dir = $cms["site_dir"] . $dir;
498 if ( ! in_array( $new_dir, $dirs ) ) {
499 $dirs[] = $new_dir;
500 }
501 $dir = dirname( $dir );
502 }
503 }
504 }
505 }
506
507 // delete template files
508 $queue[] = $cms["cms_dir"];
509 while ( $cur = array_shift( $queue ) ) {
510 if ( is_dir( $cur ) ) {
511 // add current dir to array for delete
512 array_push( $dirs, str_replace( ".cms/", "", $cur ) );
513 // search children files and dirs
514 $queue = array_merge( $queue, glob( $cur . "/*" ) );
515 } else {
516 $file = str_replace( ".cms/", "", $cur );
517 if ( is_file( $file ) ) unlink( $file );
518 }
519 }
520
521 // delete dirs
522 rsort( $dirs );
523 foreach ( $dirs as $dir ) {
524 if ( is_dir( $dir ) && $dir !== $cms["cms_dir"] && $dir !== $cms["site_dir"] ) {
525 if ( is_dir_and_empty( $dir ) ) {
526 rmdir( $dir );
527 }
528 }
529 }
530
531 }