| [ Index ] |
PHP Cross Reference of Limb3 |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 * Limb PHP Framework 4 * 5 * @link http://limb-project.com 6 * @copyright Copyright © 2004-2007 BIT(http://bit-creative.com) 7 * @license LGPL http://www.gnu.org/copyleft/lesser.html 8 */ 9 10 /** 11 * Acts on the WactCompileTreeRootNode in response to events within the WactSourceFileParser 12 * 13 * When adding an open tag to the tree, call pushExpectedTag(). When closing 14 * a tag, call popExpectedTag(), which ensures the tree is balanced. 15 * 16 * These methods do not actually add nodes to the tree, as tags and nodes 17 * do not necessarily match up. 18 * 19 * To add a node to the tree, you have the following choices. To add a node 20 * which can have children, use pushNode(). To add a terminal node use addNode(), 21 * or addWactTextNode(). 22 * 23 * @package wact 24 * @version $Id: WactTreeBuilder.class.php 5945 2007-06-06 08:31:43Z pachanga $ 25 */ 26 27 28 define ('WACT_EXPECTED_WACT_TAG', 1); 29 define ('WACT_EXPECTED_PLAIN_TAG', 2);class WactTreeBuilder 30 { 31 /** 32 * @var WactCompiler 33 */ 34 protected $compiler; 35 36 /** 37 * Current node 38 * @var WactCompileTreeNode 39 * @access private 40 */ 41 var $component; 42 43 protected $property_dictionary; 44 protected $tag_dictionary; 45 protected $filter_dictionary; 46 47 /** 48 * Stack of tags pushed onto the tree builder, may also contain components 49 * @see pushExpectedTag 50 * @see popExpectedTag 51 * @see pushCursor 52 * @access private 53 */ 54 protected $expected_tags = array(); 55 56 function __construct($compiler, $tag_dictionary, $property_dictionary, $filter_dictionary) 57 { 58 $this->compiler = $compiler; 59 $this->tag_dictionary = $tag_dictionary; 60 $this->property_dictionary = $property_dictionary; 61 $this->filter_dictionary = $filter_dictionary; 62 } 63 64 /** 65 * Returns the current component 66 * @return WactCompileTreeNode 67 * @return void 68 */ 69 function getCursor() 70 { 71 return $this->cursor_node; 72 } 73 74 /** 75 * Sets the cursor (the current working component) of the tree builder 76 * @param WactCompileTreeNode 77 * @return void 78 */ 79 function setCursor($node) 80 { 81 $this->cursor_node = $node; 82 } 83 84 /** 85 * Begins a component's build phase in relation to the component tree. 86 * Adds a component to the tree, then makes that component the 'cursor'. 87 * @param WactCompileTreeNode 88 * @return void 89 */ 90 function pushNode($new_node) 91 { 92 $this->cursor_node->addChild($new_node); 93 $this->setCursor($new_node); 94 95 return $this->cursor_node->preParse($this->compiler); 96 } 97 98 /** 99 * Adds a component to the tree, without descending into it. 100 * This begins and finishes the component's composition 101 * @param WactCompileTreeNode 102 */ 103 function addNode($child_node) 104 { 105 $this->cursor_node->addChild($child_node); 106 $child_node->preParse($this->compiler); 107 } 108 109 function addWactTextNode($text) 110 { 111 $this->addNode(new WactTextNode(null, $text)); 112 } 113 114 /** 115 * Ends a component's build phase in relation to the tree. 116 * Checks child server ids and moves the 'cursor' up the tree to the parent 117 * component. 118 */ 119 function popNode() 120 { 121 $this->cursor_node->checkChildrenServerIds(); 122 $this->setCursor($this->cursor_node->parent); 123 } 124 125 /** 126 * @param string tag name 127 * @param mixed info about the tag 128 * @param boolean if the tag is one of the wact tags (of having wact:id or runat='server' attributes) 129 * @return void 130 */ 131 function _pushExpectedTag($tag, $location, $tag_kind) 132 { 133 array_push($this->expected_tags, array($tag, $location, $tag_kind)); 134 } 135 136 function pushExpectedPlainTag($tag, $location) 137 { 138 $this->_pushExpectedTag($tag, $location, WACT_EXPECTED_PLAIN_TAG); 139 } 140 141 function pushExpectedWactTag($tag, $location) 142 { 143 $this->_pushExpectedTag($tag, $location, WACT_EXPECTED_WACT_TAG); 144 } 145 146 /** 147 * Sets the cursor to a new position, and pushes the old cursor onto the expected tags stack. 148 * @param WactCompileTreeNode 149 * @return void 150 */ 151 function pushCursor($new_position, $location) 152 { 153 $this->pushExpectedWactTag($this->cursor_node, $location); 154 $this->setCursor($new_position); 155 } 156 157 /** 158 * Tests the passed tag against what is expected. 159 * Returns info if expected tag was a wact tag or a plain tag 160 */ 161 protected function _popExpectedTag($pop_tag, $pop_tag_location, $pop_tag_kind) 162 { 163 if(!$expected_tag_info = array_pop($this->expected_tags)) 164 { 165 throw new WactException('Lonely closing tag', array('tag' => $pop_tag, 166 'file' => $pop_tag_location->getFile(), 167 'line' => $pop_tag_location->getLine())); 168 } 169 170 // if we have a cursor on the stack, restore the current cursor to that, and 171 // pop the stack again 172 if (is_object($expected_tag_info[0])) 173 { 174 $this->cursor_node =& $expected_tag_info[0]; 175 return $this->_popExpectedTag($pop_tag, $pop_tag_location, $pop_tag_kind); 176 } 177 178 $expected_tag = $expected_tag_info[0]; 179 $expected_tag_location = $expected_tag_info[1]; 180 $expected_tag_kind = $expected_tag_info[2]; 181 182 // if the tag names are equal we dont care about if they are both wact tags or not 183 if(strcasecmp($expected_tag, $pop_tag) === 0) 184 return $expected_tag_kind; 185 186 // ignore plain html tag since we dont need to balance them 187 if($expected_tag_kind == WACT_EXPECTED_PLAIN_TAG) 188 return $this->_popExpectedTag($pop_tag, $pop_tag_location, $pop_tag_kind); 189 190 // we stops at the nearest wact tag if we poping up a plain html tag 191 if(($expected_tag_kind == WACT_EXPECTED_WACT_TAG) && ($pop_tag_kind == WACT_EXPECTED_PLAIN_TAG)) 192 { 193 // restore stack 194 $this->pushExpectedWactTag($expected_tag, $expected_tag_location); 195 return WACT_EXPECTED_PLAIN_TAG; 196 } 197 198 // if we expected a wact tag and poping up a wact tag also and the tags names are different 199 // => template is not balanced. 200 throw new WactException('Unexpected closing tag', 201 array('file' => $pop_tag_location->getFile(), 202 'tag' => $pop_tag, 203 'line' => $pop_tag_location->getLine(), 204 'ExpectTag' => $expected_tag, 205 'ExpectTagFile' => $expected_tag_location->getFile(), 206 'ExpectedTagLine' => $expected_tag_location->getLine())); 207 } 208 209 function popExpectedPlainTag($pop_tag, $pop_tag_location) 210 { 211 return $this->_popExpectedTag($pop_tag, $pop_tag_location, WACT_EXPECTED_PLAIN_TAG); 212 } 213 214 function popExpectedWactTag($pop_tag, $pop_tag_location) 215 { 216 return $this->_popExpectedTag($pop_tag, $pop_tag_location, WACT_EXPECTED_WACT_TAG); 217 } 218 219 function getExpectedTagCount() 220 { 221 return count($this->expected_tags); 222 } 223 224 function getExpectedTag() 225 { 226 // Returns the tagname of the first non-component item on the stack 227 $item = end($this->expected_tags); 228 while ($item && !is_string($item[0])) { 229 $item = prev($this->expected_tags); 230 } 231 return $item ? $item[0] : false; 232 } 233 234 function getExpectedTagLocation() 235 { 236 $item = end($this->expected_tags); 237 return $item[1]; 238 } 239 240 function addProcessingInstruction($target, $instruction) 241 { 242 // Pass through any PI's except PHP PI's 243 $php_targets = array('php','PHP','=',''); 244 if(in_array($target, $php_targets)) 245 { 246 $this->addNode(new WactPHPNode(null, $instruction)); 247 } 248 else 249 { 250 $php = 'echo "<?'.$target.' '; // Whitespace assumption 251 $php.= str_replace('"','\"',$instruction); 252 $php.= '?>\n";'; // Newline assumption 253 $this->addNode(new WactPHPNode(null, $php)); 254 } 255 } 256 257 /** 258 * Builds a component, adding attributes 259 * @param WactTagInfo 260 * @param string XML tag name of component 261 * @param array attributes for tag 262 * @param boolean whether the tag has contents 263 * @return WactCompileTreeNode 264 */ 265 function buildTagNode($tag_info, $tag, $location, $attrs, $is_empty = false, $has_closing_tag = true) 266 { 267 $tag_node = $this->_createTagNode($tag_info, $tag, $location); 268 269 $this->_registerPropertiesInTagNode($tag_node); 270 271 $tag_node->emptyClosedTag = $is_empty; 272 $tag_node->hasClosingTag = $has_closing_tag; 273 274 $this->_convertAttributesToExpressionIfRequired($tag_node, $tag_info, $attrs); 275 276 $this->_addAttributesToTagNode($tag_node, $location, $attrs); 277 278 return $tag_node; 279 } 280 281 protected function _createTagNode($tag_info, $tag, $location) 282 { 283 $class = $tag_info->TagClass; 284 $tag_node = new $class($location, $tag, $tag_info); 285 286 return $tag_node; 287 } 288 289 protected function _registerPropertiesInTagNode($tag_node) 290 { 291 $properties = $this->property_dictionary->getPropertyList($tag_node); 292 foreach ($properties as $property) 293 { 294 $property->load(); 295 $property_class = $property->PropertyClass; 296 $tag_node->registerProperty($property->Property, new $property_class($tag_node)); 297 } 298 } 299 300 protected function _addAttributesToTagNode($tag_node, $location, $attrs) 301 { 302 foreach ($attrs as $name => $value) 303 { 304 $attribute = new WactAttribute($name); 305 if($value !== NULL) 306 { 307 $listener = new WactAttributeBlockAnalizerListener($attribute, $tag_node, $this->filter_dictionary); 308 309 $analizer = new WactBlockAnalizer(); 310 $analizer->parse($value, $listener); 311 } 312 313 $tag_node->addChildAttribute($attribute); 314 } 315 } 316 317 // this code added to support old form of DBE expressions in some attributes 318 // like <core:optional for='var'> should actually be <core:optional 319 protected function _convertAttributesToExpressionIfRequired($tag_node, $tag_info, &$attributes) 320 { 321 foreach($tag_info->getConvertAttributesToExpressions() as $name) 322 { 323 if(!isset($attributes[$name])) 324 continue; 325 326 $value = $attributes[$name]; 327 328 if(strpos($value, '{$') !== FALSE) 329 continue; 330 331 if($tag_node->isDataSource() && (strpos($value, '#') === FALSE)) 332 $attributes[$name] = '{$^' . $value . '}'; 333 else 334 $attributes[$name] = '{$' . $value . '}'; 335 } 336 } 337 338 function addContent($text, $location) 339 { 340 $listener = new WactContentBlockAnalizerListener($this, $location, $this->filter_dictionary); 341 $analizer = new WactBlockAnalizer(); 342 $analizer->parse($text, $listener); 343 } 344 } 345 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Sat Sep 6 04:46:52 2008 | Cross-referenced by PHPXref 0.7 |