ViewRoot.php
<?php
namespace Fresh;
class ViewRoot {
public $file;
protected $compFile;
public $name;
protected $passthru;
protected $setupCode = [];
protected $queries = [];
protected $compileHandlers = [];
protected $runtimeHandlers = [];
protected $findHandler = null;
public function __construct($viewFile,$viewName,$passthru=[]){
$this->file = $viewFile;
$this->name = $viewName;
$this->passthru = $passthru;
$this->compFile = dirname($this->file).'/compiled/'.$viewName.'.php';
$this->initialize();
}
public function setPassthru($passthru){
$this->passthru = $passthru;
}
public function addFormatter($name,$callback){
$this->addRuntimeHandler('format_'.$name,$callback);
}
public function addQuery($xpath,$callable){
$this->queries[] = ['xpath'=>$xpath,'callback'=>$callable];
}
public function addCompileHandler($name,$callable){
$this->compileHandlers[$name][] = $callable;
}
protected function executeCompileHandlers($handlerName, ...$args){
$handlers = $this->compileHandlers[$handlerName] ?? null;
if ($handlers===null)return;
foreach ($handlers as $handler){
$handler(...$args);//$this,$rbAttrs,$prop,$attribute->value);
}
}
public function addRuntimeHandler($name,$callable){
// $this->runtimeHandlers[$name][] = $callable;
$this->runtimeHandlers[$name] = $callable;
}
public function __call($method,$args){
if (!isset($this->runtimeHandlers[$method]))throw new \BadMethodCallException("Method '{$method}' does not exist.");
$handler = $this->runtimeHandlers[$method];
// print_r($handler);
// exit;
return $handler(...$args);
}
public function compile($forceRecompile=false){
$file = $this->file;
$compFile = $this->compFile;
if (!$forceRecompile&&
true&&
file_exists($compFile)&&filemtime($file)<filemtime($compFile)){
return $compFile;
}
$viewContent = file_get_contents($file);
// echo $viewContent."\n\n";
$compiler = new \RBCompiler();
$cleanSource = $compiler->cleanSource($viewContent);
$preDocHandlers = $this->compileHandlers['pre-doc'];
foreach ($preDocHandlers as $handler){
$cleanSource = $handler($cleanSource,$viewContent,$compiler,$this);
}
$doc = new \RBDoc($cleanSource);
$compiler->appendCode($doc);
foreach ($this->queries as $queryInfo){
//TODO perform all queries before calling any handlers
//TODO pass doc to the handler (in case the node gets removed from the doc)
$xpath = $queryInfo['xpath'];
$callback = $queryInfo['callback'];
$xp = new \DOMXpath($doc);
$nodeList = $xp->query($xpath);
foreach ($nodeList as $node){
$callback($doc,$this,$compiler,$node);
}
}
$output = $compiler->output();
// echo "output:\n\n";
// echo $output;
// echo "\n\n\n----done";
// exit;
$compiler->writeTo($compFile);
$this->writeSetupCode();
return $compFile;
}
protected function output(){
$compiledFile = $this->compile();
// var_dump($this->passthru);
// exit;
extract($this->passthru);
ob_start();
require($compiledFile);
return ob_get_clean();
}
public function __toString(){
$output = $this->output();
return $output;
}
public function writeSetupCode(){
$compDir = dirname($this->compFile).'/setup/';
$setupFile = $compDir.basename($this->compFile);
if (!is_dir($compDir))mkdir($compDir);
file_put_contents($setupFile,implode('',$this->setupCode));
}
public function appendSetupCode($code){
$this->setupCode[] = $code;
}
public function setup($passthru=[]){
$compDir = dirname($this->compFile).'/setup/';
$setupFile = $compDir.basename($this->compFile);
extract($passthru);
if (file_exists($setupFile))require($setupFile);
}
}