Resource.php

<?php

namespace ROF;

class Resource {

    static protected $instance;

    static public function instance($newInstance=NULL){
        if ($newInstance instanceof \ROF\Resource){
            static::$instance = $newInstance;
        } else if (!(static::$instance instanceof \ROF\Resource)){
            static::$instance = new \ROF\Resource();
        }
        return static::$instance;
    }


    public $data = [
        "default"=>[
            "auto_key"=>[],
            "text"=>[],
            "compiled"=>[],
            "set"=>[],
            "stylesheet"=>[],
        ],
    ];

    public $stylesheets = [];
    public $scripts = [];
    public $basedir;
    public $compileDir;
    public $compileUrl;
    public $decoder;

    public function __construct(){
        $this->decoder = new \ROF\Resource\Decoder();
    }

    public function addFiles($files){
        foreach ($files as $file){
            $this->addFile($file,'default');
        }
    }
    public function parseString($string,$type=NULL){
        if ($type===null)return $this->decoder->parseString($string);
        else return $this->decoder->parseString($string, $type);
    }
    public function addParsed($data){
        // echo "add parsed data\n";
        // print_r($data);
        $this->data = (array)array_merge_recursive($this->data,['default'=>(array)$data]);

    }
    public function addFile($file){
        $data = $this->decoder->parseFile($file);
        // print_r($data);
        // exit;
        if ($data===NULL){
            throw new \Exception("Did not find valid data at ".$file);
        }
        $this->addParsed($data);
    }

    public function all(){

    }
    public function getNamespace($parts){
        $ns = $parts[0];
        if (isset($this->data[$ns])){
            return $ns;
        }

        return 'default';
    }
    public function parseLookup($lookupString){
        $pieces =  explode('.',$lookupString);
        
        $namespace = 'default';
        if (isset($this->data[$pieces[0]])){
            $namespace = $pieces[0];
            array_shift($pieces);
        }
        $key = "auto_key";
        if (isset($pieces[0])&&isset($this->data[$namespace][$pieces[0]])){
            $key = $pieces[0];
            array_shift($pieces);
        }
        return [
            'namespace'=>$namespace,
            'key'=>$key,
            'lookup'=>implode('.',$pieces),
        ];
    }
    public function getValue($namespace,$key,$lookupString){
        $next = $this->data[$namespace][$key];
        $pieces = explode('.',$lookupString);
        // var_dump($next);
        foreach($pieces as $index=>$piece){
            if (is_array($next)
                    &&isset($next[$piece])){
                $next = $next[$piece];
                continue;
            } else {
                throw new \Exception("Value is not set for '{$piece}' in the lookup key '{$key}.{$lookupString}'");
            }
        }

        $value = $next;
        return $value;
    }
    protected function getCompiledStylesheet(){
        $compilation = '';
        foreach ($this->stylesheets as $path){
            $path = $this->basedir.'/'.$path;
            $compilation .="\n\n/* ---start ".basename($path)."--- */\n\n";
            $compilation .= file_exists($path) ? file_get_contents($path) : "/* ".basename($path)." was not found */";
        }
        return $compilation;
    }
    public function parseValue($value,$lookupParts){
        if ($lookupParts['key']=='compiled'){
            $pieces = explode('.',$lookupParts['lookup']);
            if ($lookupParts['lookup']=='stylesheet'){
                $compiled = $this->getCompiledStylesheet();
                return $compiled;
            } else if ($lookupParts['lookup']=='stylesheet.linktag'){
                if (count($this->stylesheets)==0){
                    return '<!-- no stylesheets to compile -->'."\n";
                }
                $url = $this->compileUrl;
                $fileName = $this->compileStyle();
                $url .= '/'.$fileName;
                $url = str_replace('//','/',$url);
                return '<link rel="stylesheet" type="text/css" href="'.$url.'">'."\n";
            } else if ($lookupParts['lookup']=='script.scripttag'){
                if (count($this->scripts)==0){
                    return '<!-- no scripts to compile -->'."\n";
                }
                $url = $this->compileUrl;
                $fileName = $this->compileScript();
                $url .= '/'.$fileName;
                $url = str_replace('//','/',$url);
                return '<script type="text/javascript" src="'.$url.'"></script>'."\n";
            }
        } else {
            return $value;
        }
    }
    public function compileStyle(){
        $sheets = $this->stylesheets;
        sort($sheets,SORT_REGULAR);
        $compiledFile = implode('_',$sheets);
        $compiledFile = 'compiled'.str_replace(['/','.css'],['-',''], $compiledFile).'.css';
        $compiledPath = $this->compileDir.'/'.$compiledFile;
        
        $compMtime = file_exists($compiledPath) ? filemtime($compiledPath) : 0;
        $recompile = FALSE;
        foreach ($sheets as $path){
            $path = $this->basedir.'/'.$path;
            if (filemtime($path)>=$compMtime){
                $recompile = TRUE;
                break;
            }
            
        }
        if ($recompile){
            $compilation = '';
            foreach ($sheets as $path){
                $path = $this->basedir.'/'.$path;
                $compilation .="\n\n/* ---start ".basename($path)."--- */\n\n";
                $compilation .= file_exists($path) ? file_get_contents($path) : "/* ".basename($path)." was not found */";
            }
            file_put_contents($compiledPath,$compilation);
        }
        $mtime = filemtime($compiledPath);
        return $compiledFile.'?updated_at='.date('y-z-G-i-s',$mtime);
    }
    public function compileScript(){
        $scripts = $this->scripts;
        sort($scripts,SORT_REGULAR);
        $compiledFile = implode('_',$scripts);
        $compiledFile = 'compiled'.str_replace(['/','.js'],['-',''], $compiledFile).'.js';
        $compiledPath = $this->compileDir.'/'.$compiledFile;
        
        $compMtime = file_exists($compiledPath) ? filemtime($compiledPath) : 0;
        $recompile = FALSE;
        foreach ($scripts as $path){
            $path = $this->basedir.'/'.$path;
            if (filemtime($path)>=$compMtime){
                $recompile = TRUE;
                break;
            }
            
        }
        if ($recompile){
            $compilation = '';
            foreach ($scripts as $path){
                $path = $this->basedir.'/'.$path;
                $compilation .="\n\n/* ---start ".basename($path)."--- */\n\n";
                $compilation .= file_exists($path) ? file_get_contents($path) : "/* ".basename($path)." was not found */";
            }
            file_put_contents($compiledPath,$compilation);
        }
        
        $mtime = filemtime($compiledPath);
        return $compiledFile.'?updated_at='.date('y-z-G-i-s',$mtime);
    }
    public function setValue($lookupString,$newValue){
        $parts = $this->parseLookup($lookupString);
        if ($parts['lookup']=='stylesheet'){
            $this->stylesheets[] = $newValue;
            return true;
        } else if ($parts['lookup']=='script'){
            $this->scripts[] = $newValue;
            return true;
        } else if ($parts['lookup']=='basedir'){
            $this->basedir = $newValue;
        } else if ($parts['lookup']=='stylesheet.dir'){
            $baseDir = $newValue;
            $handle = opendir($baseDir);
            while ($file = readdir($handle)){
                if ($file=='.'||$file=='..')continue;
                $newPath = $baseDir.'/'.$file;
                if (is_dir($newPath)){
                    $this->setValue('set.stylesheet.dir',$newPath);
                } else {
                    if (substr($newPath,0,strlen($this->basedir))==$this->basedir){
                        $newPath = substr($newPath,strlen($this->basedir));
                        $this->setValue('set.stylesheet',$newPath);
                    } else {
                        $this->setValue('set.stylesheet',$newPath);
                    }
                    
                }
            }
        } else if ($parts['lookup']=='script.dir'){
            $baseDir = $newValue;
            $handle = opendir($baseDir);
            while ($file = readdir($handle)){
                if ($file=='.'||$file=='..')continue;
                $newPath = $baseDir.'/'.$file;
                if (is_dir($newPath)){
                    $this->setValue('set.script.dir',$newPath);
                } else {
                    if (substr($newPath,0,strlen($this->basedir))==$this->basedir){
                        $newPath = substr($newPath,strlen($this->basedir));
                        $this->setValue('set.script',$newPath);
                    } else {
                        $this->setValue('set.script',$newPath);
                    }
                    
                }
            }
        } else if ($parts['lookup']=='compile.dir'){
            $this->compileDir = $newValue;
        } else if ($parts['lookup']=='compile.url'){
            $this->compileUrl = $newValue;
        }
        return false;
    }
    public function getResource($lookupString, $newValue=NULL){
        $parts = $this->parseLookup($lookupString);
        if ($parts['key']=='set'
            &&$newValue!==NULL){
            $this->setValue($lookupString,$newValue);
            return null;
        }
        $value = $this->getValue($parts['namespace'],$parts['key'],$parts['lookup']);
        $parsed = $this->parseValue($value,$parts);

        return $parsed;

    }

    public function setScopedName($callingFile,$callingFunction){

    }

    
}
require_once(__DIR__.'/R_funcs.php');