| [ Index ] |
|
Code source de eZ Publish 3.9.0 |
1 <?php 2 // 3 // Definition of eZXMLOutputHandler class 4 // 5 // Created on: <06-Nov-2002 15:10:02 wy> 6 // 7 // SOFTWARE NAME: eZ publish 8 // SOFTWARE RELEASE: 3.9.0 9 // BUILD VERSION: 17785 10 // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS 11 // SOFTWARE LICENSE: GNU General Public License v2.0 12 // NOTICE: > 13 // This program is free software; you can redistribute it and/or 14 // modify it under the terms of version 2.0 of the GNU General 15 // Public License as published by the Free Software Foundation. 16 // 17 // This program is distributed in the hope that it will be useful, 18 // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 // GNU General Public License for more details. 21 // 22 // You should have received a copy of version 2.0 of the GNU General 23 // Public License along with this program; if not, write to the Free 24 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 25 // MA 02110-1301, USA. 26 // 27 // 28 29 /*! \file ezxmloutputhandler.php 30 */ 31 32 /*! 33 \class eZXMLOutputHandler ezxmloutputhandler 34 \ingroup eZDatatype 35 \brief The class eZXMLOutputHandler does 36 37 */ 38 39 include_once ( "lib/ezxml/classes/ezxml.php" ); 40 41 include_once ( 'kernel/classes/datatypes/ezurl/ezurl.php' ); 42 include_once ( 'lib/eztemplate/classes/eztemplateincludefunction.php' ); 43 44 include_once ( "lib/ezxml/classes/ezxml.php" ); 45 46 if ( !class_exists( 'eZXMLSchema' ) ) 47 include_once ( 'kernel/classes/datatypes/ezxmltext/ezxmlschema.php' ); 48 49 class eZXMLOutputHandler 50 { 51 /*! 52 Constructor 53 */ 54 function eZXMLOutputHandler( &$xmlData, $aliasedType, $contentObjectAttribute = null ) 55 { 56 $this->XMLData =& $xmlData; 57 $this->AliasedType = $aliasedType; 58 $this->AliasedHandler = null; 59 60 if ( is_object( $contentObjectAttribute ) ) 61 { 62 $this->ContentObjectAttribute =& $contentObjectAttribute; 63 $this->ObjectAttributeID = $contentObjectAttribute->attribute( 'id' ); 64 } 65 66 $ini =& eZINI::instance( 'ezxml.ini' ); 67 if ( $ini->hasVariable( 'InputSettings', 'AllowMultipleSpaces' ) ) 68 { 69 $allowMultipleSpaces = $ini->variable( 'InputSettings', 'AllowMultipleSpaces' ); 70 $this->AllowMultipleSpaces = $allowMultipleSpaces == 'true' ? true : false; 71 } 72 if ( $ini->hasVariable( 'InputSettings', 'AllowNumericEntities' ) ) 73 { 74 $allowNumericEntities = $ini->variable( 'InputSettings', 'AllowNumericEntities' ); 75 $this->AllowNumericEntities = $allowNumericEntities == 'true' ? true : false; 76 } 77 } 78 79 /*! 80 \return an array with attribute names. 81 */ 82 function attributes() 83 { 84 return array( 'output_text', 85 'aliased_type', 86 'aliased_handler', 87 'view_template_name' ); 88 } 89 90 /*! 91 \return true if the attribute \a $name exists. 92 */ 93 function hasAttribute( $name ) 94 { 95 return in_array( $name, $this->attributes() ); 96 } 97 98 /*! 99 \return the value of the attribute \a $name if it exists, if not returns \c null. 100 */ 101 function &attribute( $name ) 102 { 103 switch ( $name ) 104 { 105 case 'output_text': 106 { 107 $retValue =& $this->outputText(); 108 } break; 109 case 'aliased_type': 110 { 111 return $this->AliasedType; 112 } break; 113 case 'view_template_name': 114 { 115 $retValue =& $this->viewTemplateName(); 116 } break; 117 case 'aliased_handler': 118 { 119 if ( $this->AliasedType !== false and 120 $this->AliasHandler === null ) 121 { 122 $this->AliasedHandler =& eZXMLText::inputHandler( $this->XMLData, 123 $this->AliasedType, 124 false ); 125 } 126 return $this->AliasedHandler; 127 } break; 128 default: 129 { 130 eZDebug::writeError( "Attribute '$name' does not exist", 'eZXMLOutputHandler::attribute' ); 131 $retValue = null; 132 } break; 133 } 134 return $retValue; 135 } 136 137 /*! 138 \return the template name for this input handler, includes the edit suffix if any. 139 */ 140 function &viewTemplateName() 141 { 142 $name = 'ezxmltext'; 143 $suffix = $this->viewTemplateSuffix(); 144 if ( $suffix !== false ) 145 $name .= '_' . $suffix; 146 return $name; 147 } 148 149 /*! 150 \virtual 151 \return true if the output handler is considered valid, if not the handler will not be used. 152 \note Default returns true 153 */ 154 function isValid() 155 { 156 return true; 157 } 158 159 /*! 160 \pure 161 \return the suffix for the attribute template, if false it is ignored. 162 */ 163 function &viewTemplateSuffix( &$contentobjectAttribute ) 164 { 165 $suffix = false; 166 return $suffix; 167 } 168 169 /*! 170 \return the xml data as text. 171 */ 172 function xmlData() 173 { 174 return $this->XMLData; 175 } 176 177 /*! 178 Returns the output text representation of the XML structure 179 Default implementation uses default mechanism of rules and tag handlers to render tags. 180 */ 181 function &outputText() 182 { 183 $this->Tpl =& templateInit(); 184 $this->Res =& eZTemplateDesignResource::instance(); 185 if ( $this->ContentObjectAttribute ) 186 { 187 $this->Res->setKeys( array( array( 'attribute_identifier', $this->ContentObjectAttribute->attribute( 'contentclass_attribute_identifier' ) ) ) ); 188 } 189 190 $xml = new eZXML(); 191 $this->Document =& $xml->domTree( $this->XMLData, array( "TrimWhiteSpace" => false, "SetParentNode" => true ) ); 192 if ( !$this->Document ) 193 { 194 $this->Output = ''; 195 return $this->Output; 196 } 197 198 $this->prefetch(); 199 200 $this->XMLSchema =& eZXMLSchema::instance(); 201 202 // Add missing elements to the OutputTags array 203 foreach( $this->XMLSchema->availableElements() as $element ) 204 { 205 if ( !isset( $this->OutputTags[$element] ) ) 206 $this->OutputTags[$element] = array(); 207 } 208 209 $this->NestingLevel = 0; 210 $params = array(); 211 212 $output = $this->outputTag( $this->Document->Root, $params ); 213 $this->Output = $output[1]; 214 215 $this->Document->cleanup(); 216 217 unset( $this->Document ); 218 unset( $this->XMLData ); 219 220 $this->Res->removeKey( 'attribute_identifier' ); 221 return $this->Output; 222 } 223 224 // Prefetch objects, nodes and urls for further rendering 225 function prefetch() 226 { 227 $relatedObjectIDArray = array(); 228 $nodeIDArray = array(); 229 230 // Fetch all links and cache urls 231 $links =& $this->Document->elementsByName( "link" ); 232 233 if ( count( $links ) > 0 ) 234 { 235 $linkIDArray = array(); 236 // Find all Link ids 237 foreach ( $links as $link ) 238 { 239 $linkID = $link->attributeValue( 'url_id' ); 240 if ( $linkID && !in_array( $linkID, $linkIDArray ) ) 241 $linkIDArray[] = $linkID; 242 243 $objectID = $link->attributeValue( 'object_id' ); 244 if ( $objectID && !in_array( $objectID, $relatedObjectIDArray ) ) 245 $relatedObjectIDArray[] = $objectID; 246 247 $nodeID = $link->attributeValue( 'node_id' ); 248 if ( $nodeID && !in_array( $nodeID, $nodeIDArray ) ) 249 $nodeIDArray[] = $nodeID; 250 } 251 252 if ( count( $linkIDArray ) > 0 ) 253 { 254 $inIDSQL = implode( ', ', $linkIDArray ); 255 256 $db =& eZDB::instance(); 257 $linkArray = $db->arrayQuery( "SELECT * FROM ezurl WHERE id IN ( $inIDSQL ) " ); 258 259 foreach ( $linkArray as $linkRow ) 260 { 261 $this->LinkArray[$linkRow['id']] = $linkRow['url']; 262 } 263 } 264 } 265 266 // Fetch all embeded objects and cache by ID 267 $objectArray =& $this->Document->elementsByName( "object" ); 268 269 if ( count( $objectArray ) > 0 ) 270 { 271 foreach ( $objectArray as $object ) 272 { 273 $objectID = $object->attributeValue( 'id' ); 274 if ( $objectID != null && !in_array( $objectID, $relatedObjectIDArray ) ) 275 $relatedObjectIDArray[] = $objectID; 276 } 277 } 278 279 $embedTagArray =& $this->Document->elementsByName( "embed" ); 280 $embedInlineTagArray =& $this->Document->elementsByName( "embed-inline" ); 281 282 $embedTags = array_merge( $embedTagArray, $embedInlineTagArray ); 283 284 if ( count( $embedTags ) > 0 ) 285 { 286 foreach ( $embedTags as $embedTag ) 287 { 288 $objectID = $embedTag->attributeValue( 'object_id' ); 289 if ( $objectID && !in_array( $objectID, $relatedObjectIDArray ) ) 290 $relatedObjectIDArray[] = $objectID; 291 292 $nodeID = $embedTag->attributeValue( 'node_id' ); 293 if ( $nodeID && !in_array( $nodeID, $nodeIDArray ) ) 294 $nodeIDArray[] = $nodeID; 295 } 296 } 297 298 if ( $relatedObjectIDArray != null ) 299 $this->ObjectArray =& eZContentObject::fetchIDArray( $relatedObjectIDArray ); 300 301 if ( $nodeIDArray != null ) 302 { 303 $nodes = eZContentObjectTreeNode::fetch( $nodeIDArray ); 304 305 if ( is_array( $nodes ) ) 306 { 307 foreach( $nodes as $node ) 308 { 309 $nodeID = $node->attribute( 'node_id' ); 310 $this->NodeArray["$nodeID"] = $node; 311 } 312 } 313 elseif ( $nodes ) 314 { 315 $node =& $nodes; 316 $nodeID = $node->attribute( 'node_id' ); 317 $this->NodeArray["$nodeID"] = $node; 318 } 319 } 320 } 321 322 // Main recursive functions for rendering tags 323 // $element - current element 324 // $sibilingParams - array of parameters that are passed by reference to all the children of the 325 // current tag to provide a way to "communicate" between their handlers. 326 // This array is empty for the first child. 327 // $parentParams - parameter passed to this tag handler by the parent tag's handler. 328 // This array is passed with no reference. Can by modified in tag's handler 329 // for subordinate tags. 330 331 function outputTag( &$element, &$sibilingParams, $parentParams = array() ) 332 { 333 $tagName = $element->nodeName; 334 if ( isset( $this->OutputTags[$tagName] ) ) 335 { 336 $currentTag =& $this->OutputTags[$tagName]; 337 } 338 else 339 $currentTag = null; 340 341 // Prepare attributes array 342 $attributeNodes = $element->attributes(); 343 $attributes = array(); 344 foreach( $attributeNodes as $attrNode ) 345 { 346 if ( $attrNode->Prefix && $attrNode->Prefix != 'custom' ) 347 $attrName = $attrNode->Prefix . ':' . $attrNode->LocalName; 348 else 349 $attrName = $attrNode->nodeName; 350 351 // classes check 352 if ( $attrName == 'class' ) 353 { 354 $classesList = $this->XMLSchema->getClassesList( $tagName ); 355 if ( !in_array( $attrNode->value, $classesList ) ) 356 { 357 eZDebug::writeWarning( "Using tag '$tagName' with class '$attrNode->value' is not allowed.", 'XML output handler' ); 358 return array( true, '' ); 359 } 360 } 361 362 $attributes[$attrName] = $attrNode->value; 363 } 364 365 // Set default attribute values if not present in the input 366 $attrDefaults = $this->XMLSchema->attrDefaultValues( $tagName ); 367 foreach( $attrDefaults as $name=>$value ) 368 { 369 if ( !isset( $attributes[$name] ) ) 370 $attributes[$name] = $value; 371 } 372 373 // Init handler returns an array that may contain the following items: 374 // 375 // 'no_render' (boolean) : 376 // If false tag will not be rendered, only it's children (if any). 377 // 'design_keys' array( 'design_key_name_1' => 'value_1', 'design_key_name_2'=>'value_2', ... ) : 378 // An array of additional design keys. 379 // 'tpl_vars' array( 'var_name_1' => 'value_1', 'var_name_2' => 'value_2', ... ) : 380 // An array of additional template variables. 381 // 'template_name' (string) : 382 // Overrides tag template name. 383 384 $result = $this->callTagInitHandler( 'initHandler', $element, $attributes, $sibilingParams, $parentParams ); 385 386 // Process children 387 $childrenOutput = array(); 388 if ( $element->hasChildNodes() ) 389 { 390 // Initialize sibiling parameters array for the next level children 391 // Parent parameters for the children may be modified in the current tag handler. 392 $nextSibilingParams = array(); 393 394 $this->NestingLevel++; 395 foreach( array_keys( $element->Children ) as $key ) 396 { 397 $child =& $element->Children[$key]; 398 $childOutput = $this->outputTag( $child, $nextSibilingParams, $parentParams ); 399 400 if ( is_array( $childOutput[0] ) ) 401 $childrenOutput = array_merge( $childrenOutput, $childOutput ); 402 else 403 $childrenOutput[] = $childOutput; 404 } 405 $this->NestingLevel--; 406 } 407 else 408 { 409 $childrenOutput = array( array( true, '' ) ); 410 } 411 412 if ( isset( $result['no_render'] ) && $result['no_render'] ) 413 { 414 return $childrenOutput; 415 } 416 417 // Set tpl variables by attributes and rename rules 418 $vars = array(); 419 420 if ( !isset( $currentTag['quickRender'] ) && isset( $currentTag['attrNamesTemplate'] ) ) 421 $attrRenameRules =& $currentTag['attrNamesTemplate']; 422 elseif ( isset( $currentTag['quickRender'] ) && isset( $currentTag['attrNamesQuick'] ) ) 423 $attrRenameRules =& $currentTag['attrNamesQuick']; 424 else 425 $attrRenameRules = array(); 426 427 foreach( $attributes as $name=>$value ) 428 { 429 if ( isset( $attrRenameRules[$name] ) ) 430 { 431 $vars[$attrRenameRules[$name]] = $value; 432 continue; 433 } 434 435 if ( substr( $name, 0, 6 ) == 'custom:' ) 436 $name = substr( $name, strpos( $name, ':' ) + 1 ); 437 438 $vars[$name] = $value; 439 } 440 441 // set missing variables that have rename rules defined 442 // but were not present in the element 443 foreach( $attrRenameRules as $attrName=>$varName ) 444 { 445 if ( !isset( $attributes[$attrName] ) ) 446 $vars[$varName] = ''; 447 } 448 449 $this->TemplateUri = ''; 450 451 // In quick render mode we does not use templates and 452 // render template variables as tag attributes 453 if ( !isset( $currentTag['quickRender'] ) ) 454 { 455 // Set additional variables passed by tag handler 456 if ( isset( $result['tpl_vars'] ) ) 457 { 458 $vars = array_merge( $vars, $result['tpl_vars'] ); 459 } 460 461 foreach( $vars as $name=>$value ) 462 { 463 $this->Tpl->setVariable( $name, $value, 'xmltagns' ); 464 } 465 466 // Create design keys array 467 $designKeys = array(); 468 if ( isset( $currentTag['attrDesignKeys'] ) ) 469 { 470 foreach( $currentTag['attrDesignKeys'] as $attrName=>$keyName ) 471 { 472 if ( isset( $attributes[$attrName] ) && $attributes[$attrName] ) 473 $designKeys[$keyName] = $attributes[$attrName]; 474 } 475 } 476 // Set additional design keys passed by tag handler 477 if ( isset( $result['design_keys'] ) ) 478 { 479 $designKeys = array_merge( $designKeys, $result['design_keys'] ); 480 } 481 482 $existingKeys = $this->Res->keys(); 483 $savedKeys = array(); 484 485 // Save old keys values and set new design keys 486 foreach( $designKeys as $key=>$value ) 487 { 488 if ( isset( $existingKeys[$key] ) ) 489 { 490 $savedKeys[$key] = $existingKeys[$key]; 491 } 492 $this->Res->setKeys( array( array( $key, $value ) ) ); 493 } 494 495 // Template name 496 if ( isset( $result['template_name'] ) ) 497 { 498 $templateName = $result['template_name']; 499 } 500 else 501 { 502 $templateName = $element->nodeName; 503 } 504 $this->TemplateUri = $this->TemplatesPath . $templateName . '.tpl'; 505 } 506 507 $output = $this->callTagRenderHandler( 'renderHandler', $element, $childrenOutput, $vars ); 508 509 if ( !isset( $currentTag['quickRender'] ) ) 510 { 511 // Restore saved template override keys and remove others 512 foreach( $designKeys as $key=>$value ) 513 { 514 if ( isset( $savedKeys[$key] ) ) 515 $this->Res->setKeys( array( array( $key, $savedKeys[$key] ) ) ); 516 else 517 $this->Res->removeKey( $key ); 518 } 519 520 // Unset variables 521 foreach( $vars as $name=>$value ) 522 { 523 if ( $this->Tpl->hasVariable( $name, 'xmltagns' ) ) 524 $this->Tpl->unsetVariable( $name, 'xmltagns' ); 525 } 526 } 527 528 return $output; 529 } 530 531 function renderTag( &$element, $content, $vars ) 532 { 533 $currentTag =& $this->OutputTags[$element->nodeName]; 534 if ( $currentTag && isset( $currentTag['quickRender'] ) ) 535 { 536 $renderedTag = ''; 537 $attrString = ''; 538 foreach( $vars as $name=>$value ) 539 { 540 if ( $value != '' ) 541 $attrString .= " $name=\"$value\""; 542 } 543 544 if ( isset( $currentTag['quickRender'][0] ) && $currentTag['quickRender'][0] ) 545 $renderedTag = '<' . $currentTag['quickRender'][0] . "$attrString>" . $content . '</' . $currentTag['quickRender'][0] . '>'; 546 else 547 $renderedTag = $content; 548 549 if ( isset( $currentTag['quickRender'][1] ) && $currentTag['quickRender'][1] ) 550 $renderedTag .= $currentTag['quickRender'][1]; 551 } 552 else 553 { 554 if ( isset( $currentTag['contentVarName'] ) ) 555 $contentVarName = $currentTag['contentVarName']; 556 else 557 $contentVarName = 'content'; 558 559 $this->Tpl->setVariable( $contentVarName, $content, 'xmltagns' ); 560 eZTemplateIncludeFunction::handleInclude( $textElements, $this->TemplateUri, $this->Tpl, 'foo', 'xmltagns' ); 561 $renderedTag = is_array( $textElements ) ? implode( '', $textElements ) : ''; 562 } 563 return $renderedTag; 564 } 565 566 // Default render handler 567 // Renders all the content of children tags inside the current tag 568 function renderAll( &$element, $childrenOutput, $vars ) 569 { 570 $tagText = ''; 571 foreach( $childrenOutput as $childOutput ) 572 { 573 $tagText .= $childOutput[1]; 574 } 575 $tagText = $this->renderTag( $element, $tagText, $vars ); 576 return array( false, $tagText ); 577 } 578 579 function callTagInitHandler( $handlerName, &$element, &$attributes, &$sibilingParams, &$parentParams ) 580 { 581 $result = array(); 582 $thisOutputTag =& $this->OutputTags[$element->nodeName]; 583 if ( isset( $thisOutputTag[$handlerName] ) ) 584 { 585 if ( is_callable( array( $this, $thisOutputTag[$handlerName] ) ) ) 586 eval( '$result = $this->' . $thisOutputTag[$handlerName] . '( $element, $attributes, $sibilingParams, $parentParams );' ); 587 } 588 return $result; 589 } 590 591 function callTagRenderHandler( $handlerName, &$element, $childrenOutput, $vars ) 592 { 593 $result = array(); 594 $thisOutputTag =& $this->OutputTags[$element->nodeName]; 595 if ( isset( $thisOutputTag[$handlerName] ) ) 596 $handlerFunction = $thisOutputTag[$handlerName]; 597 else 598 $handlerFunction = 'renderAll'; 599 600 if ( is_callable( array( $this, $handlerFunction ) ) ) 601 eval( '$result = $this->' . $handlerFunction . '( $element, $childrenOutput, $vars );' ); 602 else 603 eZDebug::writeWarning( "'$handlerName' render handler for tag <$element->nodeName> doesn't exist: '" . $thisOutputTag[$handlerName] . "'.", 'eZXML converter' ); 604 return $result; 605 } 606 607 // This array should be overriden in derived class with the set of rules 608 // for outputting tags. 609 var $OutputTags = array(); 610 611 // Path to tags' templates 612 var $TemplatesPath = 'design:content/datatype/view/ezxmltags/'; 613 614 /// Contains the XML data as text 615 var $XMLData; 616 var $Document; 617 618 var $XMLSchema; 619 620 var $AliasedType; 621 var $AliasedHandler; 622 623 var $Output = ''; 624 var $Tpl; 625 var $TemplateURI = ''; 626 var $Res; 627 628 var $AllowMultipleSpaces = false; 629 var $AllowNumericEntities = false; 630 631 var $ContentObjectAttribute; 632 var $ObjectAttributeID; 633 634 /// Contains the URL's for <link> tags hashed by ID 635 var $LinkArray = array(); 636 /// Contains the Objects hashed by ID 637 var $ObjectArray = array(); 638 /// Contains the Nodes hashed by ID 639 var $NodeArray = array(); 640 641 var $NestingLevel = 0; 642 } 643 644 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sat Feb 24 10:30:04 2007 | par Balluche grâce à PHPXref 0.7 |