| [ Index ] |
PHP Cross Reference of Joomla 1.5.26 DE |
[Summary view] [Print] [Text view]
1 <?PHP 2 /** 3 * Compiler for patTemplate 4 * 5 * $Id: Compiler.php 10381 2008-06-01 03:35:53Z pasamio $ 6 * 7 * WARNING: This is still experimental! 8 * 9 * @package patTemplate 10 * @subpackage Compiler 11 * @author Stephan Schmidt <schst@php.net> 12 */ 13 14 // Check to ensure this file is within the rest of the framework 15 defined('JPATH_BASE') or die(); 16 17 /** 18 * Compiler for patTemplate 19 * 20 * $Id: Compiler.php 10381 2008-06-01 03:35:53Z pasamio $ 21 * 22 * WARNING: This is still experimental! 23 * 24 * @package patTemplate 25 * @subpackage Compiler 26 * @author Stephan Schmidt <schst@php.net> 27 * 28 * @todo implement all template types 29 * @todo implement variable modifiers 30 * @todo implement getParsedTemplate 31 * @todo check for existing compiled template 32 */ 33 class patTemplate_Compiler extends patTemplate 34 { 35 /** 36 * list of all templates that already have been compiled 37 * 38 * @access private 39 * @var array() 40 */ 41 var $_compiledTemplates = array(); 42 43 /** 44 * file pointer to the compiled template 45 * 46 * @access private 47 * @var resource 48 */ 49 var $_fp; 50 51 /** 52 * constructor 53 * 54 * Creates a new patTemplate Compiler 55 * 56 * @access public 57 * @param string type of the templates, either 'html' or 'tex' 58 */ 59 function patTemplate_Compiler( $type = 'html' ) 60 { 61 $GLOBALS['patTemplate_Compiler'] = &$this; 62 patTemplate::patTemplate( $type ); 63 } 64 65 /** 66 * compile the currently loaded templates 67 * 68 * @access public 69 * @param string name of the input (filename, shm segment, etc.) 70 */ 71 function compile( $compileName = null ) 72 { 73 $this->_varRegexp = '/'.$this->_startTag.'([^a-z:]+)'.$this->_endTag.'/U'; 74 $this->_depRegexp = '/'.$this->_startTag.'TMPL:([^a-z:]+)'.$this->_endTag.'/U'; 75 76 $compileFolder = $this->getOption( 'compileFolder' ); 77 $compileFile = sprintf( '%s/%s', $compileFolder, $compileName ); 78 79 $this->_fp = fopen( $compileFile, 'w' ); 80 $this->_addToCode( '<?PHP' ); 81 $this->_addToCode( '/**' ); 82 $this->_addToCode( ' * compiled patTemplate file' ); 83 $this->_addToCode( ' *' ); 84 $this->_addToCode( ' * compiled on '. date( 'Y-m-d H:i:s' ) ); 85 $this->_addToCode( ' */' ); 86 $this->_addToCode( 'class compiledTemplate {' ); 87 88 foreach( $this->_templates as $template => $spec ) 89 { 90 $this->compileTemplate( $template ); 91 } 92 93 $this->_addToCode( '}' ); 94 $this->_addToCode( '?>' ); 95 fclose( $this->_fp ); 96 97 include_once $compileFile; 98 return true; 99 } 100 101 /** 102 * compile a template 103 * 104 * @access public 105 * @param string name of the template 106 */ 107 function compileTemplate( $template ) 108 { 109 $name = strtolower( $template ); 110 111 if( !isset( $this->_templates[$template] ) ) 112 { 113 return patErrorManager::raiseWarning( 114 PATTEMPLATE_WARNING_NO_TEMPLATE, 115 "Template '$name' does not exist." 116 ); 117 } 118 119 120 /** 121 * check, if the template has been loaded 122 * and load it if necessary. 123 */ 124 if( $this->_templates[$template]['loaded'] !== true ) 125 { 126 if( $this->_templates[$template]['attributes']['parse'] == 'on' ) 127 { 128 $result = $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template ); 129 } 130 else 131 { 132 $result = $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], $template ); 133 } 134 if( patErrorManager::isError( $result ) ) 135 { 136 return $result; 137 } 138 } 139 140 $this->_addToCode( '' ); 141 $this->_addToCode( '/**' ); 142 $this->_addToCode( ' * Compiled version of '.$template ); 143 $this->_addToCode( ' *' ); 144 $this->_addToCode( ' * Template type is '.$this->_templates[$template]['attributes']['type'] ); 145 $this->_addToCode( ' */' ); 146 147 148 /** 149 * start the output 150 */ 151 $this->_addToCode( 'function '.$template.'()' ); 152 $this->_addToCode( '{' ); 153 $this->_addToCode( '$this->_prepareCompiledTemplate( "'.$template.'" );', 1 ); 154 $this->_addToCode( '$this->prepareTemplate( "'.$template.'" );', 1 ); 155 156 /** 157 * attributes 158 */ 159 $this->_addToCode( '$this->_templates["'.$template.'"]["attributes"] = unserialize( \''.serialize($this->_templates[$template]['attributes']).'\' );', 1, 'Read the attributes' ); 160 161 /** 162 * copyVars 163 */ 164 $this->_addToCode( '$this->_templates["'.$template.'"]["copyVars"] = unserialize( \''.serialize($this->_templates[$template]['copyVars']).'\' );', 1, 'Read the copyVars' ); 165 166 /** 167 * check visibility 168 */ 169 $this->_addToCode( 'if( $this->_templates["'.$template.'"]["attributes"]["visibility"] != "hidden" ) {', 1, 'Check, whether template is hidden' ); 170 171 /** 172 * autoloop the template 173 */ 174 $this->_addToCode( '$this->_templates["'.$template.'"]["iteration"] = 0;', 2, 'Reset the iteration' ); 175 176 $this->_addToCode( '$loop = count( $this->_vars["'.$template.'"]["rows"] );', 2, 'Get the amount of loops' ); 177 $this->_addToCode( '$loop = max( $loop, 1 );', 2 ); 178 $this->_addToCode( '$this->_templates["'.$template.'"]["loop"] = $loop;', 2 ); 179 180 $this->_addToCode( 'for( $i = 0; $i < $loop; $i++ ) {', 2, 'Traverse all variables.' ); 181 182 /** 183 * fetch the variables 184 */ 185 $this->_addToCode( 'unset( $this->_templates["'.$template.'"]["vars"] );', 3 ); 186 $this->_addToCode( '$this->_fetchVariables("'.$template.'");', 3 ); 187 188 /** 189 * different templates have to be compiled differently 190 */ 191 switch( $this->_templates[$template]['attributes']['type'] ) 192 { 193 /** 194 * modulo template 195 */ 196 case 'modulo': 197 $this->_compileModuloTemplate( $template ); 198 break; 199 200 /** 201 * simple condition template 202 */ 203 case 'simplecondition': 204 $this->_compileSimpleConditionTemplate( $template ); 205 break; 206 207 /** 208 * condition template 209 */ 210 case 'condition': 211 $this->_compileConditionTemplate( $template ); 212 break; 213 214 /** 215 * standard template 216 */ 217 default: 218 $this->_compileStandardTemplate( $template ); 219 break; 220 } 221 $this->_addToCode( '$this->_templates["'.$template.'"]["iteration"]++;', 3 ); 222 223 $this->_addToCode( '}', 2 ); 224 225 $this->_addToCode( '}', 1 ); 226 $this->_addToCode( '}' ); 227 228 /** 229 * remember this template 230 */ 231 array_push( $this->_compiledTemplates, $template ); 232 } 233 234 /** 235 * compile a standard template 236 * 237 * @access private 238 * @param string name of the template 239 */ 240 function _compileStandardTemplate( $template ) 241 { 242 $content = $this->_templateToPHP( $this->_templates[$template]['content'], $template ); 243 $this->_addToCode( $content ); 244 return true; 245 } 246 247 /** 248 * compile a modulo template 249 * 250 * A modulo template will be compiled into a switch/case 251 * statement. 252 * 253 * @access private 254 * @param string name of the template 255 * @todo check special conditions (__first, __last, __default) 256 */ 257 function _compileModuloTemplate( $template ) 258 { 259 $this->_compileBuiltinConditions( $template ); 260 261 262 $this->_addToCode( 'if( !$_displayed ) {', 3, 'Builtin condition has been displayed?' ); 263 264 /** 265 * build switch statement 266 */ 267 $this->_addToCode( 'switch( ( $this->_templates["'.$template.'"]["iteration"] + 1 ) % '.$this->_templates[$template]['attributes']['modulo'].' ) {', 4 ); 268 269 foreach( $this->_templates[$template]['subtemplates'] as $condition => $spec ) 270 { 271 $this->_addToCode( 'case "'.$condition.'":', 5 ); 272 $content = $this->_templateToPHP( $spec['data'], $template ); 273 $this->_addToCode( $content ); 274 $this->_addToCode( 'break;', 6 ); 275 } 276 $this->_addToCode( '}', 4 ); 277 $this->_addToCode( '}', 3 ); 278 return true; 279 } 280 281 /** 282 * compile a simpleCondition template 283 * 284 * A simpleCondition template will be compiled into an 'if' 285 * statement. 286 * 287 * @access private 288 * @param string name of the template 289 */ 290 function _compileSimpleConditionTemplate( $template ) 291 { 292 $conditions = array(); 293 foreach( $this->_templates[$template]['attributes']['requiredvars'] as $var ) 294 { 295 array_push( $conditions, 'isset( $this->_templates["'.$template.'"]["vars"]["'.$var.'"] )' ); 296 } 297 298 /** 299 * build switch statement 300 */ 301 $this->_addToCode( 'if( '.implode( ' && ', $conditions ).' ) {', 3, 'Check for required variables' ); 302 303 $content = $this->_templateToPHP( $this->_templates[$template]['content'], $template ); 304 $this->_addToCode( $content ); 305 $this->_addToCode( '}', 3 ); 306 return true; 307 } 308 309 /** 310 * compile a condition template 311 * 312 * A condition template will be compiled into an 'switch/case' 313 * statement. 314 * 315 * @access private 316 * @param string name of the template 317 */ 318 function _compileConditionTemplate( $template ) 319 { 320 /** 321 * __first, __last 322 */ 323 $this->_compileBuiltinConditions( $template ); 324 325 $this->_addToCode( 'if( !$_displayed ) {', 3, 'Builtin condition has been displayed?' ); 326 327 /** 328 * build switch statement 329 */ 330 $this->_addToCode( 'switch( $this->_templates["'.$template.'"]["vars"]["'.$this->_templates[$template]["attributes"]["conditionvar"].'"] ) {', 4 ); 331 332 foreach( $this->_templates[$template]['subtemplates'] as $condition => $spec ) 333 { 334 if( $condition == '__default' ) 335 { 336 $this->_addToCode( 'default:', 5 ); 337 } 338 else 339 { 340 $this->_addToCode( 'case "'.$condition.'":', 5 ); 341 } 342 $content = $this->_templateToPHP( $spec['data'], $template ); 343 $this->_addToCode( $content ); 344 $this->_addToCode( 'break;', 6 ); 345 } 346 $this->_addToCode( '}', 4 ); 347 $this->_addToCode( '}', 3 ); 348 return true; 349 } 350 351 /** 352 * compile built-in conditions 353 * 354 * This will create the neccessary PHP code for: 355 * - __first 356 * - __last 357 * 358 * @access private 359 * @param string template name 360 */ 361 function _compileBuiltinConditions( $template ) 362 { 363 $this->_addToCode( '$_displayed = false;', 3 ); 364 365 if( isset( $this->_templates[$template]['subtemplates']['__first'] ) ) 366 { 367 $this->_addToCode( 'if( $this->_templates["'.$template.'"]["iteration"] == 0 ) {', 3, 'Check for first entry' ); 368 $content = $this->_templateToPHP( $this->_templates[$template]['subtemplates']['__first']['data'], $template ); 369 $this->_addToCode( $content ); 370 $this->_addToCode( '$_displayed = true;', 4 ); 371 $this->_addToCode( '}', 3 ); 372 } 373 374 if( isset( $this->_templates[$template]['subtemplates']['__last'] ) ) 375 { 376 $this->_addToCode( 'if( $this->_templates["'.$template.'"]["iteration"] == ($this->_templates["'.$template.'"]["loop"]-1) ) {', 3, 'Check for last entry' ); 377 $content = $this->_templateToPHP( $this->_templates[$template]['subtemplates']['__last']['data'], $template ); 378 $this->_addToCode( $content ); 379 $this->_addToCode( '$_displayed = true;', 4 ); 380 $this->_addToCode( '}', 3 ); 381 } 382 } 383 384 /** 385 * build PHP code from a template 386 * 387 * This will replace the variables in a template with 388 * PHP Code. 389 * 390 * @access private 391 * @param string template content 392 * @param string name of the template 393 * @return string PHP code 394 */ 395 function _templateToPHP( $content, $template ) 396 { 397 $content = preg_replace( $this->_varRegexp, '<?PHP echo $this->_getVar( "'.$template.'", "$1"); ?>', $content ); 398 $content = preg_replace( $this->_depRegexp, '<?PHP compiledTemplate::$1(); ?>', $content ); 399 $content = '?>'.$content.'<?PHP'; 400 return $content; 401 } 402 403 404 /** 405 * display the compiled template 406 * 407 * This is a replacement for patTemplate::displayParsedTemplate. 408 * 409 * @access public 410 * @param string name of the template to display 411 */ 412 function displayParsedTemplate( $name = null ) 413 { 414 if( is_null( $name ) ) 415 $name = $this->_root; 416 417 $name = strtolower( $name ); 418 419 if( !is_callable( 'compiledTemplate', $name ) ) 420 { 421 jexit( 'Unknown template' ); 422 } 423 424 compiledTemplate::$name(); 425 } 426 427 /** 428 * add a line to the compiled code 429 * 430 * @access public 431 * @param string line to add 432 * @param integer indentation 433 * @return void 434 */ 435 function _addToCode( $line, $indent = 0, $comment = null ) 436 { 437 if( !is_null( $comment ) ) 438 { 439 fputs( $this->_fp, "\n" ); 440 if( $indent > 0 ) 441 fputs( $this->_fp, str_repeat( "\t", $indent ) ); 442 fputs( $this->_fp, "/* $comment */\n" ); 443 } 444 if( $indent > 0 ) 445 fputs( $this->_fp, str_repeat( "\t", $indent ) ); 446 fputs( $this->_fp, $line."\n" ); 447 } 448 449 /** 450 * function, used by the compiler to get a value of a variable 451 * 452 * Checks, whether the value is locally or globally set 453 * 454 * @access private 455 * @param string template 456 * @param string variable name 457 * 458 * @todo check for 'unusedvars' attribute 459 */ 460 function _getVar( $template, $varname ) 461 { 462 if( isset( $this->_templates[$template]['vars'][$varname] ) ) 463 return $this->_templates[$template]['vars'][$varname]; 464 465 if( isset( $this->_globals[$this->_startTag.$varname.$this->_endTag] ) ) 466 return $this->_globals[$this->_startTag.$varname.$this->_endTag]; 467 468 return ''; 469 } 470 471 /** 472 * prepare a template for the compiler 473 * 474 * @access private 475 * @param string template name 476 */ 477 function _prepareCompiledTemplate( $template ) 478 { 479 $this->_templates[$template] = array( 480 'attributes' => array(), 481 'copyVars' => array(), 482 ); 483 } 484 } 485 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Mar 28 15:54:07 2012 | Cross-referenced by PHPXref 0.7.1 |