diff --git a/src/Interfaces/Response/IContent.php b/src/Interfaces/Response/IContent.php index 446a4ab..fef4842 100644 --- a/src/Interfaces/Response/IContent.php +++ b/src/Interfaces/Response/IContent.php @@ -4,7 +4,7 @@ interface IContent { public function &getData(): array; - public function &render(): string; + public function render(): void; public function getContentType(): string; } diff --git a/src/Response/ContentBase.php b/src/Response/ContentBase.php index 359cbdb..31d0053 100644 --- a/src/Response/ContentBase.php +++ b/src/Response/ContentBase.php @@ -11,7 +11,7 @@ abstract class ContentBase implements IContent return $this->data; } - abstract public function &render(): string; + abstract public function render(): void; abstract public function getContentType(): string; } diff --git a/src/Response/HtmlContent.php b/src/Response/HtmlContent.php index 2e1b13e..b5c9d6c 100644 --- a/src/Response/HtmlContent.php +++ b/src/Response/HtmlContent.php @@ -12,7 +12,7 @@ class HtmlContent extends ContentBase $this->data = &$data; } - public function &render(): string + public function render(): void { if (!empty($_ENV['DEV'])) { $generator = new Linker($this->view); @@ -21,14 +21,9 @@ class HtmlContent extends ContentBase extract($this->data); - ob_start(); require ROOT . '/cache/views/' . $this->view . '.php'; - $content = ob_get_contents(); - ob_end_clean(); - $content .= ''; - - return $content; + echo ''; } public function getContentType(): string diff --git a/src/Response/JsonContent.php b/src/Response/JsonContent.php index d71eab8..c2ecac0 100644 --- a/src/Response/JsonContent.php +++ b/src/Response/JsonContent.php @@ -7,13 +7,11 @@ class JsonContent extends ContentBase $this->data = &$data; } - public function &render(): string + public function render(): void { $this->data['__debug__runtime'] = round((hrtime(true) - SCRIPT_STARTED) / 1e+6, 1); - $content = json_encode($this->data); - - return $content; + echo json_encode($this->data); } public function getContentType(): string diff --git a/src/View/Linker.php b/src/View/Linker.php index 360d69c..817d8ac 100644 --- a/src/View/Linker.php +++ b/src/View/Linker.php @@ -2,6 +2,8 @@ class Linker { + const INLINE_ASSET_LIMIT = 2000; + private string $view; public function __construct(string $view) @@ -14,7 +16,7 @@ class Linker $input = ROOT . '/views/' . $this->view . '.php'; $temporaryFiles = []; - $sections = []; + $sections = ['externalCss' => '', 'inlineCss' => '', 'externalJs' => '', 'inlineJs' => '']; $extra = ['', '']; do { @@ -23,6 +25,8 @@ class Linker $extends = $fragment->getExtends(); + $this->generateAssets($fragment, $sections); + $sections = array_merge($sections, $fragment->getSections()); //TODO: detect if section defined multiple times $extra[0] = $fragment->getExtra()[0] . $extra[0]; $extra[1] = $extra[1] . $fragment->getExtra()[1]; @@ -100,4 +104,52 @@ class Linker fclose($inputFileHandle); fclose($outputFileHandle); } + + private function generateAssets(ParsedFragment $fragment, array &$sections) + { + foreach ($fragment->getCss() as $cssFile) { + $asset = $this->parseAsset($cssFile, 'css'); + if (isset($asset['code'])) { + $sections['inlineCss'] .= '' . PHP_EOL; + } elseif (isset($asset['file'])) { + $sections['externalCss'] .= '' . PHP_EOL; + } + } + + foreach ($fragment->getJs() as $jsFile) { + $asset = $this->parseAsset($jsFile, 'js'); + if (isset($asset['code'])) { + $sections['inlineJs'] .= '' . PHP_EOL; + } elseif (isset($asset['file'])) { + $sections['externalJs'] .= '' . PHP_EOL; + } + } + } + + private function parseAsset(string $asset, string $type): array + { + $output = []; + + eval('$asset = ' . $asset . ';'); + + if ( + empty($_ENV['DEV']) && + preg_match('/^' . $type . '\/.*/', $asset) && + filesize(ROOT . '/public/static/' . $asset) < self::INLINE_ASSET_LIMIT + ) { + $output['code'] = file_get_contents(ROOT . '/public/static/' . $asset); + } else { + if (!preg_match('/^http(s)?/', $asset)) { + $output['file'] = $_ENV['STATIC_ROOT'] . '/' . $asset . '?rev=' . REVISION; + } else { + $output['file'] = $asset; + } + } + + return $output; + } } diff --git a/src/View/ParsedFragment.php b/src/View/ParsedFragment.php index 52bbb5b..a270a32 100644 --- a/src/View/ParsedFragment.php +++ b/src/View/ParsedFragment.php @@ -4,13 +4,19 @@ class ParsedFragment { private ?string $extends; + private array $css; + + private array $js; + private array $sections; private array $extra; - public function __construct(?string $extends, array $sections, array $extra) + public function __construct(?string $extends, array $css, array $js, array $sections, array $extra) { $this->extends = $extends; + $this->css = $css; + $this->js = $js; $this->sections = $sections; $this->extra = $extra; } @@ -20,6 +26,16 @@ class ParsedFragment return $this->extends; } + public function getCss(): array + { + return $this->css; + } + + public function getJs(): array + { + return $this->js; + } + public function getSections(): array { return $this->sections; diff --git a/src/View/Parser.php b/src/View/Parser.php index 6cbde82..0356027 100644 --- a/src/View/Parser.php +++ b/src/View/Parser.php @@ -11,11 +11,12 @@ class Parser public function parse(): ParsedFragment { - $sectionOpen = null; $extraOpen = false; $extends = null; + $js = []; + $css = []; $sections = []; $extra = ['', '']; @@ -28,6 +29,18 @@ class Parser while (($line = fgets($fileHandle)) !== false) { ++$lineNumber; + if (($cssMatched = $this->matchCss($line)) !== null) { + $css[] = $cssMatched; + + continue; + } + + if (($jsMatched = $this->matchJs($line)) !== null) { + $js[] = $jsMatched; + + continue; + } + if (($extendsMatched = $this->matchExtends($line)) !== null) { if ($extends !== null) { throw new \Exception('Error in file ' . $this->file . ' in line ' . $lineNumber . ' - There is already an \'@extends\' declared.'); @@ -90,7 +103,25 @@ class Parser fclose($fileHandle); - return new ParsedFragment($extends, $sections, $extra); + return new ParsedFragment($extends, $css, $js, $sections, $extra); + } + + private function matchCss(string $line): ?string + { + if (preg_match('/^\s*@css\((.*)\)\s*$/', $line, $matches)) { + return $matches[1]; + } + + return null; + } + + private function matchJs(string $line): ?string + { + if (preg_match('/^\s*@js\((.*)\)\s*$/', $line, $matches)) { + return $matches[1]; + } + + return null; } private function matchExtends(string $line): ?string diff --git a/views/admin/map_editor.php b/views/admin/map_editor.php index 1ca983f..1f4ca55 100644 --- a/views/admin/map_editor.php +++ b/views/admin/map_editor.php @@ -1,19 +1,12 @@ -@extra - -@endextra +@css('node_modules/leaflet/dist/leaflet.css') +@css('css/map_editor.css') +@css('node_modules/leaflet.markercluster/dist/MarkerCluster.css') +@css('node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css') + +@js('node_modules/leaflet/dist/leaflet.js') +@js('node_modules/leaflet.markercluster/dist/leaflet.markercluster.js') +@js('https://maps.googleapis.com/maps/api/js?key=' . $_ENV['GOOGLE_MAPS_JS_API_KEY']) +@js('js/map_editor.js') @extends('templates/layout_full') @@ -75,7 +68,7 @@ $jsFiles = [ @endsection -@section('pagescript') +@section('pageScript') - @yields('pagescript') + @yields('pageScript') - - - - - - + @yields('externalJs') + @yields('inlineJs')