Mercurial
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 } |