ViewRoot.php
<?php
namespace Fresh;
class ViewRoot {
use \Fresh\Readonly;
protected $file;
private $r_file;
protected $name;
private $r_name;
protected $src;
private $r_src;
protected $handler;
private $r_handler;
protected $compFile;
protected $passthru = [];
private $r_passthru;
protected $setupCode = [];
protected $component;
private $r_component;
public function __construct($component,$viewName,$passthru=[]){
$this->component = $component;
$this->file = $this->fileFor($viewName);
$this->name = $viewName;
$this->passthru = $passthru;
$this->handler = new \Fresh\Handler();
$this->addRuntimeHandler('compileAndAddResources',[$this,'compileResourcesAndOutsource']);
$this->src = file_get_contents($this->file);
$this->compFile = $this->compileFileFor($viewName);
$this->initialize();
}
public function compileResourcesAndOutsource(){
$c = 0;
$list = [
'css'=>[],
'js'=>[],
'php'=>[]
];
$name = basename($this->file);
$name = substr($name,0,strrpos($name,'.'));
$dir = dirname($this->file);
$path = $dir.'/'.$name;
$cssFile = $path.'.css';
if (file_exists($cssFile)){
$list['css'][] = $cssFile;
$c++;
}
$jsFile = $path.'.js';
if (file_exists($jsFile)){
$list['js'][] = $jsFile;
$c++;
}
$resourceDir = $path.'/';
if (is_dir($resourceDir)){
$rii = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($resourceDir));
$files = array();
foreach ($rii as $file) {
if ($file->isDir()){
continue;
}
$c++;
$list[$file->getExtension()][] = $file->getPathname();
}
}
if ($c>0){
$this->callHandler('addResources',$this,$list);
}
}
protected function fileFor($viewName){
if ($viewName=='')$viewName = 'View';
$file = $this->component->dir.'/view/'.$viewName.'.php';
return $file;
}
protected function compileFileFor($viewName){
return $this->component->dir.'/compiled/'.$viewName.'.php';
}
public function form(){
$form = $this->component->form($this->name);
return $form;
}
public function view(){
$view = $this->component->view($this->name);
return $view;
}
public function setPassthru($passthru){
$this->passthru = $passthru;
}
public function addFormatter($name,$callback){
$this->handler->setHandler('runtime','format_'.$name,$callback);
}
public function addQuery($xpath,$callable){
$this->handler->addHandler('query','all',['xpath'=>$xpath,'callback'=>$callable]);
}
public function addCompileHandler($name,$callable){
$this->handler->addHandler('compile',$name,$callable);
}
protected function executeCompileHandlers($handlerName, ...$args){
$handlers = $this->handler->compile->$handlerName;
if ($handlers===null)return;
$ret = [];
foreach ($handlers as $handler){
$ret[] = $handler(...$args);
}
return $ret;
}
public function addRuntimeHandler($name,$callable){
$this->handler->addHandler('runtime',$name,$callable);
}
public function setRuntimeHandler($name,$callable){
$this->handler->setHandler('runtime',$name,$callable);
}
public function callHandler($method,...$args){
return $this->handler->callMethod('runtime',$method,$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);
$compiler = new \Taeluf\PHTML\Compiler();
$cleanSource = $compiler->cleanSource($viewContent);
$preDocHandlers = $this->handler->compile->preDoc ?? [];
foreach ($preDocHandlers as $handler){
$cleanSource = $handler($cleanSource,$viewContent,$compiler,$this);
}
$doc = new \Taeluf\PHTML($cleanSource);
$compiler->appendCode($doc);
$queryResults = [];
$qRes = [];
foreach ($this->handler->query->all as $queryInfo){
$xpath = $queryInfo['xpath'];
$callback = $queryInfo['callback'];
$nodeList = $doc->xpath($xpath);
$qRes[] = [
'callback'=>$callback,
'xpath'=>$xpath,
'nodes'=>$nodeList
];
}
foreach ($qRes as $qi){
foreach ($qi['nodes'] as $node){
$qi['callback']($doc,$this,$compiler,$node);
}
}
$compiler->prependCode('<?php $this->callHandler(\'compileAndAddResources\');?>');
$compiler->writeTo($compFile,0660);
$this->writeSetupCode();
return $compFile;
}
protected function output(){
$compiledFile = $this->compile();
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,0771,true);
}
file_put_contents($setupFile,implode('',$this->setupCode));
}
public function appendSetupCode($code){
$this->setupCode[] = trim($code);
}
public function setup($passthru=[]){
$compDir = dirname($this->compFile).'/setup/';
$setupFile = $compDir.basename($this->compFile);
extract($passthru);
if (file_exists($setupFile))require($setupFile);
}
}