summaryrefslogtreecommitdiff
path: root/framework/web/renderers
diff options
context:
space:
mode:
Diffstat (limited to 'framework/web/renderers')
-rw-r--r--framework/web/renderers/CPradoViewRenderer.php305
-rw-r--r--framework/web/renderers/CViewRenderer.php97
2 files changed, 402 insertions, 0 deletions
diff --git a/framework/web/renderers/CPradoViewRenderer.php b/framework/web/renderers/CPradoViewRenderer.php
new file mode 100644
index 0000000..343a78b
--- /dev/null
+++ b/framework/web/renderers/CPradoViewRenderer.php
@@ -0,0 +1,305 @@
+<?php
+/**
+ * CPradoViewRenderer class file.
+ *
+ * @author Steve Heyns http://customgothic.com/
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008-2011 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>
+ * @version $Id: CPradoViewRenderer.php 2799 2011-01-01 19:31:13Z qiang.xue $
+ * @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]);
+ }
+ else if(strpos($str,'</com:')===0) // closing component tag
+ $this->_output.=$this->processEndWidget($match[3][0],$match[2][1]);
+ else if(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]);
+ }
+ else if(strpos($str,'</cache:')===0) // closing cache tag
+ $this->_output.=$this->processEndCache($match[3][0],$match[2][1]);
+ else if(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]);
+ }
+ else if(strpos($str,'</clip:')===0) // closing clip tag
+ $this->_output.=$this->processEndClip($match[3][0],$match[2][1]);
+ else if(strpos($str,'<%=')===0) // expression
+ $this->_output.=$this->processExpression($match[1][0],$match[1][1]);
+ else if(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)));
+ }
+}
diff --git a/framework/web/renderers/CViewRenderer.php b/framework/web/renderers/CViewRenderer.php
new file mode 100644
index 0000000..093c3bb
--- /dev/null
+++ b/framework/web/renderers/CViewRenderer.php
@@ -0,0 +1,97 @@
+<?php
+/**
+ * CViewRenderer class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright &copy; 2008-2011 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+/**
+ * CViewRenderer is the base class for view renderer classes.
+ *
+ * A view renderer is an application component that renders views written
+ * in a customized syntax.
+ *
+ * Once installing a view renderer as a 'viewRenderer' application component,
+ * the normal view rendering process will be intercepted by the renderer.
+ * The renderer will first parse the source view file and then render the
+ * the resulting view file.
+ *
+ * Parsing results are saved as temporary files that may be stored
+ * under the application runtime directory or together with the source view file.
+ *
+ * @author Steve Heyns http://customgothic.com/
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id: CViewRenderer.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @package system.web.renderers
+ * @since 1.0
+ */
+abstract class CViewRenderer extends CApplicationComponent implements IViewRenderer
+{
+ /**
+ * @var boolean whether to store the parsing results in the application's
+ * runtime directory. Defaults to true. If false, the parsing results will
+ * be saved as files under the same directory as the source view files and the
+ * file names will be the source file names appended with letter 'c'.
+ */
+ public $useRuntimePath=true;
+ /**
+ * @var integer the chmod permission for temporary directories and files
+ * generated during parsing. Defaults to 0755 (owner rwx, group rx and others rx).
+ */
+ public $filePermission=0755;
+ /**
+ * @var string the extension name of the view file. Defaults to '.php'.
+ */
+ public $fileExtension='.php';
+
+ /**
+ * Parses the source view file and saves the results as another file.
+ * @param string $sourceFile the source view file path
+ * @param string $viewFile the resulting view file path
+ */
+ abstract protected function generateViewFile($sourceFile,$viewFile);
+
+ /**
+ * Renders a view file.
+ * This method is required by {@link IViewRenderer}.
+ * @param CBaseController $context the controller or widget who is rendering the view file.
+ * @param string $sourceFile the view file path
+ * @param mixed $data the data to be passed to the view
+ * @param boolean $return whether the rendering result should be returned
+ * @return mixed the rendering result, or null if the rendering result is not needed.
+ */
+ public function renderFile($context,$sourceFile,$data,$return)
+ {
+ if(!is_file($sourceFile) || ($file=realpath($sourceFile))===false)
+ throw new CException(Yii::t('yii','View file "{file}" does not exist.',array('{file}'=>$sourceFile)));
+ $viewFile=$this->getViewFile($sourceFile);
+ if(@filemtime($sourceFile)>@filemtime($viewFile))
+ {
+ $this->generateViewFile($sourceFile,$viewFile);
+ @chmod($viewFile,$this->filePermission);
+ }
+ return $context->renderInternal($viewFile,$data,$return);
+ }
+
+ /**
+ * Generates the resulting view file path.
+ * @param string $file source view file path
+ * @return string resulting view file path
+ */
+ protected function getViewFile($file)
+ {
+ if($this->useRuntimePath)
+ {
+ $crc=sprintf('%x', crc32(get_class($this).Yii::getVersion().dirname($file)));
+ $viewFile=Yii::app()->getRuntimePath().DIRECTORY_SEPARATOR.'views'.DIRECTORY_SEPARATOR.$crc.DIRECTORY_SEPARATOR.basename($file);
+ if(!is_file($viewFile))
+ @mkdir(dirname($viewFile),$this->filePermission,true);
+ return $viewFile;
+ }
+ else
+ return $file.'c';
+ }
+}