view = $view; } public function generate(): void { $input = ROOT . '/views/' . $this->view . '.php'; $temporaryFiles = []; $sections = []; $extra = ['', '']; do { $parser = new Parser($input); $fragment = $parser->parse(); $extends = $fragment->getExtends(); $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]; if ($extends === null) { $this->writeFinal($extra, $input, ROOT . '/cache/views/' . $this->view . '.php'); break; } $tmpFile = tempnam(sys_get_temp_dir(), 'mapg-view-'); $temporaryFiles[] = $tmpFile; $this->extendTemplate($sections, ROOT . '/views/' . $extends . '.php', $tmpFile); $input = $tmpFile; } while (true); foreach ($temporaryFiles as $tmpFile) { unlink($tmpFile); } } private function extendTemplate(array $sections, string $file, string $output): void { $inputFileHandle = fopen($file, 'r'); if (!$inputFileHandle) { throw new \Exception('Cannot open file ' . $file); } $outputFileHandle = fopen($output, 'w'); if (!$outputFileHandle) { throw new \Exception('Cannot open file ' . $output . 'for writing.'); } $lineNumber = 0; while (($line = fgets($inputFileHandle)) !== false) { ++$lineNumber; if (preg_match('/^\s*@yields\(\'([\w\/]+)\'\)\s*$/', $line, $matches)) { if (isset($sections[$matches[1]])) { fwrite($outputFileHandle, $sections[$matches[1]]); } } else { fwrite($outputFileHandle, $line); } } fclose($inputFileHandle); fclose($outputFileHandle); } private function writeFinal(array $extra, string $file, string $output): void { $dirname = pathinfo($output, PATHINFO_DIRNAME); if (!is_dir($dirname)) { mkdir($dirname, 0755, true); } $inputFileHandle = fopen($file, 'r'); if (!$inputFileHandle) { throw new \Exception('Cannot open file ' . $file); } $outputFileHandle = fopen($output, 'w'); if (!$outputFileHandle) { throw new \Exception('Cannot open file ' . $output . 'for writing.'); } fwrite($outputFileHandle, $extra[0]); while (($line = fgets($inputFileHandle)) !== false) { fwrite($outputFileHandle, $line); } fwrite($outputFileHandle, $extra[1]); fclose($inputFileHandle); fclose($outputFileHandle); } }