|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZXHTMLXMLOutput class 00004 // 00005 // Created on: <18-Aug-2006 15:05:00 ks> 00006 // 00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00008 // SOFTWARE NAME: eZ Publish 00009 // SOFTWARE RELEASE: 4.0.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS 00011 // SOFTWARE LICENSE: GNU General Public License v2.0 00012 // NOTICE: > 00013 // This program is free software; you can redistribute it and/or 00014 // modify it under the terms of version 2.0 of the GNU General 00015 // Public License as published by the Free Software Foundation. 00016 // 00017 // This program is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 // GNU General Public License for more details. 00021 // 00022 // You should have received a copy of version 2.0 of the GNU General 00023 // Public License along with this program; if not, write to the Free 00024 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00025 // MA 02110-1301, USA. 00026 // 00027 // 00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00029 // 00030 00031 /*! 00032 */ 00033 00034 //include_once( 'kernel/classes/datatypes/ezxmltext/ezxmloutputhandler.php' ); 00035 ////include_once( 'lib/eztemplate/classes/eztemplateincludefunction.php' ); 00036 00037 class eZXHTMLXMLOutput extends eZXMLOutputHandler 00038 { 00039 00040 public $OutputTags = array( 00041 00042 'section' => array( 'quickRender' => true, 00043 'initHandler' => 'initHandlerSection', 00044 'renderHandler' => 'renderChildrenOnly' ), 00045 00046 'embed' => array( 'initHandler' => 'initHandlerEmbed', 00047 'renderHandler' => 'renderAll', 00048 'attrNamesTemplate' => array( 'class' => 'classification', 00049 'xhtml:id' => 'id', 00050 'object_id' => false, 00051 'node_id' => false, 00052 'show_path' => false ), 00053 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00054 00055 'embed-inline' => array( 'initHandler' => 'initHandlerEmbed', 00056 'renderHandler' => 'renderInline', 00057 'attrNamesTemplate' => array( 'class' => 'classification', 00058 'xhtml:id' => 'id', 00059 'object_id' => false, 00060 'node_id' => false, 00061 'show_path' => false ), 00062 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00063 00064 'table' => array( 'initHandler' => 'initHandlerTable', 00065 'renderHandler' => 'renderAll', 00066 'contentVarName' => 'rows', 00067 'attrNamesTemplate' => array( 'class' => 'classification', 00068 'width' => 'width' ), 00069 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00070 00071 'tr' => array( //'quickRender' => array( 'tr', "\n" ), 00072 'initHandler' => 'initHandlerTr', 00073 'renderHandler' => 'renderAll', 00074 'attrNamesTemplate' => array( 'class' => 'classification' ), 00075 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00076 00077 'td' => array( 'initHandler' => 'initHandlerTd', 00078 'renderHandler' => 'renderAll', 00079 'attrNamesTemplate' => array( 'xhtml:width' => 'width', 00080 'xhtml:colspan' => 'colspan', 00081 'xhtml:rowspan' => 'rowspan', 00082 'class' => 'classification' ), 00083 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00084 00085 'th' => array( 'initHandler' => 'initHandlerTd', 00086 'renderHandler' => 'renderAll', 00087 'attrNamesTemplate' => array( 'xhtml:width' => 'width', 00088 'xhtml:colspan' => 'colspan', 00089 'xhtml:rowspan' => 'rowspan', 00090 'class' => 'classification' ), 00091 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00092 00093 'ol' => array( 'renderHandler' => 'renderAll', 00094 'attrNamesTemplate' => array( 'class' => 'classification' ), 00095 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00096 00097 'ul' => array( 'renderHandler' => 'renderAll', 00098 'attrNamesTemplate' => array( 'class' => 'classification' ), 00099 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00100 00101 'li' => array( 'renderHandler' => 'renderAll', 00102 'attrNamesTemplate' => array( 'class' => 'classification' ), 00103 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00104 00105 'header' => array( 'initHandler' => 'initHandlerHeader', 00106 'renderHandler' => 'renderAll', 00107 'attrNamesTemplate' => array( 'class' => 'classification' ), 00108 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00109 00110 'paragraph' => array( //'quickRender' => array( 'p', "\n" ), 00111 'renderHandler' => 'renderParagraph', 00112 'attrNamesTemplate' => array( 'class' => 'classification' ), 00113 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00114 00115 'line' => array( //'quickRender' => array( '', "<br/>" ), 00116 'renderHandler' => 'renderLine' ), 00117 00118 'literal' => array( 'renderHandler' => 'renderAll', 00119 'attrNamesTemplate' => array( 'class' => 'classification' ), 00120 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00121 00122 'strong' => array( 'renderHandler' => 'renderInline', 00123 'attrNamesTemplate' => array( 'class' => 'classification' ), 00124 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00125 00126 'emphasize' => array( 'renderHandler' => 'renderInline', 00127 'attrNamesTemplate' => array( 'class' => 'classification' ), 00128 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00129 00130 'link' => array( 'initHandler' => 'initHandlerLink', 00131 'renderHandler' => 'renderInline', 00132 'attrNamesTemplate' => array( 'xhtml:id' => 'id', 00133 'xhtml:title' => 'title', 00134 'url_id' => false, 00135 'object_id' => false, 00136 'node_id' => false, 00137 'show_path' => false, 00138 'ezurl_id' => false, 00139 'anchor_name' => false, 00140 'class' => 'classification' ), 00141 'attrDesignKeys' => array( 'class' => 'classification' ) ), 00142 00143 'anchor' => array( 'renderHandler' => 'renderInline' ), 00144 00145 'custom' => array( 'initHandler' => 'initHandlerCustom', 00146 'renderHandler' => 'renderCustom', 00147 'attrNamesTemplate' => array( 'name' => false ) ), 00148 00149 '#text' => array( 'quickRender' => true, 00150 'renderHandler' => 'renderText' ) 00151 ); 00152 00153 function eZXHTMLXMLOutput( &$xmlData, $aliasedType, $contentObjectAttribute = null ) 00154 { 00155 $this->eZXMLOutputHandler( $xmlData, $aliasedType, $contentObjectAttribute ); 00156 00157 $ini = eZINI::instance('ezxml.ini'); 00158 if ( $ini->variable( 'ezxhtml', 'RenderParagraphInTableCells' ) == 'disabled' ) 00159 $this->RenderParagraphInTableCells = false; 00160 } 00161 00162 function initHandlerSection( $element, &$attributes, &$siblingParams, &$parentParams ) 00163 { 00164 $ret = array(); 00165 if( !isset( $parentParams['section_level'] ) ) 00166 $parentParams['section_level'] = 0; 00167 else 00168 $parentParams['section_level']++; 00169 00170 // init header counter for current level and for the next level if needed 00171 $level = $parentParams['section_level']; 00172 if ( $level != 0 ) 00173 { 00174 if ( !isset( $this->HeaderCount[$level] ) ) 00175 $this->HeaderCount[$level] = 0; 00176 00177 if ( !isset( $this->HeaderCount[$level + 1] ) ) 00178 $this->HeaderCount[$level + 1] = 0; 00179 } 00180 00181 return $ret; 00182 } 00183 00184 function initHandlerHeader( $element, &$attributes, &$siblingParams, &$parentParams ) 00185 { 00186 $level = $parentParams['section_level']; 00187 $this->HeaderCount[$level]++; 00188 00189 // headers auto-numbering 00190 $i = 1; 00191 $headerAutoName = ''; 00192 while ( $i <= $level ) 00193 { 00194 if ( $i > 1 ) 00195 $headerAutoName .= "_"; 00196 00197 $headerAutoName .= $this->HeaderCount[$i]; 00198 $i++; 00199 } 00200 $levelNumber = str_replace( "_", ".", $headerAutoName ); 00201 00202 if ( $this->ObjectAttributeID ) 00203 $headerAutoName = $this->ObjectAttributeID . '_' . $headerAutoName; 00204 00205 $ret = array( 'tpl_vars' => array( 'level' => $level, 00206 'header_number' => $levelNumber, 00207 'toc_anchor_name' => $headerAutoName ) ); 00208 00209 return $ret; 00210 } 00211 00212 function initHandlerLink( $element, &$attributes, &$siblingParams, &$parentParams ) 00213 { 00214 $ret = array(); 00215 00216 // Set link parameters for rendering children of link tag 00217 $href=''; 00218 if ( $element->getAttribute( 'url_id' ) != null ) 00219 { 00220 $linkID = $element->getAttribute( 'url_id' ); 00221 if ( isset( $this->LinkArray[$linkID] ) ) 00222 $href = $this->LinkArray[$linkID]; 00223 } 00224 elseif ( $element->getAttribute( 'node_id' ) != null ) 00225 { 00226 $nodeID = $element->getAttribute( 'node_id' ); 00227 $node = isset( $this->NodeArray[$nodeID] ) ? $this->NodeArray[$nodeID] : null; 00228 00229 if ( $node != null ) 00230 { 00231 $view = $element->getAttribute( 'view' ); 00232 if ( $view ) 00233 $href = 'content/view/' . $view . '/' . $nodeID; 00234 else 00235 $href = $node->attribute( 'url_alias' ); 00236 } 00237 else 00238 { 00239 eZDebug::writeWarning( "Node #$nodeID doesn't exist", "XML output handler: link" ); 00240 } 00241 } 00242 elseif ( $element->getAttribute( 'object_id' ) != null ) 00243 { 00244 $objectID = $element->getAttribute( 'object_id' ); 00245 if ( isset( $this->ObjectArray["$objectID"] ) ) 00246 { 00247 $object = $this->ObjectArray["$objectID"]; 00248 $node = $object->attribute( 'main_node' ); 00249 if ( $node ) 00250 { 00251 $nodeID = $node->attribute( 'node_id' ); 00252 00253 $view = $element->getAttribute( 'view' ); 00254 if ( $view ) 00255 $href = 'content/view/' . $view . '/' . $nodeID; 00256 else 00257 $href = $node->attribute( 'url_alias' ); 00258 } 00259 else 00260 { 00261 eZDebug::writeWarning( "Object #$objectID doesn't have assigned nodes", "XML output handler: link" ); 00262 } 00263 } 00264 else 00265 { 00266 eZDebug::writeWarning( "Object #$objectID doesn't exist", "XML output handler: link" ); 00267 } 00268 } 00269 elseif ( $element->getAttribute( 'href' ) != null ) 00270 { 00271 $href = $element->getAttribute( 'href' ); 00272 } 00273 00274 if ( $element->getAttribute( 'anchor_name' ) != null ) 00275 { 00276 $href .= '#' . $element->getAttribute( 'anchor_name' ); 00277 } 00278 00279 if ( $href !== false ) 00280 { 00281 $attributes['href'] = $href; 00282 $parentParams['link_parameters'] = $attributes; 00283 } 00284 00285 return $ret; 00286 } 00287 00288 function initHandlerEmbed( $element, &$attributes, &$siblingParams, &$parentParams ) 00289 { 00290 // default return value in case of errors 00291 $ret = array( 'no_render' => true ); 00292 00293 $tplSuffix = ''; 00294 $objectID = $element->getAttribute( 'object_id' ); 00295 if ( $objectID && 00296 !empty( $this->ObjectArray["$objectID"] ) ) 00297 { 00298 $object = $this->ObjectArray["$objectID"]; 00299 } 00300 else 00301 { 00302 $nodeID = $element->getAttribute( 'node_id' ); 00303 if ( $nodeID ) 00304 { 00305 if ( isset( $this->NodeArray[$nodeID] ) ) 00306 { 00307 $node = $this->NodeArray[$nodeID]; 00308 $objectID = $node->attribute( 'contentobject_id' ); 00309 $object = $node->object(); 00310 $tplSuffix = '_node'; 00311 } 00312 else 00313 { 00314 eZDebug::writeWarning( "Node #$nodeID doesn't exist", "XML output handler: embed" ); 00315 return $ret; 00316 } 00317 } 00318 } 00319 00320 if ( !isset( $object ) || !$object || !( $object instanceof eZContentObject ) ) 00321 { 00322 eZDebug::writeWarning( "Can't fetch object #$objectID", "XML output handler: embed" ); 00323 return $ret; 00324 } 00325 if ( $object->attribute( 'status' ) != eZContentObject::STATUS_PUBLISHED ) 00326 { 00327 eZDebug::writeWarning( "Object #$objectID is not published", "XML output handler: embed" ); 00328 return $ret; 00329 } 00330 00331 if ( $object->attribute( 'can_read' ) || 00332 $object->attribute( 'can_view_embed' ) ) 00333 { 00334 $templateName = $element->nodeName . $tplSuffix; 00335 } 00336 else 00337 { 00338 $templateName = $element->nodeName . '_denied'; 00339 } 00340 00341 $objectParameters = array(); 00342 $excludeAttrs = array( 'view', 'class', 'node_id', 'object_id' ); 00343 00344 foreach ( array_keys( $attributes ) as $attrName ) 00345 { 00346 $value = $attributes[$attrName]; 00347 if ( !in_array( $attrName, $excludeAttrs ) ) 00348 { 00349 if ( strpos( $attrName, ':' ) !== false ) 00350 $attrName = substr( $attrName, strpos( $attrName, ':' ) + 1 ); 00351 00352 $objectParameters[$attrName] = $value; 00353 unset( $attributes[$attrName] ); 00354 } 00355 } 00356 00357 if ( isset( $parentParams['link_parameters'] ) ) 00358 $linkParameters = $parentParams['link_parameters']; 00359 else 00360 $linkParameters = array(); 00361 00362 $ret = array( 'template_name' => $templateName, 00363 'tpl_vars' => array( 'object' => $object, 00364 'link_parameters' => $linkParameters, 00365 'object_parameters' => $objectParameters ), 00366 'design_keys' => array( 'class_identifier', $object->attribute( 'class_identifier' ) ) ); 00367 00368 if ( $tplSuffix == '_node') 00369 $ret['tpl_vars']['node'] = $node; 00370 00371 return $ret; 00372 } 00373 00374 function initHandlerTable( $element, &$attributes, &$siblingParams, &$parentParams ) 00375 { 00376 // Numbers of rows and cols are lower by 1 for back-compatibility. 00377 $rows = $element->childNodes; 00378 $rowCount = $rows->length; 00379 $rowCount--; 00380 $lastRow = $element->lastChild; 00381 $cols = $lastRow->childNodes; 00382 $colCount = $cols->length; 00383 if ( $colCount ) 00384 $colCount--; 00385 00386 $ret = array( 'tpl_vars' => array( 'col_count' => $colCount, 00387 'row_count' => $rowCount ) ); 00388 return $ret; 00389 } 00390 00391 function initHandlerTr( $element, &$attributes, &$siblingParams, &$parentParams ) 00392 { 00393 $ret = array(); 00394 if( !isset( $siblingParams['table_row_count'] ) ) 00395 $siblingParams['table_row_count'] = 0; 00396 else 00397 $siblingParams['table_row_count']++; 00398 00399 $parentParams['table_row_count'] = $siblingParams['table_row_count']; 00400 00401 // Number of cols is lower by 1 for back-compatibility. 00402 $cols = $element->childNodes; 00403 $colCount = $cols->length; 00404 if ( $colCount ) 00405 $colCount--; 00406 00407 $ret = array( 'tpl_vars' => array( 'row_count' => $parentParams['table_row_count'], 00408 'col_count' => $colCount ) ); 00409 return $ret; 00410 } 00411 00412 function initHandlerTd( $element, &$attributes, &$siblingParams, &$parentParams ) 00413 { 00414 if( !isset( $siblingParams['table_col_count'] ) ) 00415 $siblingParams['table_col_count'] = 0; 00416 else 00417 $siblingParams['table_col_count']++; 00418 00419 $ret = array( 'tpl_vars' => array( 'col_count' => &$siblingParams['table_col_count'], 00420 'row_count' => &$parentParams['table_row_count'] ) ); 00421 return $ret; 00422 } 00423 00424 function initHandlerCustom( $element, &$attributes, &$siblingParams, &$parentParams ) 00425 { 00426 $ret = array( 'template_name' => $attributes['name'] ); 00427 return $ret; 00428 } 00429 00430 // Render handlers 00431 00432 function renderParagraph( $element, $childrenOutput, $vars ) 00433 { 00434 // don't render if inside 'li' or inside 'td' (by option) 00435 $parent = $element->parentNode; 00436 00437 if ( ( $parent->nodeName == 'li' && $parent->childNodes->length == 1 ) || 00438 ( $parent->nodeName == 'td' && $parent->childNodes->length == 1 && !$this->RenderParagraphInTableCells ) ) 00439 { 00440 return $childrenOutput; 00441 } 00442 00443 // break paragraph by block tags 00444 $tagText = ''; 00445 $lastTagInline = null; 00446 $inlineContent = ''; 00447 foreach( $childrenOutput as $key=>$childOutput ) 00448 { 00449 if ( $childOutput[0] === true ) 00450 $inlineContent .= $childOutput[1]; 00451 00452 if ( ( $childOutput[0] === false && $lastTagInline === true ) || 00453 ( $childOutput[0] === true && !array_key_exists( $key + 1, $childrenOutput ) ) ) 00454 { 00455 $tagText .= $this->renderTag( $element, $inlineContent, $vars ); 00456 $inlineContent = ''; 00457 } 00458 00459 if ( $childOutput[0] === false ) 00460 $tagText .= $childOutput[1]; 00461 00462 $lastTagInline = $childOutput[0]; 00463 } 00464 return array( false, $tagText ); 00465 } 00466 00467 function renderInline( $element, $childrenOutput, $vars ) 00468 { 00469 $renderedArray = array(); 00470 $lastTagInline = null; 00471 $inlineContent = ''; 00472 00473 foreach( $childrenOutput as $key=>$childOutput ) 00474 { 00475 if ( $childOutput[0] === true ) 00476 $inlineContent .= $childOutput[1]; 00477 00478 // Render only inline parts, block parts just passed to parent 00479 if ( ( $childOutput[0] === false && $lastTagInline === true ) || 00480 ( $childOutput[0] === true && !array_key_exists( $key + 1, $childrenOutput ) ) ) 00481 { 00482 $tagText = $this->renderTag( $element, $inlineContent, $vars ); 00483 $renderedArray[] = array( true, $tagText ); 00484 $inlineContent = ''; 00485 } 00486 00487 if ( $childOutput[0] === false ) 00488 $renderedArray[] = array( false, $childOutput[1] ); 00489 00490 $lastTagInline = $childOutput[0]; 00491 00492 } 00493 return $renderedArray; 00494 } 00495 00496 function renderLine( $element, $childrenOutput, $vars ) 00497 { 00498 $renderedArray = array(); 00499 $lastTagInline = null; 00500 $inlineContent = ''; 00501 00502 foreach( $childrenOutput as $key=>$childOutput ) 00503 { 00504 if ( $childOutput[0] === true ) 00505 $inlineContent .= $childOutput[1]; 00506 00507 // Render line tag only if the last part of childrenOutput is inline and the next tag 00508 // within the same paragraph is 'line' too. 00509 00510 if ( $childOutput[0] === false && $lastTagInline === true ) 00511 { 00512 $renderedArray[] = array( true, $inlineContent ); 00513 $inlineContent = ''; 00514 } 00515 elseif ( $childOutput[0] === true && !array_key_exists( $key + 1, $childrenOutput ) ) 00516 { 00517 $next = $element->nextSibling; 00518 if ( $next && $next->nodeName == 'line' ) 00519 { 00520 $tagText = $this->renderTag( $element, $inlineContent, $vars ); 00521 $renderedArray[] = array( true, $tagText ); 00522 } 00523 else 00524 $renderedArray[] = array( true, $inlineContent ); 00525 } 00526 00527 if ( $childOutput[0] === false ) 00528 $renderedArray[] = array( false, $childOutput[1] ); 00529 00530 $lastTagInline = $childOutput[0]; 00531 } 00532 return $renderedArray; 00533 } 00534 00535 function renderCustom( $element, $childrenOutput, $vars ) 00536 { 00537 if ( $this->XMLSchema->isInline( $element ) ) 00538 { 00539 $ret = $this->renderInline( $element, $childrenOutput, $vars ); 00540 } 00541 else 00542 { 00543 $ret = $this->renderAll( $element, $childrenOutput, $vars ); 00544 } 00545 return $ret; 00546 } 00547 00548 function renderChildrenOnly( $element, $childrenOutput, $vars ) 00549 { 00550 $tagText = ''; 00551 foreach( $childrenOutput as $childOutput ) 00552 { 00553 $tagText .= $childOutput[1]; 00554 } 00555 00556 return array( false, $tagText ); 00557 } 00558 00559 function renderText( $element, $childrenOutput, $vars ) 00560 { 00561 if ( $element->parentNode->nodeName != 'literal' ) 00562 { 00563 $text = htmlspecialchars( $element->textContent ); 00564 // Get rid of linebreak and spaces stored in xml file 00565 $text = preg_replace( "#[\n]+#", "", $text ); 00566 00567 if ( $this->AllowMultipleSpaces ) 00568 $text = preg_replace( "# #", " ", $text ); 00569 else 00570 $text = preg_replace( "# +#", " ", $text ); 00571 00572 if ( $this->AllowNumericEntities ) 00573 $text = preg_replace( '/&#([0-9]+);/', '&#\1;', $text ); 00574 } 00575 else 00576 { 00577 $text = $element->textContent; 00578 } 00579 00580 return array( true, $text ); 00581 } 00582 00583 00584 /// Array of parameters for rendering tags that are children of 'link' tag 00585 public $LinkParameters = array(); 00586 00587 public $HeaderCount = array(); 00588 00589 public $RenderParagraphInTableCells = true; 00590 } 00591 00592 ?>