#!/usr/bin/env php 1) ? $argv[1] : '.'); function compile_path($directory) { global $workingDirectory; return implode( DIRECTORY_SEPARATOR, array_merge([$workingDirectory], (array)($directory)) ); } function get_template_mtime($template) { $templateDependencies = ['index.tpl', 'menu.tpl', 'content/' . $template]; foreach ($templateDependencies as $template) { $includes = []; preg_match_all('/\{include .*\}/', file_get_contents(compile_path(['template', $template])), $includes); foreach ($includes[0] as $include) { $externalPath = []; if (preg_match('/file="(.*)"/', $include, $externalPath)) { $templateDependencies[] = $externalPath[1]; } } } foreach (glob(compile_path(['config', '*.json'])) as $configFile) { $templateDependencies[] = '../config/' . basename($configFile); } return max( array_map( function($file) { return filemtime(compile_path(['template', $file])); }, $templateDependencies ) ); } $outputDirectory = compile_path('static'); if (!file_exists($outputDirectory)) { mkdir($outputDirectory); } else { if (!is_dir($outputDirectory)) { throw new Exception('Output path already exists, but not a directory'); } } $templateDirectory = compile_path(['template', 'content']); if (!(file_exists($templateDirectory) && is_dir($templateDirectory))) { throw new Exception('Template directory not found'); } $inputDirectory = compile_path('http'); if (is_link($inputDirectory)) { $inputDirectory = compile_path('src'); } $dynamicFiles = ['.htaccess', 'index.php']; exec( 'rsync -urLp ' . implode( ' ', array_map( function($file) { return '--exclude=' . $file; }, $dynamicFiles ) ) . ' ' . escapeshellarg($inputDirectory . DIRECTORY_SEPARATOR) . ' ' . escapeshellarg($outputDirectory)); exec('find ' . escapeshellarg(compile_path('caches')) . ' -type f -not -name .gitignore -delete'); $bootstrapper = compile_path(['include', 'setup.php']); require_once($bootstrapper); $indexTemplates = ['index.tpl', 'main.tpl', 'home.tpl']; $indexTemplate = array_search(TRUE, array_map( function($template) { return file_exists(compile_path(['template', 'content', $template])); }, $indexTemplates )); if ($indexTemplate === FALSE) { throw new Exception('Index template not found'); } $filesToRender = ['index.html' => $indexTemplates[$indexTemplate], '404.html' => '../404.tpl']; $contentTemplateCommand = sprintf( 'find %s -name \*.tpl', escapeshellarg($templateDirectory) ); $contentTemplates = array_filter( explode( PHP_EOL, shell_exec($contentTemplateCommand) ) ); foreach ($contentTemplates as $file) { $fileMatch = array(); if (preg_match(sprintf( '#^%s\/(.*\.tpl)$#', preg_quote($templateDirectory) ), $file, $fileMatch)) { $filesToRender[ preg_replace( '/\.tpl$/', DIRECTORY_SEPARATOR . 'index.html', $fileMatch[1] ) ] = $fileMatch[1]; } } $lang = ($argc > 2) ? $argv[2] : ''; Env::setLang($lang); $renderer = new MySmarty(); $renderer->assign('lang', Env::lang()); $basePath = ($argc > 3) ? $argv[3] : '/'; $renderer->assign('base', $basePath); try { $scripts = Env::get('resources', 'scripts'); } catch(EnvNoSuchEntryException $e) { $scripts = []; } try { $sheets = Env::get('resources', 'sheets'); } catch(EnvNoSuchEntryException $e) { $sheets = []; } try { $minify = (bool)Env::get('resources', 'minify'); } catch(EnvNoSuchEntryException $e) { $minify = FALSE; } if ($minify && class_exists('Minify')) { $minifiedJSPath = compile_path(['static', '_js', 'scripts.js']); $minifiedJSHash = Minify::minifyJS($scripts, $minifiedJSPath); $outputScripts = [ basename($minifiedJSPath) . '?mtime=' . $minifiedJSHash ]; $minifiedCSSPath = compile_path(['static', '_css', 'styles.css']); $minifiedCSSHash = Minify::minifyCSS($sheets, $minifiedCSSPath); $outputSheets = [ basename($minifiedCSSPath) . '?mtime=' . $minifiedCSSHash ]; foreach ($scripts as $script) { unlink(compile_path(['static', '_js', $script])); } foreach ($sheets as $sheet) { unlink(compile_path(['static', '_css', $sheet])); } } else { $outputScripts = $scripts; $outputSheets = $sheets; } foreach ($filesToRender as $output => $template) { $outputPath = compile_path(['static', $output]); if (!file_exists($outputPath) || filemtime($outputPath) < get_template_mtime($template) || filemtime($outputPath) < filemtime(__FILE__) || ($minify && class_exists('Minify') && (filemtime($outputPath) < Minify::getMTime($scripts, $sheets)))) { $content = new MySmarty(); $content->assign('lang', Env::lang()); $menu = new MySmarty(); try { if (class_exists('Menu')) { $menu->assign('items', Menu::getItems()); $menu->assign('content', Menu::getActiveLink(preg_replace('/\.tpl$/', '', $template))); } } catch(EnvNoSuchEntryException $e) {} $renderer->assign('menu', $menu->fetch('menu.tpl')); $renderer->assign('content', $content->fetch('content/' . $template)); $title = NULL; try { $title = Env::get('titles', preg_replace('/\.tpl$/', '', $template)); } catch(EnvNoSuchEntryException $e) {} $renderer->assign('title', $title); $renderer->assign('scripts', $outputScripts); $renderer->assign('sheets', $outputSheets); $outputDir = implode( DIRECTORY_SEPARATOR, array_slice(explode(DIRECTORY_SEPARATOR, $outputPath), 0, -1) ); if (!is_dir($outputDir)) { mkdir($outputDir, 0777, TRUE); } file_put_contents($outputPath, $renderer->fetch('index.tpl')); } } if (!file_exists(compile_path(['static', '.htaccess']))) { file_put_contents(compile_path(['static', '.htaccess']), 'ErrorDocument 404 ' . rtrim($basePath, '/') . '/404.html' . PHP_EOL); } ?>