|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZSimplifiedXMLEditOutput class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package kernel 00009 */ 00010 00011 // if ( !class_exists( 'eZXMLSchema' ) ) 00012 class eZSimplifiedXMLEditOutput 00013 { 00014 public $OutputTags = array( 00015 00016 'section' => array( 'handler' => 'outputSection' ), 00017 00018 'embed' => array( 'handler' => 'outputEmbed', 00019 'attributes' => array( 'xhtml:id' => 'id', 00020 'object_id' => false, 00021 'node_id' => false, 00022 'show_path' => false ), 00023 'isSingle' => true ), 00024 00025 'embed-inline' => array( 'handler' => 'outputEmbed', 00026 'attributes' => array( 'xhtml:id' => 'id', 00027 'object_id' => false, 00028 'node_id' => false, 00029 'show_path' => false ), 00030 'isSingle' => true ), 00031 00032 'object' => array( 'handler' => 'outputObject', 00033 'attributes' => array( 'xhtml:id' => 'id', 00034 'image:ezurl_target' => 'target', 00035 'image:ezurl_href' => 'href', 00036 'image:ezurl_id' => false ), 00037 'isSingle' => true ), 00038 00039 'td' => array( 'handler' => 'outputTd', 00040 'attributes' => array( 'xhtml:width' => 'width', 00041 'xhtml:colspan' => 'colspan', 00042 'xhtml:rowspan' => 'rowspan' ) ), 00043 00044 'th' => array( 'handler' => 'outputTd', 00045 'attributes' => array( 'xhtml:width' => 'width', 00046 'xhtml:colspan' => 'colspan', 00047 'xhtml:rowspan' => 'rowspan' ) ), 00048 00049 'header' => array( 'handler' => 'outputHeader' ), 00050 00051 'paragraph' => array( 'handler' => 'outputParagraph' ), 00052 00053 'line' => array( 'handler' => 'outputLine' ), 00054 00055 'link' => array( 'handler' => 'outputLink', 00056 'attributes' => array( 'xhtml:id' => 'id', 00057 'xhtml:title' => 'title', 00058 'url_id' => false, 00059 'object_id' => false, 00060 'node_id' => false, 00061 'show_path' => false, 00062 'ezurl_id' => false, 00063 'anchor_name' => false ) ), 00064 'anchor' => array( 'isSingle' => true ), 00065 00066 '#text' => array( 'handler' => 'outputText' ) 00067 ); 00068 00069 // Call this function to obtain edit output string 00070 00071 function performOutput( $dom ) 00072 { 00073 $this->XMLSchema = eZXMLSchema::instance(); 00074 $this->NestingLevel = 0; 00075 $this->Output = ''; 00076 $sectionLevel = -1; 00077 00078 $this->createLinksArray( $dom ); 00079 00080 $this->outputTag( $dom->documentElement, $sectionLevel ); 00081 00082 return $this->Output; 00083 } 00084 00085 function outputTag( $element, $sectionLevel ) 00086 { 00087 $tagName = $element->nodeName; 00088 if ( isset( $this->OutputTags[$tagName] ) ) 00089 { 00090 $currentTag = $this->OutputTags[$tagName]; 00091 00092 if ( isset( $currentTag['attributes'] ) ) 00093 $attributeRules = $currentTag['attributes']; 00094 } 00095 else 00096 { 00097 $currentTag = null; 00098 } 00099 00100 //eZDebugSetting::writeDebug( 'kernel-datatype-ezxmltext', 'outputting tag ' . $element->nodeName ); 00101 00102 // Prepare attributes array 00103 00104 $attributes = array(); 00105 00106 if ( $element->hasAttributes() ) 00107 { 00108 $attributeNodes = $element->attributes; 00109 00110 foreach ( $attributeNodes as $attrNode ) 00111 { 00112 if ( $attrNode->prefix && $attrNode->prefix != 'custom' ) 00113 { 00114 $attrName = $attrNode->prefix . ':' . $attrNode->localName; 00115 } 00116 else 00117 { 00118 $attrName = $attrNode->nodeName; 00119 } 00120 00121 $attributes[$attrName] = $attrNode->value; 00122 } 00123 } 00124 00125 // Call tag handler 00126 $result = null; 00127 if ( $currentTag && isset( $currentTag['handler'] ) ) 00128 { 00129 $result = $this->callOutputHandler( 'handler', $element, $attributes, $sectionLevel ); 00130 } 00131 00132 $hasChildren = $element->hasChildNodes(); 00133 $isInline = $this->XMLSchema->isInline( $element ); 00134 //eZDebugSetting::writeDebug( 'kernel-datatype-ezxmltext', $isInline ? 'yes' : 'no', 'is inline element?' ); 00135 $isSingle = isset( $currentTag['isSingle'] ) && $currentTag['isSingle']; 00136 //eZDebugSetting::writeDebug( 'kernel-datatype-ezxmltext', $isSingle ? 'yes' : 'no', 'is single element?' ); 00137 00138 // If output was not set by handler, do a normal tag output 00139 if ( !is_string( $result ) ) 00140 { 00141 // Convert (if needed) and output attributes 00142 $attrString = ''; 00143 foreach ( array_keys( $attributes ) as $name ) 00144 { 00145 $value = $attributes[$name]; 00146 if ( isset( $attributeRules ) && isset( $attributeRules[$name] ) ) 00147 { 00148 if ( !$attributeRules[$name] ) 00149 continue; 00150 00151 $name = $attributeRules[$name]; 00152 } 00153 $attrString .= ' ' . $name . '="' . $value . '"'; 00154 } 00155 00156 $this->formatBeforeOpeningTag( $element, $isInline, $hasChildren ); 00157 00158 //Output opening tag 00159 $closing = $isSingle ? ' />' : '>'; 00160 00161 $this->Output .= '<' . $tagName . $attrString . $closing; 00162 00163 if ( !$isSingle ) 00164 { 00165 $this->formatAfterOpeningTag( $element, $isInline, $hasChildren ); 00166 } 00167 00168 $this->NestingLevel++; 00169 00170 //eZDebugSetting::writeDebug( 'kernel-datatype-ezxmltext', $this->Output, 'output so far' ); 00171 } 00172 00173 if ( $element->hasChildNodes() ) 00174 { 00175 // Process children 00176 foreach ( $element->childNodes as $child ) 00177 { 00178 $this->outputTag( $child, $sectionLevel ); 00179 } 00180 } 00181 00182 if ( is_string( $result ) ) 00183 { 00184 $this->Output .= $result; 00185 return; 00186 } 00187 else 00188 { 00189 $this->NestingLevel--; 00190 if ( !$isSingle ) 00191 { 00192 $this->formatBeforeClosingTag( $element, $isInline, $hasChildren ); 00193 00194 $this->Output .= '</' . $tagName . '>'; 00195 } 00196 00197 $this->formatAfterClosingTag( $element, $isInline, $hasChildren ); 00198 } 00199 00200 return; 00201 } 00202 00203 function formatBeforeOpeningTag( $element, $isInline, $hasChildren ) 00204 { 00205 // Add indenting for block tags 00206 if ( !$isInline ) 00207 { 00208 if ( $this->NestingLevel > 0 ) 00209 { 00210 $this->Output .= str_repeat( ' ', $this->NestingLevel ); 00211 } 00212 } 00213 } 00214 00215 function formatAfterOpeningTag( $element, $isInline, $hasChildren ) 00216 { 00217 // Add linebreak in case we have block tag as a first child 00218 if ( !$isInline && $hasChildren ) 00219 { 00220 $firstChild = $element->firstChild; 00221 if ( $firstChild && $firstChild->nodeName == 'paragraph' && !$firstChild->hasAttributes() ) 00222 { 00223 $firstChild = $firstChild->firstChild; 00224 } 00225 if ( $firstChild && $firstChild->nodeName == 'line' ) 00226 { 00227 $firstChild = $firstChild->firstChild; 00228 } 00229 if ( $firstChild && !$this->XMLSchema->isInline( $firstChild ) ) 00230 { 00231 $this->Output .= "\n"; 00232 } 00233 } 00234 } 00235 00236 function formatBeforeClosingTag( $element, $isInline, $hasChildren ) 00237 { 00238 if ( !$isInline && $hasChildren ) 00239 { 00240 $lastChild = $element->lastChild; 00241 if ( $lastChild && $lastChild->nodeName == 'paragraph' && !$lastChild->hasAttributes() ) 00242 { 00243 $lastChild = $lastChild->lastChild; 00244 } 00245 if ( $lastChild && $lastChild->nodeName == 'line' ) 00246 { 00247 $lastChild = $lastChild->lastChild; 00248 } 00249 if ( $lastChild && !$this->XMLSchema->isInline( $lastChild ) ) 00250 { 00251 // Add line breaks and indenting for block tags 00252 $this->Output .= "\n"; 00253 if ( $this->NestingLevel > 0 ) 00254 { 00255 $this->Output .= str_repeat( ' ', $this->NestingLevel ); 00256 } 00257 } 00258 } 00259 } 00260 00261 function formatAfterClosingTag( $element, $isInline, $hasChildren ) 00262 { 00263 if ( !$isInline ) 00264 { 00265 $next = $element->nextSibling; 00266 if ( $next ) 00267 { 00268 $this->Output .= "\n"; 00269 } 00270 else 00271 { 00272 $parent = $element->parentNode; 00273 while( $parent && $parent->nodeName == 'section' ) 00274 { 00275 $next = $parent->nextSibling; 00276 if ( $next ) 00277 { 00278 $this->Output .= "\n"; 00279 break; 00280 } 00281 $parent = $parent->parentNode; 00282 } 00283 } 00284 } 00285 } 00286 00287 function callOutputHandler( $handlerName, $element, &$params, &$sectionLevel ) 00288 { 00289 $result = null; 00290 $thisOutputTag = $this->OutputTags[$element->nodeName]; 00291 if ( isset( $thisOutputTag[$handlerName] ) ) 00292 { 00293 if ( is_callable( array( $this, $thisOutputTag[$handlerName] ) ) ) 00294 { 00295 $result = call_user_func_array( array( $this, $thisOutputTag[$handlerName] ), 00296 array( $element, &$params, &$sectionLevel ) ); 00297 } 00298 else 00299 { 00300 eZDebug::writeWarning( "'$handlerName' output handler for tag <$element->nodeName> doesn't exist: '" . $thisOutputTag[$handlerName] . "'.", 'eZXML converter' ); 00301 } 00302 } 00303 return $result; 00304 } 00305 00306 /* 00307 Tag handlers 00308 */ 00309 function outputSection( $element, &$attributes, &$sectionLevel ) 00310 { 00311 $sectionLevel++; 00312 00313 $ret = ''; 00314 return $ret; 00315 } 00316 00317 function outputText( $element, &$attributes, &$sectionLevel ) 00318 { 00319 $text = $element->textContent; 00320 00321 if ( $element->parentNode->nodeName != 'literal' ) 00322 { 00323 $text = htmlspecialchars( $text ); 00324 $text = str_replace ( '&nbsp;', ' ', $text); 00325 $text = str_replace( "\n", '', $text ); 00326 } 00327 return $text; 00328 } 00329 00330 function outputTd( $element, &$attributes, &$sectionLevel ) 00331 { 00332 $ret = null; 00333 00334 // We have to reset section level in the table cell 00335 $sectionLevel = 0; 00336 return $ret; 00337 } 00338 00339 function outputHeader( $element, &$attributes, &$sectionLevel ) 00340 { 00341 $ret = null; 00342 $attributes['level'] = $sectionLevel; 00343 return $ret; 00344 } 00345 00346 function outputParagraph( $element, &$attributes, &$sectionLevel ) 00347 { 00348 $ret = null; 00349 if ( count( $attributes ) == 0 ) 00350 { 00351 $next = $element->nextSibling; 00352 if ( $next ) 00353 { 00354 $ret = "\n\n"; 00355 } 00356 else 00357 { 00358 $ret = ""; 00359 $parent = $element->parentNode; 00360 while( $parent && $parent->nodeName == 'section' ) 00361 { 00362 $next = $parent->nextSibling; 00363 if ( $next ) 00364 { 00365 $ret = "\n\n"; 00366 break; 00367 } 00368 $parent = $parent->parentNode; 00369 } 00370 } 00371 } 00372 return $ret; 00373 } 00374 00375 function outputLine( $element, &$attributes, &$sectionLevel ) 00376 { 00377 $ret = ''; 00378 $next = $element->nextSibling; 00379 if ( is_object( $next ) ) 00380 { 00381 $ret = "\n"; 00382 } 00383 return $ret; 00384 } 00385 00386 function outputEmbed( $element, &$attributes, &$sectionLevel ) 00387 { 00388 $ret = null; 00389 $href = ''; 00390 $objectID = isset( $attributes['object_id'] ) ? $attributes['object_id'] : null; 00391 $nodeID = isset( $attributes['node_id'] ) ? $attributes['node_id'] : null; 00392 $showPath = isset( $attributes['show_path'] ) ? $attributes['show_path'] : null; 00393 if ( $objectID ) 00394 { 00395 $href = 'ezobject://' .$objectID; 00396 } 00397 elseif ( $nodeID ) 00398 { 00399 $href = eZSimplifiedXMLEditOutput::eznodeHref( $nodeID, $showPath ); 00400 } 00401 $attributes['href'] = $href; 00402 return $ret; 00403 } 00404 00405 function outputObject( $element, &$attributes, &$sectionLevel ) 00406 { 00407 $ret = null; 00408 if ( isset( $attributes['image:ezurl_id'] ) ) 00409 { 00410 $linkID = $attributes['image:ezurl_id']; 00411 if ( $linkID != null ) 00412 { 00413 $href = eZURL::url( $linkID ); 00414 $attributes['href'] = $href; 00415 } 00416 } 00417 return $ret; 00418 } 00419 00420 function outputLink( $element, &$attributes, &$sectionLevel ) 00421 { 00422 $ret = null; 00423 $href = ''; 00424 $linkID = isset( $attributes['url_id'] ) ? $attributes['url_id'] : null; 00425 $objectID = isset( $attributes['object_id'] ) ? $attributes['object_id'] : null; 00426 $nodeID = isset( $attributes['node_id'] ) ? $attributes['node_id'] : null; 00427 $anchorName = isset( $attributes['anchor_name'] ) ? $attributes['anchor_name'] : null; 00428 $showPath = isset( $attributes['show_path'] ) ? $attributes['show_path'] : null; 00429 00430 if ( $objectID ) 00431 { 00432 $href = 'ezobject://' .$objectID; 00433 } 00434 elseif ( $nodeID ) 00435 { 00436 $href = eZSimplifiedXMLEditOutput::eznodeHref( $nodeID, $showPath ); 00437 } 00438 elseif ( $linkID ) 00439 { 00440 // Fetch URL from cached array 00441 $href = $this->LinkArray[$linkID]; 00442 } 00443 else 00444 { 00445 $href = isset( $attributes['href'] ) ? $attributes['href'] : ''; 00446 } 00447 00448 if ( $anchorName != null ) 00449 { 00450 $href .= '#' . $anchorName; 00451 } 00452 00453 $attributes['href'] = $href; 00454 return $ret; 00455 } 00456 00457 /*! 00458 Helper function to generate the href attribute value for the eznode:// protocol 00459 */ 00460 static function eznodeHref( $nodeID, $showPath ) 00461 { 00462 if ( $showPath == 'true' ) 00463 { 00464 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false ); 00465 $href = $node ? 'eznode://' . $node['path_identification_string'] : 'eznode://' . $nodeID; 00466 } 00467 else 00468 { 00469 $href = 'eznode://' . $nodeID; 00470 } 00471 00472 return $href; 00473 } 00474 00475 /*! 00476 Helper function to prepare links array 00477 */ 00478 function createLinksArray( $dom ) 00479 { 00480 $links = array(); 00481 $node = array(); 00482 00483 if ( $dom ) 00484 { 00485 // Fetch all links and cache the url's 00486 $links = $dom->getElementsByTagName( "link" ); 00487 } 00488 00489 $linkIDArray = array(); 00490 // Find all Link id's 00491 foreach ( $links as $link ) 00492 { 00493 $linkIDValue = $link->getAttribute( 'url_id' ); 00494 if ( !$linkIDValue ) 00495 { 00496 continue; 00497 } 00498 if ( !in_array( $linkIDValue, $linkIDArray ) ) 00499 { 00500 $linkIDArray[] = $linkIDValue; 00501 } 00502 } 00503 00504 if ( count( $linkIDArray ) > 0 ) 00505 { 00506 $inIDSQL = implode( ', ', $linkIDArray ); 00507 $db = eZDB::instance(); 00508 $linkArray = $db->arrayQuery( "SELECT * FROM ezurl WHERE id IN ( $inIDSQL ) " ); 00509 foreach ( $linkArray as $linkRow ) 00510 { 00511 $this->LinkArray[$linkRow['id']] = $linkRow['url']; 00512 } 00513 } 00514 } 00515 00516 public $XMLSchema; 00517 public $Output = ''; 00518 public $NestingLevel = 0; 00519 00520 // Contains all links hashed by ID 00521 public $LinkArray = array(); 00522 } 00523 ?>