path); $folder = __DIR__ . '/../../../storage/framework/views'; if (!is_file("{$folder}/{$hash}.php")) { touch("{$folder}/{$hash}.php"); } $cached = realpath("{$folder}/{$hash}.php"); if (!file_exists($hash) || filemtime($view->path) > filemtime($hash)) { $content = $this->compile(file_get_contents($view->path)); file_put_contents($cached, $content); } extract($view->data); ob_start(); include($cached); $contents = ob_get_contents(); ob_end_clean(); if ($layout = $this->layouts[$cached] ?? null) { $contentsWithLayout = view($layout, array_merge( $view->data, ['contents' => $contents], )); return $contentsWithLayout; } return $contents; } protected function compile(string $template): string { // replace `@extends` with `$this->extends` $template = preg_replace_callback('#@extends\(((?<=\().*(?=\)))\)#', function($matches) { return 'extends(' . $matches[1] . '); ?>'; }, $template); // replace `@if` with `if(...):` $template = preg_replace_callback('#@if\(((?<=\().*(?=\)))\)#', function($matches) { return ''; }, $template); // replace `@endif` with `endif;` $template = preg_replace_callback('#@endif#', function($matches) { return ''; }, $template); // replace `@foreach` with `foreach(...):` $template = preg_replace_callback('#@foreach\(((?<=\().*(?=\)))\)#', function($matches) { return ''; }, $template); // replace `@endforeach` with `endforeach;` $template = preg_replace_callback('#@endforeach#', function($matches) { return ''; }, $template); // replace `@[anything](...)` with `$this->[anything](...)` $template = preg_replace_callback('#\s+@([^(]+)\(((?<=\().*(?=\)))\)#', function($matches) { return '' . $matches[1] . '(' . $matches[2] . '); ?>'; }, $template); // replace `{{ ... }}` with `print $this->escape(...)` $template = preg_replace_callback('#\{\{([^}]*)\}\}#', function($matches) { return 'escape(' . $matches[1] . '); ?>'; }, $template); // replace `{!! ... !!}` with `print ...` $template = preg_replace_callback('#\{!!([^}]+)!!\}#', function($matches) { return ''; }, $template); return $template; } protected function extends(string $template): static { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); $this->layouts[realpath($backtrace[0]['file'])] = $template; return $this; } public function __call(string $name, $values) { return $this->manager->useMacro($name, ...$values); } }