response = $responseHtml; $this->cache = $cache ?? new Caching\Memory(""); $this->context = $context ?? new Compiler\BaseContext(); $this->languageRegistration = $languageRegistration ?? new Language\DefaultRegistrations(); $this->builderTemplatePath = $builderTemplatePath ?? dirname(__FILE__) . static::DEFAULT_BUILDER_TEMPLATE; $this->compiler = $compiler ?? $this->instanciateCompiler(); $this->fileFetcher = $fileFetcher ?? $this->instanciateFileFetcher(); $this->debug = $debug; #$this->context->exportFunctions(); $this->renderContext($this->context); } public function renderHtml(string $viewPath, array $variables = [], ?object $proxy = null) : string { if ( null === $object = $this->fetchFromCache($viewPath, $variables, $proxy) ) { throw new \RuntimeException("An error occured while trying to save a compiled template."); } return $object(); } public function renderContext(Compiler\Context $context) : object { if ( null === $object = $this->contextFromCache($context) ) { throw new \RuntimeException("An error occured while trying to save a compiled template."); } return $object; } #public function outputHtml(string $viewPath, array $variables) : ResponseInterface #{ # if ( $this->response ?? false ) { # if ( false === $content = $this->cache->handle($viewPath) ) { # # } # $source = $this->compileSource($source ?? "test"); # $response = $this->response; # return $response("abc"); # } # throw new \InvalidArgumentException("No \Psr\Http\Message\ResponseInterface closure provided. Please provide one using the constructor or assigning it to the class variable `responseHtml`."); #} public function compileSource(string $source) : array { $this->compiler->loadSourceCode($source); return [ 'context' => $context = clone $this->context, 'source' => $this->compiler->compile($context), ]; } public function compileFile(string $viewPath) : array { if (! file_exists($viewPath) ) { throw new \InvalidArgumentException("File `$viewPath` cannot be found or there is a permission problem."); } if ( false === $fileContent = file_get_contents($viewPath) ) { throw new \ErrorException("Given file could not be opened `$viewPath`. This could indicate a permission misconfiguration on your file or folder."); } $this->compiler->loadSourceCode($fileContent); $context = clone $this->context; $context->viewPath = $viewPath; $context->source = $this->compiler->compile($context); return $context; } public function buildFromSource(string $source) : array { $tmpFolder = sys_get_temp_dir(); $builder = $this->instanciateBuilder(); $compiledSource = $this->compileSource($source); list($namespace, $className, $compiledSource) = $builder->build($compiledSource['context'], $compiledSource['source']) ; $path = "$tmpFolder/$className.php"; file_put_contents($path, $compiledSource); return [ 'path' => $path, 'namespace' => $namespace, 'className' => $className, ]; } public function fetchFromCache(string $viewPath, array $variables = [], ?object $proxy = null) : ?object { if ( $this->debug || ! $this->cache->compiled($viewPath) ) { $context = $this->compileView($viewPath); $this->cache->save($context); if ( $context->extendFrom ) { $this->fetchFromCache($context->extendFrom, $variables, $proxy); } } return $this->cache->load($viewPath, $this, $variables, $proxy); } public function contextFromCache(Compiler\Context $context) : ?object { if ( $this->debug || ! $this->cache->compiled( $context->cacheFilename() ) ) { $context = $this->compileContext($context); $this->cache->save($context); } return $this->cache->load($context->cacheFilename(), $this); } public function instanciateCompiler() : Compiler { return new Compiler($this->languageRegistration); } public function instanciateBuilder() : Builder { return new Builder($this->builderTemplatePath); } public function instanciateFileFetcher() : FileFetcher { return new FileFetcher(); } public function registerAll(Compiler $compiler) : void { $this->registerSyntax($compiler); $this->registerControlStructure($compiler); $this->registerExtension($compiler); } public function registerSyntax(Compiler $compiler) : void { $this->languageRegistration->registerSyntax($compiler); } public function registerControlStructure(Compiler $compiler) : void { $this->languageRegistration->registerControlStructure($compiler); } public function registerExtension(Compiler $compiler) : void { $this->languageRegistration->registerExtension($compiler); } protected function compileView(string $viewPath) : Compiler\Context { $tmpFolder = sys_get_temp_dir(); $builder = $this->instanciateBuilder(); $compiled = $this->compileSource($this->fileFetcher->getFileContent($viewPath)); $context = $compiled['context']; $context->viewPath = $viewPath; $context = $builder->build($compiled['context'], $compiled['source']) ; $context->classPath = $tmpFolder . DIRECTORY_SEPARATOR . $context->className . ".php"; if ( $context->extendFrom ) { $this->compileView($context->extendFrom); } return $context; } protected function compileContext(Compiler\Context $context) : Compiler\Context { $tmpFolder = sys_get_temp_dir(); $builder = $this->instanciateBuilder(); $compiled = $this->compileSource(""); $context->viewPath = $context->cacheFilename(); $builder->build($context, ""); $context->classPath = $tmpFolder . DIRECTORY_SEPARATOR . $context->cacheFilename() . ".php"; return $context; } }