viewsPath = rtrim($viewsPath, '/') . '/'; $this->debugMode = $debugMode; } public function render($file, $data = []) { try { $code = $this->includeFiles($file); $code = $this->compileCode($code); extract($data, EXTR_SKIP); ob_start(); eval('?>' . $code); return ob_get_clean(); } catch(Exception $e) { if($this->debugMode) echo "Error rendering template: " . $e->getMessage(); throw $e; } } private function compileCode($code) { $code = $this->compileBlock($code); $code = $this->compileYield($code); $code = $this->compileEchos($code); $code = $this->compilePHP($code); return $code; } private function includeFiles($file) { $filePath = $this->viewsPath . preg_replace("/\.twig$/", "", $file) . ".twig"; if(!file_exists($filePath)) throw new Exception("View file not found: {$filePath}"); $code = file_get_contents($filePath); preg_match_all('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', $code, $matches, PREG_SET_ORDER); foreach($matches as $match) { $includedCode = $this->includeFiles($match[2]); $code = str_replace($match[0], $includedCode, $code); } return preg_replace('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', '', $code); } private function compilePHP($code) { return preg_replace('~\{%\s*(.+?)\s*%}~is', '', $code); } private function compileEchos($code) { $code = preg_replace('~\{\{\s*(.+?)\s*\}\}~is', '', $code); return preg_replace('~\{\{\{\s*(.+?)\s*\}\}\}~is', '', $code); } private function compileEscapedEchos($code) { return preg_replace('~\{{{\s*(.+?)\s*}}}~is', '', $code); } private function compileBlock($code) { preg_match_all('/{% ?block ?(.*?) ?%}(.*?){% ?endblock ?%}/is', $code, $matches, PREG_SET_ORDER); foreach($matches as $match) { if(!isset($this->blocks[$match[1]])) $this->blocks[$match[1]] = ''; $this->blocks[$match[1]] = str_replace('@parent', $this->blocks[$match[1]], $match[2]); $code = str_replace($match[0], '', $code); } return $code; } private function compileYield($code) { foreach($this->blocks as $block => $value) $code = preg_replace('/{% ?yield ?' . $block . ' ?%}/', $value, $code); return preg_replace('/{% ?yield ?(.*?) ?%}/i', '', $code); } }