[ Index ] |
PHP Cross Reference of Web Application Component Toolkit |
[Summary view] [Print] [Text view]
1 <?php 2 //-------------------------------------------------------------------------------- 3 // Copyright 2003 Procata, Inc. 4 // Released under the LGPL license (http://www.gnu.org/copyleft/lesser.html) 5 //-------------------------------------------------------------------------------- 6 /** 7 * @package WACT_TEMPLATE 8 * @version $Id: compilercomponent.inc.php,v 1.45 2004/11/15 21:51:45 jeffmoore Exp $ 9 */ 10 //-------------------------------------------------------------------------------- 11 /** 12 * Base class for compile time components. Compile time component methods are 13 * called by the template parser SourceFileParser.<br /> 14 * Note this in the comments for this class, parent and child refer to the XML 15 * heirarchy in the template, as opposed to the PHP class tree. 16 * @see SourceFileParser 17 * @see http://wact.sourceforge.net/index.php/CompilerComponent 18 * @access public 19 * @abstract 20 * @package WACT_TEMPLATE 21 */ 22 class CompilerComponent { 23 /** 24 * XML attributes of the tag 25 * @var array 26 * @access private 27 */ 28 var $attributeNodes = array(); 29 30 /** 31 * Child compile-time components 32 * @var array of compile time component objects 33 * @access private 34 */ 35 var $children = array(); 36 37 /** 38 * A list of properties for this component 39 * @var array 40 * @access private 41 */ 42 var $properties = array(); 43 44 /** 45 * Parent compile-time component 46 * @var object subclass of CompilerComponent 47 * @access private 48 */ 49 var $parent = NULL; 50 51 /** 52 * Stores the identifying component ID 53 * @var string value of id attribute 54 * @access private 55 */ 56 var $ServerId; 57 58 /** 59 * Name of the XML tag as it appears in the template. This would include 60 * the namespace prefix, if applicable. 61 * @var string tag name 62 * @access private 63 */ 64 var $tag = ''; 65 66 /** 67 * Used to identify the source template file, when generating compile time 68 * error messages. 69 * @var string source template filename 70 * @access private 71 */ 72 var $SourceFile; 73 74 /** 75 * Used to indentify the line number where a compile time error occurred. 76 * @var int line number 77 * @access private 78 */ 79 var $StartingLineNo; 80 81 /** 82 * Defines whether the tag is allowed to have a closing tag 83 * @var boolean 84 * @access private 85 */ 86 var $hasClosingTag = TRUE; 87 88 /** 89 * Whether the was empty and closed such as <br /> 90 * @var boolean 91 * @access private 92 */ 93 var $emptyClosedTag = FALSE; 94 95 /** 96 * Counter for plain text tags matching the current tag component 97 * name. Used to prevent premature closing. See bug 906138 98 * @var int 99 * @access private 100 */ 101 var $plainTagCount = 0; 102 103 /** 104 * TagInfo metadata for this component 105 * @var TagInfo 106 */ 107 var $TagInfo; 108 109 /** 110 * Instance of a CoreWrapTag 111 * @see CoreWrapTag 112 * @var CoreWrapTag 113 * @access private 114 */ 115 var $WrappingComponents = array(); 116 117 /** 118 * Set a wrapping component for this component 119 * @param object 120 * @return void 121 * @access protected 122 */ 123 function registerWrapper(&$wrapper) { 124 $this->WrappingComponents[] =& $wrapper; 125 } 126 127 /** 128 * Sets the XML attributes for this component (as extracted from the 129 * template) 130 * @param object XML attributes 131 * @return void 132 * @access protected 133 */ 134 function addChildAttribute(&$child) { 135 $attrib = strtolower($child->name); 136 if (isset($this->attributeNodes[$attrib])) { 137 RaiseError('compiler', 'DUPLICATEATTRIBUTE', array( 138 'attribute' => $attrib, 139 'tag' => $this->tag, 140 'file' => $this->SourceFile, 141 'line' => $this->StartingLineNo)); 142 } 143 $this->attributeNodes[$attrib] =& $child; 144 } 145 146 /** 147 * Sets an attribute 148 * @param string name of attribute 149 * @param string value of attribute 150 * @return void 151 * @access public 152 */ 153 function setAttribute($attrib, $value) { 154 $Component =& new AttributeNode($attrib, $value); 155 $this->addChildAttribute($Component); 156 } 157 158 /** 159 * Returns the value of an XML attribute (as extracted from template) or 160 * NULL if attribute not found 161 * @param string attribute name 162 * @return mixed string attribute value or null 163 * @access public 164 */ 165 function getAttribute($attrib) { 166 if ( isset($this->attributeNodes[strtolower($attrib)]) ) { 167 return $this->attributeNodes[strtolower($attrib)]->getValue(); 168 } 169 } 170 171 /** 172 * Check to see whether a named attribute exists 173 * @param string name of attribute 174 * @return boolean 175 * @access public 176 */ 177 function hasAttribute($attrib) { 178 return isset($this->attributeNodes[strtolower($attrib)]); 179 } 180 181 /** 182 * Return the value of a boolean attribute as a boolean. 183 * ATTRIBUTE=ANYTHING (true) 184 * ATTRIBUTE=(FALSE|N|NA|NO|NONE|0) (false) 185 * ATTRIBUTE (true) 186 * (attribute unspecified) (default) 187 * @param string attribute name 188 * @param boolean value to return if attribute is not found 189 * @return boolean 190 * @access public 191 */ 192 function getBoolAttribute($attrib, $default = FALSE) { 193 if ( isset($this->attributeNodes[strtolower($attrib)]) ) { 194 switch (strtoupper($this->attributeNodes[strtolower($attrib)]->getValue())) { 195 case 'FALSE': 196 case 'N': 197 case 'NO': 198 case 'NONE': 199 case 'NA': 200 case '0': 201 return false; 202 default: 203 return true; 204 } 205 } else { 206 return $default; 207 } 208 } 209 210 /** 211 * Remove an attribute from the list 212 * @param string name of attribute 213 * @return void 214 * @access public 215 */ 216 function removeAttribute($attrib) { 217 unset($this->attributeNodes[strtolower($attrib)]); 218 } 219 220 /** 221 * Returns an array containing the attributes of this component that 222 * can be resolved at compile time. 223 * @return array representation of attributes 224 * @access protected 225 */ 226 function getAttributesAsArray($suppress = array()) { 227 $suppress = array_map('strtolower', $suppress); 228 $attributes = array(); 229 foreach( array_keys($this->attributeNodes) as $key) { 230 if (!in_array($key, $suppress) && $this->attributeNodes[$key]->isConstant()) { 231 $attributes[$this->attributeNodes[$key]->name] = 232 $this->attributeNodes[$key]->getValue(); 233 $this->getAttribute($key); 234 } 235 } 236 return $attributes; 237 } 238 239 function generateAttributeList(&$code, $suppress = array()) { 240 $suppress = array_map('strtolower', $suppress); 241 foreach( array_keys($this->attributeNodes) as $key) { 242 if (!in_array($key, $suppress)) { 243 $this->attributeNodes[$key]->generate($code); 244 } 245 } 246 } 247 248 function generateDynamicAttributeList(&$code, $suppress = array()) { 249 $suppress = array_map('strtolower', $suppress); 250 foreach( array_keys($this->attributeNodes) as $key) { 251 if (!in_array($key, $suppress) && !$this->attributeNodes[$key]->isConstant()) { 252 $this->attributeNodes[$key]->generate($code); 253 } 254 } 255 } 256 257 /** 258 * register a property with this component. Currently, this 259 * component must be a database to support properties. This may 260 * change. 261 * @access public 262 */ 263 function registerProperty($name, &$property) { 264 $this->properties[$name] =& $property; 265 } 266 267 /** 268 * @return CompilerProperty returns the named property or NULL if it doesn't exist 269 * @access public 270 */ 271 function &getProperty($name) { 272 if (array_key_exists($name, $this->properties)) { 273 return $this->properties[$name]; 274 } else { 275 if ($this->isDataSource()) { 276 return NULL; 277 } else { 278 return $this->parent->getProperty($name); 279 } 280 } 281 } 282 283 /** 284 * Get the value of the XML id attribute 285 * @return string value of id attribute 286 * @access protected 287 */ 288 function getClientId() { 289 if ( $this->hasAttribute('id') ) { 290 return $this->getAttribute('id'); 291 } 292 } 293 294 /** 295 * Returns the identifying server ID. It's value it determined in the 296 * following order; 297 * <ol> 298 * <li>The XML id attribute in the template if it exists</li> 299 * <li>The value of $this->ServerId</li> 300 * <li>An ID generated by the getNewServerId() function</li> 301 * </ol> 302 * @see getNewServerId 303 * @return string value identifying this component 304 * @access protected 305 */ 306 function getServerId() { 307 if ($this->hasAttribute('id')) { 308 return $this->getAttribute('id'); 309 } else if (!empty($this->ServerId)) { 310 return $this->ServerId; 311 } else { 312 $this->ServerId = getNewServerId(); 313 return $this->ServerId; 314 } 315 } 316 317 /** 318 * Adds a child component, by reference, to the array of children 319 * @param object instance of a compile time component 320 * @return void 321 * @access protected 322 */ 323 function addChild(&$child) { 324 $child->parent =& $this; 325 $this->children[] =& $child; 326 } 327 328 /** 329 * Removes a child component, given it's ServerID 330 * @param string server id 331 * @return mixed if child is found, returns a reference to it or void 332 * @access protected 333 */ 334 function &removeChild($ServerId) { 335 foreach( array_keys($this->children) as $key) { 336 $child =& $this->children[$key]; 337 if ($child->getServerid() == $ServerId) { 338 unset($this->children[$key]); 339 return $child; 340 } 341 } 342 } 343 344 /** 345 * Returns the last child added to a component 346 * @return mixed last child instance or false if no children 347 * @access protected 348 */ 349 function &getLastChild() { 350 // end() doesn't return a reference! 351 $end = count($this->children)-1; 352 if ( $end >= 0 ) { 353 return $this->children[$end]; 354 } 355 return FALSE; 356 } 357 358 /** 359 * Returns a child component, given it's ServerID 360 * @param string server id 361 * @return mixed if child is found, returns a reference of false 362 * @access protected 363 */ 364 function &findChild($ServerId) { 365 foreach( array_keys($this->children) as $key) { 366 if ($this->children[$key]->getServerid() == $ServerId) { 367 return $this->children[$key]; 368 } else { 369 $result =& $this->children[$key]->findChild($ServerId); 370 if ($result) { 371 return $result; 372 } 373 } 374 } 375 return FALSE; 376 } 377 378 /** 379 * Returns a child component, given it's compile time component class 380 * @param string PHP class name 381 * @return mixed if child is found, returns a reference of false 382 * @access protected 383 */ 384 function &findChildByClass($class) { 385 foreach( array_keys($this->children) as $key) { 386 if (is_a($this->children[$key], $class)) { 387 return $this->children[$key]; 388 } else { 389 $result =& $this->children[$key]->findChildByClass($class); 390 if ($result) { 391 return $result; 392 } 393 } 394 } 395 return FALSE; 396 } 397 398 /** 399 * Returns an array of child components, given it's compile time component class 400 * @param string PHP class name 401 * @return array 402 * @access protected 403 */ 404 function findChildrenByClass($class) { 405 $ret = array(); 406 foreach( array_keys($this->children) as $key) { 407 if (is_a($this->children[$key], $class)) { 408 $ret[] =& $this->children[$key]; 409 } else { 410 $more_children = $this->children[$key]->findChildrenByClass($class); 411 if (count($more_children)) { 412 $ret = array_merge($ret, $more_children); 413 } 414 } 415 } 416 return $ret; 417 } 418 419 /** 420 * Returns a child component, given it's compile time component class 421 * @param string PHP class name 422 * @return mixed if child is found, returns a reference of false 423 * @access protected 424 */ 425 function &findImmediateChildByClass($class) { 426 foreach( array_keys($this->children) as $key) { 427 if (is_a($this->children[$key], $class)) { 428 return $this->children[$key]; 429 } 430 } 431 return FALSE; 432 } 433 434 /** 435 * Returns a parent component, recursively searching parents by their 436 * compile time component class name 437 * @param string PHP class name 438 * @return mixed if parent is found, returns a reference of void 439 * @access protected 440 */ 441 function &findParentByClass($class) { 442 $Parent =& $this->parent; 443 while ($Parent && !is_a($Parent, $class)) { 444 $Parent =& $Parent->parent; 445 } 446 return $Parent; 447 } 448 449 /** 450 * Extends findParentByClass to begin search at the <i>current</i> component 451 * <i>then</i> moving on to its parent, if there's no match. This is called 452 * from TagJudge to determine known children. 453 * @param string class name 454 * @return mixed if parent is found, returns a reference of void 455 * @access protected 456 */ 457 function & findSelfOrParentByClass($class) { 458 if (is_a($this, $class)) { 459 return $this; 460 } else { 461 return $this->findParentByClass($class); 462 } 463 } 464 465 /** 466 * Calls the prepare method for each child component, which will override 467 * this method it it's concrete implementation. In the subclasses, prepare 468 * will set up compile time variables. For example the CoreWrapTag uses 469 * the prepare method to assign itself as the wrapping component. 470 * @see CoreWrapTag 471 * @return void 472 * @access protected 473 */ 474 function prepare() { 475 foreach( array_keys($this->attributeNodes) as $key) { 476 $this->attributeNodes[$key]->prepare(); 477 } 478 foreach( array_keys($this->children) as $key) { 479 $this->children[$key]->prepare(); 480 } 481 } 482 483 /** 484 * Used to perform some error checking on the source template, such as 485 * examining the tag hierarchy and triggering an error if a tag is 486 * incorrectly nested. Concrete implementation is in subclasses 487 * @return void 488 * @access protected 489 */ 490 function CheckNestingLevel() { 491 } 492 493 /** 494 * Provides instruction to the template parser, while parsing is in 495 * progress, telling it how it should handle the tag. Subclasses of 496 * CompilerComponent will return different instructions.<br /> 497 * Available instructions are; 498 * <ul> 499 * <li>PARSER_REQUIRE_PARSING - default in this class. Tag must be parsed</li> 500 * <li>PARSER_FORBID_PARSING - Tag may not be parsed</li> 501 * <li>PARSER_ALLOW_PARSING - Tag may can be parsed</li> 502 * </ul> 503 * In practice, the parser currently only pays attention to the 504 * PARSER_FORBID_PARSING instruction.<br /> 505 * Also used to perform error checking on template related to the syntax of 506 * the concrete tag implementing this method. 507 * @see SourceFileParser 508 * @return int PARSER_REQUIRE_PARSING 509 * @access protected 510 */ 511 function preParse() { 512 return PARSER_REQUIRE_PARSING; 513 } 514 515 /** 516 * @return Boolean Indicating whether or not this component is a DataSource 517 */ 518 function isDataSource() { 519 return FALSE; 520 } 521 522 /** 523 * If a parent compile time component exists, returns the value of the 524 * parent's getDataSource() method, which will be a concrete implementation 525 * @return mixed object compile time component if parent exists or void 526 * @access protected 527 */ 528 function &getDataSource() { 529 if (!$this->isDataSource()) { 530 if (isset($this->parent)) { 531 return $this->parent->getDataSource(); 532 } 533 } 534 } 535 536 /** 537 * Gets the parent in the DataSource, if one exists 538 * @return mixed object compile time data component if exists or void 539 * @access protected 540 */ 541 function &getParentDataSource() { 542 $DataSource =& $this->getDataSource(); 543 if (isset($DataSource->parent)) { 544 return $DataSource->parent->getDataSource(); 545 } 546 } 547 548 /** 549 * Gets a root DataSource 550 * @return mixed object compile time data component if exists or void 551 * @access protected 552 */ 553 function &getRootDataSource() { 554 $root =& $this; 555 while ($root->parent != NULL) { 556 $root =& $root->parent; 557 } 558 return $root; 559 } 560 561 /** 562 * Gets the DataSource reference code of the parent 563 * @return string 564 * @access protected 565 */ 566 function getDataSourceRefCode() { 567 return $this->parent->getDataSourceRefCode(); 568 } 569 570 /** 571 * Gets the component reference code of the parent. This is a PHP string 572 * which is used in the compiled template to reference the component in 573 * the hierarchy at runtime 574 * @return string 575 * @access protected 576 */ 577 function getComponentRefCode() { 578 return $this->parent->getComponentRefCode(); 579 } 580 581 /** 582 * Calls the generateConstructor() method of each child component 583 * @param CodeWriter 584 * @return void 585 * @access protected 586 */ 587 function generateConstructor(&$code) { 588 foreach( array_keys($this->children) as $key) { 589 $this->children[$key]->generateConstructor($code); 590 } 591 } 592 593 /** 594 * Calls the generate() method of each child component 595 * @param CodeWriter 596 * @return void 597 * @access protected 598 */ 599 function generateContents(&$code) { 600 foreach( array_keys($this->children) as $key) { 601 $this->children[$key]->generate($code); 602 } 603 } 604 605 /** 606 * Pre generation method, calls the WrappingComponents 607 * generateWrapperPrefix() method if the component exists 608 * @see CoreWrapTag 609 * @param CodeWriter 610 * @return void 611 * @access protected 612 */ 613 function preGenerate(&$code) { 614 foreach( array_keys($this->WrappingComponents) as $key) { 615 $this->WrappingComponents[$key]->generateWrapperPrefix($code); 616 } 617 foreach( array_keys($this->properties) as $key) { 618 if ($this->properties[$key]->isActive()) { 619 $this->properties[$key]->generateScopeEntry($code); 620 } 621 } 622 } 623 624 /** 625 * Post generation method, calls the WrappingComponents 626 * generateWrapperPostfix() method if the component exists 627 * @see CoreWrapTag 628 * @param CodeWriter 629 * @return void 630 * @access protected 631 */ 632 function postGenerate(&$code) { 633 foreach( array_keys($this->properties) as $key) { 634 if ($this->properties[$key]->isActive()) { 635 $this->properties[$key]->generateScopeExit($code); 636 } 637 } 638 foreach( array_reverse(array_keys($this->WrappingComponents)) as $key) { 639 $this->WrappingComponents[$key]->generateWrapperPostfix($code); 640 } 641 } 642 643 /** 644 * Calls the local preGenerate(), generateContents() and postGenerate() 645 * methods. 646 * @param CodeWriter 647 * @return void 648 * @access protected 649 */ 650 function generate(&$code) { 651 $this->preGenerate($code); 652 $this->generateContents($code); 653 $this->postGenerate($code); 654 } 655 } 656 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 28 19:36:09 2004 | Cross-referenced by PHPXref 0.5 |