1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10:
11:
12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67:
68: class CPradoViewRenderer extends CViewRenderer
69: {
70: private $_input;
71: private $_output;
72: private $_sourceFile;
73:
74: 75: 76: 77: 78: 79:
80: protected function generateViewFile($sourceFile,$viewFile)
81: {
82: static $regexRules=array(
83: '<%=?\s*(.*?)\s*%>',
84: '<\/?(com|cache|clip):([\w\.]+)\s*((?:\s*\w+\s*=\s*\'.*?(?<!\\\\)\'|\s*\w+\s*=\s*".*?(?<!\\\\)"|\s*\w+\s*=\s*\{.*?\})*)\s*\/?>',
85: '<!---.*?--->',
86: );
87: $this->_sourceFile=$sourceFile;
88: $this->_input=file_get_contents($sourceFile);
89: $n=preg_match_all('/'.implode('|',$regexRules).'/msS',$this->_input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
90: $textStart=0;
91: $this->_output="<?php /* source file: $sourceFile */ ?>\n";
92: for($i=0;$i<$n;++$i)
93: {
94: $match=&$matches[$i];
95: $str=$match[0][0];
96: $matchStart=$match[0][1];
97: $matchEnd=$matchStart+strlen($str)-1;
98:
99: if($matchStart>$textStart)
100: $this->_output.=substr($this->_input,$textStart,$matchStart-$textStart);
101: $textStart=$matchEnd+1;
102:
103: if(strpos($str,'<com:')===0)
104: {
105: $type=$match[3][0];
106: if($str[strlen($str)-2]!=='/')
107: $this->_output.=$this->processBeginWidget($type,$match[4][0],$match[2][1]);
108: else
109: $this->_output.=$this->processWidget($type,$match[4][0],$match[2][1]);
110: }
111: elseif(strpos($str,'</com:')===0)
112: $this->_output.=$this->processEndWidget($match[3][0],$match[2][1]);
113: elseif(strpos($str,'<cache:')===0)
114: {
115: $id=$match[3][0];
116: if($str[strlen($str)-2]!=='/')
117: $this->_output.=$this->processBeginCache($id,$match[4][0],$match[2][1]);
118: else
119: $this->_output.=$this->processCache($id,$match[4][0],$match[2][1]);
120: }
121: elseif(strpos($str,'</cache:')===0)
122: $this->_output.=$this->processEndCache($match[3][0],$match[2][1]);
123: elseif(strpos($str,'<clip:')===0)
124: {
125: $id=$match[3][0];
126: if($str[strlen($str)-2]!=='/')
127: $this->_output.=$this->processBeginClip($id,$match[4][0],$match[2][1]);
128: else
129: $this->_output.=$this->processClip($id,$match[4][0],$match[2][1]);
130: }
131: elseif(strpos($str,'</clip:')===0)
132: $this->_output.=$this->processEndClip($match[3][0],$match[2][1]);
133: elseif(strpos($str,'<%=')===0)
134: $this->_output.=$this->processExpression($match[1][0],$match[1][1]);
135: elseif(strpos($str,'<%')===0)
136: $this->_output.=$this->processStatement($match[1][0],$match[1][1]);
137: }
138: if($textStart<strlen($this->_input))
139: $this->_output.=substr($this->_input,$textStart);
140:
141: file_put_contents($viewFile,$this->_output);
142: }
143:
144: 145: 146: 147: 148:
149: private function processWidget($type,$attributes,$offset)
150: {
151: $attrs=$this->processAttributes($attributes);
152: if(empty($attrs))
153: return $this->generatePhpCode("\$this->widget('$type');",$offset);
154: else
155: return $this->generatePhpCode("\$this->widget('$type', array($attrs));",$offset);
156: }
157:
158: 159: 160: 161: 162:
163: private function processBeginWidget($type,$attributes,$offset)
164: {
165: $attrs=$this->processAttributes($attributes);
166: if(empty($attrs))
167: return $this->generatePhpCode("\$this->beginWidget('$type');",$offset);
168: else
169: return $this->generatePhpCode("\$this->beginWidget('$type', array($attrs));",$offset);
170: }
171:
172: 173: 174: 175:
176: private function processEndWidget($type,$offset)
177: {
178: return $this->generatePhpCode("\$this->endWidget('$type');",$offset);
179: }
180:
181: 182: 183: 184: 185:
186: private function processCache($id,$attributes,$offset)
187: {
188: return $this->processBeginCache($id,$attributes,$offset) . $this->processEndCache($id,$offset);
189: }
190:
191: 192: 193: 194: 195:
196: private function processBeginCache($id,$attributes,$offset)
197: {
198: $attrs=$this->processAttributes($attributes);
199: if(empty($attrs))
200: return $this->generatePhpCode("if(\$this->beginCache('$id')):",$offset);
201: else
202: return $this->generatePhpCode("if(\$this->beginCache('$id', array($attrs))):",$offset);
203: }
204:
205: 206: 207: 208:
209: private function processEndCache($id,$offset)
210: {
211: return $this->generatePhpCode("\$this->endCache('$id'); endif;",$offset);
212: }
213:
214: 215: 216: 217: 218:
219: private function processClip($id,$attributes,$offset)
220: {
221: return $this->processBeginClip($id,$attributes,$offset) . $this->processEndClip($id,$offset);
222: }
223:
224: 225: 226: 227: 228:
229: private function processBeginClip($id,$attributes,$offset)
230: {
231: $attrs=$this->processAttributes($attributes);
232: if(empty($attrs))
233: return $this->generatePhpCode("\$this->beginClip('$id');",$offset);
234: else
235: return $this->generatePhpCode("\$this->beginClip('$id', array($attrs));",$offset);
236: }
237:
238: 239: 240: 241:
242: private function processEndClip($id,$offset)
243: {
244: return $this->generatePhpCode("\$this->endClip('$id');",$offset);
245: }
246:
247: 248: 249: 250:
251: private function processExpression($expression,$offset)
252: {
253: return $this->generatePhpCode('echo '.$expression,$offset);
254: }
255:
256: 257: 258: 259:
260: private function processStatement($statement,$offset)
261: {
262: return $this->generatePhpCode($statement,$offset);
263: }
264:
265: 266: 267: 268:
269: private function generatePhpCode($code,$offset)
270: {
271: $line=$this->getLineNumber($offset);
272: $code=str_replace('__FILE__',var_export($this->_sourceFile,true),$code);
273: return "<?php /* line $line */ $code ?>";
274: }
275:
276: 277: 278:
279: private function processAttributes($str)
280: {
281: static $pattern='/(\w+)\s*=\s*(\'.*?(?<!\\\\)\'|".*?(?<!\\\\)"|\{.*?\})/msS';
282: $attributes=array();
283: $n=preg_match_all($pattern,$str,$matches,PREG_SET_ORDER);
284: for($i=0;$i<$n;++$i)
285: {
286: $match=&$matches[$i];
287: $name=$match[1];
288: $value=$match[2];
289: if($value[0]==='{')
290: $attributes[]="'$name'=>".str_replace('__FILE__',$this->_sourceFile,substr($value,1,-1));
291: else
292: $attributes[]="'$name'=>$value";
293: }
294: return implode(', ',$attributes);
295: }
296:
297: 298: 299:
300: private function getLineNumber($offset)
301: {
302: return count(explode("\n",substr($this->_input,0,$offset)));
303: }
304: }
305: