123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985 |
- <?php namespace Maze\Template;
- use Maze\File\Path;
- use Maze\Debug\Process as Debug;
- use Maze\Config\Load as Config;
- class Compile
- {
- /**
- * left
- *
- * @var const string
- */
- const left = '<?php ';
- /**
- * right
- *
- * @var const string
- */
- const right = ' ?>';
- /**
- * file
- *
- * @var string
- */
- protected $file;
-
- /**
- * path
- *
- * @var string
- */
- protected $path;
- /**
- * template
- *
- * @var string
- */
- protected $template;
- /**
- * content
- *
- * @var array
- */
- protected $content;
- /**
- * update
- *
- * @var bull
- */
- protected $update = false;
- /**
- * load file
- * @param string $file
- * @param string $path
- * @param string $service
- * @param string $project
- *
- * @return mixed
- */
- public function __construct($file, $template, $service, $project = false, $path = '')
- {
- $this->path = $path;
- $this->project($project);
-
- $this->file = $this->path($path . $file) . '.cmp.php';
- Debug::log($this->file);
- $this->read($file, $template, $service);
- }
- /**
- * read file
- * @param string $file
- * @param string $path
- * @param string $service
- * @param bool $local
- *
- * @return mixed
- */
- public function read($file, $path, $service, $local = false)
- {
- if(strpos($file, 'http://'))
- {
- $content = file_get_contents($file);
- # 增加抓取功能 本地化
- if($local == true)
- {
- $content = $this->local($content);
- }
- $this->template = $content;
- }
- else
- {
- $this->template = $path . $file . '.html';
- if(is_file($this->template))
- {
- $is_service = is_file($service);
- $time = is_file($this->file) ? filemtime($this->file) : 0;
- $this->update = defined('MAZE_COMPILE');
- if(filemtime($this->template) > $time || ($is_service && filemtime($service) > $time))
- {
- # 可以更新
- $this->update = true;
- }
- if($time == 0 || $this->update == true)
- {
- $content = $this->readContent($path);
- }
- if(!empty($content) && !$is_service)
- {
- return $this->create($content);
- }
- }
- else
- {
- # 当文件不存在时
- $this->update = false;
- }
- }
- }
- /**
- * readContent 获取当前模板的内容
- *
- * @return string
- */
- public function readContent($path)
- {
- # 这里直接用content传过去效率高
- $content = file_get_contents($this->template);
- if(strpos($content, '@include:') !== false)
- {
- $temp = explode('@include:', $content);
- $file = end($temp);
- $this->template = $path . $file . '.html';
- $content = file_get_contents($this->template);
- }
- # 远程读取
- elseif(strpos($content, '@url:') !== false)
- {
- //$config = $content;
- $content = str_replace("\n", '', $content);
- $temp = explode('@url:', $content);
- $this->template = end($temp);
- //$this->template = end(explode('@url:', $config));
- $content = file_get_contents($this->template);
-
- # 增加资源处理功能 @res:replace 将资源中的路径替换为带有域名的路径 @res:local 本地化
- if(strpos($temp[0], '@res:') !== false)
- {
- $temp = explode('@res:', $temp[0]);
- $content = $this->res(end($temp), $content, $this->template, $path);
- }
- }
- $this->template = $content;
- return $content;
- }
- /**
- * res 资源处理 此处待优化
- *
- * @return string
- */
- private function res($type, $content, $url, $path)
- {
- //return $content;
-
- $encode = mb_detect_encoding($content, array('GB2312','GBK','UTF-8'));
- if($encode == 'GB2312' || $encode == 'GBK' || $encode == 'EUC-CN' || $encode == 'CP936')
- {
- $content = iconv('GBK', 'UTF-8', $content);
- }
- # 过滤换行
- $content = str_replace(PHP_EOL, '', $content);
-
- if($type == 'local')
- {
- # 规则
- $rule = '<link(.*?)href="(.*?)"';
- preg_match_all('/' . $rule . '/i', $content, $result);
- $rule = '<script src="(.*?)"(.*?)<\/script>';
- preg_match_all('/' . $rule . '/i', $content, $result);
- }
- elseif(strpos($type, 'include:') !== false)
- {
- $temp = explode('include:', $type);
- $file = end($temp);
- $include = str_replace("\n", '', file_get_contents($path . $file . '.html'));
- parse_str($include, $param);
-
- foreach($param as $k => $v)
- {
- $content = $this->replace($k, $v, $content);
- }
- }
- else
- {
- parse_str($type, $param);
-
- foreach($param as $k => $v)
- {
- $content = $this->replace($k, $v, $content);
- }
- }
- return $content;
- }
- /**
- * get file
- *
- * @return string
- */
- public function file()
- {
- return $this->file;
- }
- /**
- * get template or content
- *
- * @return string
- */
- public function template()
- {
- return $this->template;
- }
- /**
- * project
- *
- * @return string
- */
- public function project($project = false)
- {
- $this->project = $project ? $project : MAZE_PROJECT_NAME;
- return $this->project;
- }
- /**
- * path create path
- * @param string $file
- * @param string $project
- *
- * @return string
- */
- public function path($file, $path = 'compile')
- {
- return Path::create(MAZE_PATH . 'data/' . $path . '/' . $this->project . '/', $file);
- }
- /**
- * get
- *
- * @return mixed
- */
- public function get()
- {
- if($this->update == false && is_file($this->file))
- {
- ob_start();
- require $this->file;
- $content = ob_get_contents();
- ob_end_clean();
- return $content;
- }
- elseif($this->update == false)
- {
- return '';
- }
- else
- {
- return false;
- }
- }
- /**
- * load view
- *
- * @param string $service
- * @return \Maze\Template\View
- */
- public function load($file, $path = '')
- {
- $desc = '<!--{'.$path.'/'.$file.'}-->';
- $view = View::getInstance($file);
- if($path)
- {
- $view->path($path);
- }
- else
- {
- $view->path($this->path);
- }
- $view->runing();
- $file = $view->file();
- if($file)
- {
- return $desc . $this->script('require MAZE_PATH . \'' . str_replace(MAZE_PATH, '', $file) . '\'') . $desc;
- }
- }
- /**
- * create
- * @param string $content
- *
- * @return string
- */
- public function create($content)
- {
- $this->update = false;
- if($this->content)
- {
- $content = implode("\n", $this->content) . "\n" . $content;
- }
- $this->write($this->assets($content));
- return $this->get();
- }
- /**
- * write
- *
- * @return mixed
- */
- public function write($content)
- {
- $content = preg_replace('/<!--(.*?)-->/s', '', $content);
-
- if(isset(Config::$global['host']['merge']) && Config::$global['host']['merge'] && strpos($content, Config::$global['host']['assets']) !== false)
- {
- $this->merge
- (
- array('<link(.*?)href=[\'|"](.*?)[\'|"](.*?)>', '<script([a-zA-Z\/"\'=\\s]+)src=[\'|"](.*?)[\'|"](.*?)<\/script>'),
- $content
- );
- }
- $copyright = '<!--power by mazephp-->';
- file_put_contents($this->file, $copyright . $content);
- @chmod($this->file, 0755);
- system('chmod -R ' . $this->file . ' 777');
- }
-
- /**
- * assets
- * @param string $content
- *
- * @return string
- */
- public function assets($content)
- {
- if(isset(Config::$global['base']['replace']) && is_array(Config::$global['base']['replace']))
- {
- foreach(Config::$global['base']['replace'] as $k => $v)
- {
- if(isset(Config::$global['host'][$k]))
- {
- $content = $this->replace($v, Config::$global['host'][$k], $content);
- }
- }
- }
- return $content;
- }
- /**
- * merge
- *
- * @return string
- */
- private function merge($rule, &$content)
- {
- foreach($rule as $k => $v)
- {
- $v = '/' . $v . '/i';
- preg_match_all($v, $content, $result);
- //print_r($result);
- if(isset($result[2]) && $result[2])
- {
- if($k == 1)
- {
- $ext = 'js';
- $fext = ';';
- }
- else
- {
- $ext = 'css';
- $fext = '';
- }
- $file = md5($this->file) . '.' . $ext;
-
- $host = Config::$global['host']['merge'] . $this->project . '/' . $file . '?v' . MAZE_TIME;
-
- $file = $this->path($file, 'assets');
-
- $assets = '';
- foreach($result[2] as $fk => $fv)
- {
- if($fv)
- {
- $fv = str_replace(Config::$global['host']['assets'], Config::$global['base']['assets'], $fv);
-
- $assets .= file_get_contents($fv) . $fext;
-
- if(strpos($content, '{{file}}') === false)
- {
- $content = str_replace($result[0][$fk], '{{file}}', $content);
- }
- else
- {
- $content = str_replace($result[0][$fk], '', $content);
- }
- }
- }
-
- if($assets)
- {
- $method = 'zip_' . $ext;
- $assets = $this->assets($assets);
- file_put_contents($file, $this->$method($assets));
- }
- $file = $k == 1 ? '<script type="text/javascript" src="'.$host.'"></script>' : '<link rel="stylesheet" type="text/css" href="'.$host.'" />';
-
- //$content = $this->zip_css($content);
-
- $content = str_replace('{{file}}', $file, $content);
- }
- }
- }
-
- /**
- * zip_css
- * @param string $string
- *
- * @return string
- */
- private function zip_css($string)
- {
- return str_replace(array("\t", "\r\n", "\r", "\n"), '', $string);
- }
-
- /**
- * zip_js
- * @param string $string
- *
- * @return string
- */
- private function zip_js($string)
- {
- return $string;
- $h1 = 'http://';
- $s1 = '【:??】';
- $h2 = 'https://';
- $s2 = '【s:??】';
- $string = preg_replace('#function include([^}]*)}#isU','',$string);//include函数体
- $string = preg_replace('#\/\*.*\*\/#isU','',$string);//块注释
- $string = str_replace($h1,$s1,$string);
- $string = str_replace($h2,$s2,$string);
- $string = preg_replace('#\/\/[^\n]*#','',$string);//行注释
- $string = str_replace($s1,$h1,$string);
- $string = str_replace($s2,$h2,$string);
- $string = preg_replace('#\s?(=|>=|\?|:|==|\+|\|\||\+=|>|<|\/|\-|,|\()\s?#','$1',$string);//字符前后多余空格
- $string = $this->zip_css($string);
- $string = trim($string," ");
-
- return $string;
- }
- /**
- * script
- * @param string $string
- *
- * @return string
- */
- public function script($string)
- {
- return self::left . $string . self::right;
- }
- /**
- * equal
- * @param string $variable
- * @param string $value
- * @param string $key
- *
- * @return string
- */
- public function equal($variable, $value, $key = '')
- {
- if(strpos($key, '$') !== false)
- {
- $variable .= '['.$key.']';
- }
- elseif($key)
- {
- $variable .= '[\''.$key.'\']';
- }
- if(is_array($value))
- {
- $value = var_export($value, true);
- }
- elseif(is_string($value) && strpos($value, '"') !== false)
- {
- $value = '\'' . $value . '\'';
- }
- return $this->script('$' . $variable . '=' . $value);
- }
- /**
- * data
- * @param string $data
- *
- * @return mixed
- */
- public function data($data)
- {
- if(is_object($data))
- {
- return $data();
- /*
- $this->set('$test', $data);
- return '<{$test}>';
- */
- }
-
- $type = $this->strip($data);
- # include page
- if(strpos($type, '@') !== false)
- {
- return explode('@', $type);
- }
- # include database|model
- elseif(strpos($type, 'http://') === false && strpos($type, '/') !== false && (strpos($type, '.') !== false || strpos($type, '-') !== false))
- {
- $key = $type;
- if(strpos($type, '|') !== false)
- {
- if(strpos($type, '!') !== false)
- {
- $type = str_replace('!', '$', $type . '');
- }
- $temp = explode('|', $type);
- $type = $temp[0];
- parse_str($temp[1], $param);
- // print_r($param);die;
- }
- $callback = 'Maze\\Routing\\Load::get(\'' . $type . '\')';
- if(isset($param))
- {
- $param = var_export($param, true);
- $callback = str_replace(')', ', '.$param.')', $callback);
- if(strpos($callback, '$') !== false)
- {
- $callback = preg_replace('/\'\$(.*?)\'/', '\$$1', $callback);
- }
- }
- $this->push($key, $this->equal('data', $callback, $key));
- return true;
- }
- return $data;
- }
- /**
- * out echo variable
- * @param string $variable
- *
- * @return string
- */
- public function out($variable)
- {
- return $this->script('echo $' . $variable);
- }
- /**
- * each
- * @param string $replace
- * @param string $data
- * @param string $content
- *
- * @return string
- */
- public function each($replace, $data, $content)
- {
- if($replace)
- {
- $strip = $this->strip($replace);
- if($strip && strpos($replace, $strip) !== false)
- {
- $replace = $strip;
- }
- }
- # 增加数组和非数组的判断,如果这里效率不高,以后可以优化,去掉第一行和最后三行即可
- return $this->script('if(is_array($data[\''.$data.'\'])):')
- .$this->equal('t', 'count($data[\''.$data.'\'])-1')
- .$this->equal('i', 0)
- .$this->script('foreach($data[\''.$data.'\'] as $k => $v):')
- //.$this->replace($replace, $this->out('v'), $content)
- .$content
- .$this->equal('i', '$i+1')
- .$this->script('endforeach;')
- .$this->script('else:')
- .$this->replace($replace, $this->out('data[\''.$data.'\']'), $content)
- .$this->script('endif;');
- }
- /**
- * content
- * @param string $content
- *
- * @return string
- */
- public function content($content, $data = false)
- {
- $echo = ' echo ';
- $content = $this->rule($content);
- $content = $this->replace('<{', self::left . $echo, $this->replace('}>', self::right, $content));
- $array = array('function', 'foreach', 'endforeach', 'if', 'endif', 'else', 'for', 'endfor', 'highlight_string', 'echo', 'print_r');
- foreach($array as $k => $v)
- {
- if(strpos($content, self::left . $echo . $v) !== false)
- {
- $content = $this->replace(self::left . $echo . $v, self::left . $v, $content);
- }
- }
- if(strpos($content, '{self}') !== false)
- {
- $content = $this->replace('{self}', '$data[\'' . $data . '\']', $content);
- }
- return $content;
- }
- /**
- * logic
- * @param string $logic
- * @param string $string
- *
- * @return string
- */
- public function logic($logic, $string)
- {
- # 这里暂时这样判断,以后再处理多种逻辑情况的
- if(strpos($logic, '|') !== false)
- {
- list($handle, $logic) = explode('|', $logic);
- if($logic == 'foreach')
- {
- $string = '<{if(isset('.$handle.') && is_array('.$handle.')):foreach('.$handle.' as $ki => $vi):}>' . $string . '<{endforeach;endif;}>';
- }
- elseif($logic == 'if')
- {
- $string = '<{if(isset('.$handle.') && '.$handle.'):}>' . $string . '<{endif;}>';
- }
- else
- {
- $string = '<{'.$handle.'}>' . $string . '<{'.$logic.'}>';
- }
- }
- else
- {
- $string = '<{if(isset('.$logic.') && is_array('.$logic.')):foreach('.$logic.' as $ki => $vi):}>' . $string . '<{endforeach;endif;}>';
- }
-
- return $this->content($string);
- }
- /**
- * replace
- * @param string $replace
- * @param string $value
- * @param string $content
- *
- * @return string
- */
- public function replace($replace, $value, $content)
- {
- if(!$replace)
- {
- return $value;
- }
- $content = str_replace($replace, $value, $content);
- /*
- if(strpos($content, $replace) !== false && strpos($content, $replace) !== false)
- {
- $content = str_replace($replace, $value, $content);
- }
- */
- return $content;
- }
- /**
- * push
- * @param string $value
- *
- * @return string
- */
- public function push($key, $value)
- {
- $this->content[$key] = $value;
- }
- /**
- * set
- * @param string $value
- *
- * @return string
- */
- public function set($key, $value = false)
- {
- if(!$value)
- {
- return $this->push($key, $this->script($this->rule($key)));
- }
- if(is_string($value))
- {
- if(strpos($value, 'Maze') === false)
- {
- $value = var_export($value, true);
- }
- $value = $this->rule($value);
- }
- elseif(is_object($value))
- {
- $value = $value();
- }
-
- $this->push($key, $this->script($this->rule($key) . '=' . $value . ''));
- }
- /**
- * tag
- * @param string $key
- * @param string $data
- *
- * @return string
- */
- public function tag($key, $data = false)
- {
- if($data)
- {
- $result = $data[$key];
- }
- else
- {
- $result = $key;
- }
- return $result;
- }
- /**
- * handle
- * @param string $data
- * @param string $content
- * @param string $expression
- *
- * @return string
- */
- public function handle($data, $content, $expression = '')
- {
- $result = '';
- if(is_array($data))
- {
- $tags = $this->strip($content);
- foreach($data as $k => $v)
- {
- $result .= $this->replace($tags, $v, $content);
- }
- }
- else
- {
- $index = false;
- if(is_string($data) && strpos($data, '#') > 0 && strpos($data, '"') === false)
- {
- list($data, $index) = explode('#', $data);
- }
- $method = $this->data($data);
- if($method === true)
- {
- $result = $this->complex($data, $content, $index, $expression);
- }
- elseif(is_array($method))
- {
- $result = $this->load($method[1], $method[0]);
- }
- elseif($method && (is_string($method) || is_numeric($method)))
- {
- $method = $this->content($method);
- $result = $this->replace($content, $method, $content);
- if($result == $content)
- {
- //$result = $this->replace($this->strip($content), $method, $content);
- }
- }
- elseif(!$result && (is_string($data) || is_numeric($data)))
- {
- $data = $this->content($data);
- $result = $this->replace($this->strip($content), $data, $content);
- }
- else
- {
- $result = $content;
- }
- }
- return $result;
- }
- /**
- * complex
- * @param string $data
- * @param string $content
- * @param string $index
- * @param string $expression
- *
- * @return string
- */
- public function complex($data, $content, $index = false, $expression = '')
- {
- if($index)
- {
- $strip = $this->strip($content);
- $result = $this->out('data[\''.$data.'\'][\''.$index.'\']');
- if($strip == $content)
- {
- $result = $this->replace($strip, $result, $content);
- }
- }
- else
- {
- if($expression)
- {
- $content = $this->replace($expression, $this->out('v'), $content);
- }
- $result = $this->each($content, $data, $this->content($content));
- }
-
- return $result;
- }
- /**
- * rule
- * @param string $content
- *
- * @return string
- */
- public function rule($content)
- {
- if(strpos($content, 'request.') !== false)
- {
- $content = preg_replace('/request\.([a-zA-Z0-9]+)/', 'Maze::input(\'$1\')', $content);
- }
- if(strpos($content, '$') !== false && strpos($content, '.') !== false)
- {
- $rule = '\$([a-zA-Z0-9]+)\.([a-zA-Z0-9._]+)';
- $content = preg_replace_callback('/' . $rule . '/i', array($this, 'rule_val'), $content);
- }
- if(strpos($content, '"+') !== false)
- {
- $content = str_replace(array('"+','+"'), array('".', '."'), $content);
- }
- if(strpos($content, '++') !== false)
- {
- $content = str_replace('++', '.', $content);
- }
- if(strpos($content, '<{$') !== false)
- {
- //$content = str_replace('<{$', '<{echo $', $content);
- }
- return $content;
- }
- /**
- * rule_val
- * @param array $result
- *
- * @return string
- */
- public function rule_val($result)
- {
- if(isset($result[2]) && $result[2])
- {
- $result[2] = '$' . $result[1] . '' . preg_replace('/\.([a-zA-Z0-9_]+)/', '[\'$1\']', '.' . $result[2]);
- return $result[2];
- }
- return $result[0];
- }
- /**
- * strip
- * @param string $content
- *
- * @return string
- */
- public function strip($content)
- {
- if(is_string($content))
- {
- return strip_tags($content);
- }
- return $content;
- }
- }
|