123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- <?php
- /**
- * CPradoViewRenderer class file.
- *
- * @author Steve Heyns http://customgothic.com/
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.yiiframework.com/
- * @copyright 2008-2013 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- /**
- * CPradoViewRenderer implements a view renderer that allows users to use a template syntax similar to PRADO templates.
- *
- * To use CPradoViewRenderer, configure it as an application component named "viewRenderer" in the application configuration:
- * <pre>
- * array(
- * 'components'=>array(
- * ......
- * 'viewRenderer'=>array(
- * 'class'=>'CPradoViewRenderer',
- * ),
- * ),
- * )
- * </pre>
- *
- * CPradoViewRenderer allows you to write view files with the following syntax:
- * <pre>
- * // PHP tags:
- * <%= expression %>
- * // <?php echo expression ?>
- * <% statement %>
- * // <?php statement ?></li>
- *
- * // component tags:
- * <com:WigetClass name1="value1" name2='value2' name3={value3} >
- * // <?php $this->beginWidget('WigetClass',
- * // array('name1'=>"value1", 'name2'=>'value2', 'name3'=>value3)); ?>
- * </com:WigetClass >
- * // <?php $this->endWidget('WigetClass'); ?>
- * <com:WigetClass name1="value1" name2='value2' name3={value3} />
- * // <?php $this->widget('WigetClass',
- * // array('name1'=>"value1", 'name2'=>'value2', 'name3'=>value3)); ?>
- *
- * // cache tags:
- * <cache:fragmentID name1="value1" name2='value2' name3={value3} >
- * // <?php if($this->beginCache('fragmentID',
- * // array('name1'=>"value1", 'name2'=>'value2', 'name3'=>value3))): ?>
- * </cache:fragmentID >
- * // <?php $this->endCache('fragmentID'); endif; ?>
- *
- * // clip tags:
- * <clip:clipID >
- * // <?php $this->beginClip('clipID'); ?>
- * </clip:clipID >
- * // <?php $this->endClip('clipID'); ?>
- *
- * // comment tags:
- * <!--- comments --->
- * // the whole tag will be stripped off
- * </pre>
- *
- * @author Steve Heyns http://customgothic.com/
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @package system.web.renderers
- * @since 1.0
- */
- class CPradoViewRenderer extends CViewRenderer
- {
- private $_input;
- private $_output;
- private $_sourceFile;
- /**
- * Parses the source view file and saves the results as another file.
- * This method is required by the parent class.
- * @param string $sourceFile the source view file path
- * @param string $viewFile the resulting view file path
- */
- protected function generateViewFile($sourceFile,$viewFile)
- {
- static $regexRules=array(
- '<%=?\s*(.*?)\s*%>', // PHP statements or expressions
- '<\/?(com|cache|clip):([\w\.]+)\s*((?:\s*\w+\s*=\s*\'.*?(?<!\\\\)\'|\s*\w+\s*=\s*".*?(?<!\\\\)"|\s*\w+\s*=\s*\{.*?\})*)\s*\/?>', // component tags
- '<!---.*?--->', // template comments
- );
- $this->_sourceFile=$sourceFile;
- $this->_input=file_get_contents($sourceFile);
- $n=preg_match_all('/'.implode('|',$regexRules).'/msS',$this->_input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
- $textStart=0;
- $this->_output="<?php /* source file: $sourceFile */ ?>\n";
- for($i=0;$i<$n;++$i)
- {
- $match=&$matches[$i];
- $str=$match[0][0];
- $matchStart=$match[0][1];
- $matchEnd=$matchStart+strlen($str)-1;
- if($matchStart>$textStart)
- $this->_output.=substr($this->_input,$textStart,$matchStart-$textStart);
- $textStart=$matchEnd+1;
- if(strpos($str,'<com:')===0) // opening component tag
- {
- $type=$match[3][0];
- if($str[strlen($str)-2]!=='/') // open tag
- $this->_output.=$this->processBeginWidget($type,$match[4][0],$match[2][1]);
- else
- $this->_output.=$this->processWidget($type,$match[4][0],$match[2][1]);
- }
- elseif(strpos($str,'</com:')===0) // closing component tag
- $this->_output.=$this->processEndWidget($match[3][0],$match[2][1]);
- elseif(strpos($str,'<cache:')===0) // opening cache tag
- {
- $id=$match[3][0];
- if($str[strlen($str)-2]!=='/') // open tag
- $this->_output.=$this->processBeginCache($id,$match[4][0],$match[2][1]);
- else
- $this->_output.=$this->processCache($id,$match[4][0],$match[2][1]);
- }
- elseif(strpos($str,'</cache:')===0) // closing cache tag
- $this->_output.=$this->processEndCache($match[3][0],$match[2][1]);
- elseif(strpos($str,'<clip:')===0) // opening clip tag
- {
- $id=$match[3][0];
- if($str[strlen($str)-2]!=='/') // open tag
- $this->_output.=$this->processBeginClip($id,$match[4][0],$match[2][1]);
- else
- $this->_output.=$this->processClip($id,$match[4][0],$match[2][1]);
- }
- elseif(strpos($str,'</clip:')===0) // closing clip tag
- $this->_output.=$this->processEndClip($match[3][0],$match[2][1]);
- elseif(strpos($str,'<%=')===0) // expression
- $this->_output.=$this->processExpression($match[1][0],$match[1][1]);
- elseif(strpos($str,'<%')===0) // statement
- $this->_output.=$this->processStatement($match[1][0],$match[1][1]);
- }
- if($textStart<strlen($this->_input))
- $this->_output.=substr($this->_input,$textStart);
- file_put_contents($viewFile,$this->_output);
- }
- /*
- * @param string $type type
- * @param string $attributes attributes
- * @param string $offset offset
- */
- private function processWidget($type,$attributes,$offset)
- {
- $attrs=$this->processAttributes($attributes);
- if(empty($attrs))
- return $this->generatePhpCode("\$this->widget('$type');",$offset);
- else
- return $this->generatePhpCode("\$this->widget('$type', array($attrs));",$offset);
- }
- /*
- * @param string $type type
- * @param string $attributes attributes
- * @param string $offset offset
- */
- private function processBeginWidget($type,$attributes,$offset)
- {
- $attrs=$this->processAttributes($attributes);
- if(empty($attrs))
- return $this->generatePhpCode("\$this->beginWidget('$type');",$offset);
- else
- return $this->generatePhpCode("\$this->beginWidget('$type', array($attrs));",$offset);
- }
- /*
- * @param string $type type
- * @param string $offset offset
- */
- private function processEndWidget($type,$offset)
- {
- return $this->generatePhpCode("\$this->endWidget('$type');",$offset);
- }
- /*
- * @param string $id id
- * @param string $attributes attributes
- * @param string $offset offset
- */
- private function processCache($id,$attributes,$offset)
- {
- return $this->processBeginCache($id,$attributes,$offset) . $this->processEndCache($id,$offset);
- }
- /*
- * @param string $id id
- * @param string $attributes attributes
- * @param string $offset offset
- */
- private function processBeginCache($id,$attributes,$offset)
- {
- $attrs=$this->processAttributes($attributes);
- if(empty($attrs))
- return $this->generatePhpCode("if(\$this->beginCache('$id')):",$offset);
- else
- return $this->generatePhpCode("if(\$this->beginCache('$id', array($attrs))):",$offset);
- }
- /*
- * @param string $id id
- * @param string $offset offset
- */
- private function processEndCache($id,$offset)
- {
- return $this->generatePhpCode("\$this->endCache('$id'); endif;",$offset);
- }
- /*
- * @param string $id id
- * @param string $attributes attributes
- * @param string $offset offset
- */
- private function processClip($id,$attributes,$offset)
- {
- return $this->processBeginClip($id,$attributes,$offset) . $this->processEndClip($id,$offset);
- }
- /*
- * @param string $id id
- * @param string $attributes attributes
- * @param string $offset offset
- */
- private function processBeginClip($id,$attributes,$offset)
- {
- $attrs=$this->processAttributes($attributes);
- if(empty($attrs))
- return $this->generatePhpCode("\$this->beginClip('$id');",$offset);
- else
- return $this->generatePhpCode("\$this->beginClip('$id', array($attrs));",$offset);
- }
- /*
- * @param string $id id
- * @param string $offset offset
- */
- private function processEndClip($id,$offset)
- {
- return $this->generatePhpCode("\$this->endClip('$id');",$offset);
- }
- /*
- * @param string $expression expression
- * @param string $offset offset
- */
- private function processExpression($expression,$offset)
- {
- return $this->generatePhpCode('echo '.$expression,$offset);
- }
- /*
- * @param string $statement statement
- * @param string $offset offset
- */
- private function processStatement($statement,$offset)
- {
- return $this->generatePhpCode($statement,$offset);
- }
- /*
- * @param string $code code
- * @param string $offset offset
- */
- private function generatePhpCode($code,$offset)
- {
- $line=$this->getLineNumber($offset);
- $code=str_replace('__FILE__',var_export($this->_sourceFile,true),$code);
- return "<?php /* line $line */ $code ?>";
- }
- /*
- * @param string $str str
- */
- private function processAttributes($str)
- {
- static $pattern='/(\w+)\s*=\s*(\'.*?(?<!\\\\)\'|".*?(?<!\\\\)"|\{.*?\})/msS';
- $attributes=array();
- $n=preg_match_all($pattern,$str,$matches,PREG_SET_ORDER);
- for($i=0;$i<$n;++$i)
- {
- $match=&$matches[$i];
- $name=$match[1];
- $value=$match[2];
- if($value[0]==='{')
- $attributes[]="'$name'=>".str_replace('__FILE__',$this->_sourceFile,substr($value,1,-1));
- else
- $attributes[]="'$name'=>$value";
- }
- return implode(', ',$attributes);
- }
- /*
- * @param string $offset offset
- */
- private function getLineNumber($offset)
- {
- return count(explode("\n",substr($this->_input,0,$offset)));
- }
- }
|