|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZXMLTextType class 00004 // 00005 // Created on: <06-May-2002 20:02:55 bf> 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 \class eZXMLTextType ezxmltexttype 00033 \ingroup eZDatatype 00034 \brief The class eZXMLTextType haneles XML formatted datatypes 00035 00036 The formatted datatypes store the data in XML. A typical example of this is shown below: 00037 \code 00038 <?xml version="1.0" encoding="utf-8" ?> 00039 <section xmlns:image="http://ez.no/namespaces/ezpublish3/image/" 00040 xmlns:xhtml="http://ez.no/namespaces/ezpublish3/xhtml/"> 00041 <header>This is a level one header</header> 00042 <paragraph> 00043 This is a <emphasize>block</emphasize> of text. 00044 </paragraph> 00045 <section> 00046 <header class="foo">This is a level two header has classification "foo"</header> 00047 <paragraph> 00048 This is the second paragraph with <bold class="foo">bold text which has classification "foo"</bold> 00049 </paragraph> 00050 <header>This is a level two header</header> 00051 <paragraph> 00052 <line>Paragraph can have table</line> 00053 <table class="foo" border='1' width='100%'> 00054 <tr> 00055 <th class="foo"><paragraph>table header of class "foo"</paragraph></th> 00056 <td xhtml:width="66" xhtml:colspan="2" xhtml:rowspan="2"> 00057 <paragraph>table cell text</paragraph> 00058 </td> 00059 </tr> 00060 </table> 00061 </paragraph> 00062 <paragraph> 00063 <line>This is the first line with <anchor name="first">anchor</anchor></line> 00064 <line>This is the second line with <link target="_self" id="1">link</link></line> 00065 <line>This is the third line.</line> 00066 </paragraph> 00067 <paragraph> 00068 <ul class="foo"> 00069 <li>List item 1</li> 00070 <li>List item 2</li> 00071 </ul> 00072 </paragraph> 00073 <paragraph> 00074 <ol> 00075 <li>Ordered list item 1</li> 00076 <li>ordered list item 2</li> 00077 </ol> 00078 </paragraph> 00079 <paragraph> 00080 <line>Paragraph can have both inline custom tag <custom name="myInlineTag">text</custom> and block custom tag</line> 00081 <custom name="myBlockTag"> 00082 <paragraph> 00083 block text 00084 </paragraph> 00085 </custom> 00086 </paragraph> 00087 <paragraph> 00088 Paragraph can have image object with link <object id="55" size="large" align="center" image:ezurl_id="4" /> 00089 </paragraph> 00090 <paragraph> 00091 You can use literal tag to write html code if you have done some changes in override system. 00092 <literal class="html"><font color="red">red text</font></literal> 00093 </paragraph> 00094 <header>This is a level two header</header> 00095 </section> 00096 </section> 00097 00098 \endcode 00099 00100 */ 00101 00102 //include_once( "kernel/classes/ezdatatype.php" ); 00103 require_once( "kernel/common/template.php" ); 00104 //include_once( 'lib/eztemplate/classes/eztemplateincludefunction.php' ); 00105 //include_once( 'kernel/classes/datatypes/ezurl/ezurl.php' ); 00106 //include_once( 'kernel/classes/datatypes/ezurl/ezurlobjectlink.php' ); 00107 //include_once( "lib/ezutils/classes/ezini.php" ); 00108 00109 class eZXMLTextType extends eZDataType 00110 { 00111 const DATA_TYPE_STRING = "ezxmltext"; 00112 const COLS_FIELD = 'data_int1'; 00113 const COLS_VARIABLE = '_ezxmltext_cols_'; 00114 00115 // The timestamp of the format for eZ Publish 3.0. 00116 const VERSION_30_TIMESTAMP = 1045487555; 00117 // Contains the timestamp of the current xml format, if the stored 00118 // timestamp is less than this it needs to be upgraded until it is correct. 00119 const VERSION_TIMESTAMP = 1045487555; // AS 21-09-2007: should be the same as VERSION_30_TIMESTAMP 00120 00121 function eZXMLTextType() 00122 { 00123 $this->eZDataType( self::DATA_TYPE_STRING, ezi18n( 'kernel/classes/datatypes', "XML block", 'Datatype name' ), 00124 array( 'serialize_supported' => true ) ); 00125 } 00126 00127 /*! 00128 Set class attribute value for template version 00129 */ 00130 function initializeClassAttribute( $classAttribute ) 00131 { 00132 if ( $classAttribute->attribute( self::COLS_FIELD ) == null ) 00133 $classAttribute->setAttribute( self::COLS_FIELD, 10 ); 00134 $classAttribute->store(); 00135 } 00136 00137 /*! 00138 Sets the default value. 00139 */ 00140 function initializeObjectAttribute( $contentObjectAttribute, $currentVersion, $originalContentObjectAttribute ) 00141 { 00142 if ( $currentVersion != false ) 00143 { 00144 $xmlText = eZXMLTextType::rawXMLText( $originalContentObjectAttribute ); 00145 $contentObjectAttribute->setAttribute( "data_text", $xmlText ); 00146 } 00147 else 00148 { 00149 //include_once( 'kernel/classes/datatypes/ezxmltext/ezxmlinputparser.php' ); 00150 $parser = new eZXMLInputParser(); 00151 $doc = $parser->createRootNode(); 00152 $xmlText = eZXMLTextType::domString( $doc ); 00153 $contentObjectAttribute->setAttribute( "data_text", $xmlText ); 00154 } 00155 } 00156 00157 /** 00158 * Method triggered on publish for xml text datatype 00159 * 00160 * This method makes sure that links from all translations of an xml text 00161 * are registered in the ezurl_object_link table, and thus retained, if 00162 * previous versions of an object are removed. 00163 * 00164 * @param eZContentObjectAttribute $contentObjectAttribute 00165 * @param eZContentObject $object 00166 * @param array $publishedNodes 00167 * @return boolean 00168 */ 00169 function onPublish( $contentObjectAttribute, $object, $publishedNodes ) 00170 { 00171 $currentVersion = $object->currentVersion(); 00172 $langMask = $currentVersion->attribute( 'language_mask' ); 00173 00174 // We find all translations present in the current version. We calculate 00175 // this from the language mask already present in the fetched version, 00176 // so no further round-trip to the DB is required. 00177 $languageList = eZContentLanguage::decodeLanguageMask( $langMask, true ); 00178 $languageList = $languageList['language_list']; 00179 00180 // We want to have the class attribute identifier of the attribute 00181 // containing the current ezxmltext, as we then can use the more efficient 00182 // eZContentObject->fetchAttributesByIdentifier() to get the data 00183 $identifier = $contentObjectAttribute->attribute( 'contentclass_attribute_identifier' ); 00184 00185 $attributeArray = $object->fetchAttributesByIdentifier( array( $identifier ), 00186 $currentVersion->attribute( 'version' ), 00187 $languageList ); 00188 00189 foreach ( $attributeArray as $attr ) 00190 { 00191 $xmlText = eZXMLTextType::rawXMLText( $attr ); 00192 $dom = new DOMDocument( '1.0', 'utf-8' ); 00193 $success = $dom->loadXML( $xmlText ); 00194 00195 if ( !$success ) 00196 { 00197 continue; 00198 } 00199 00200 $linkNodes = $dom->getElementsByTagName( 'link' ); 00201 $urlIdArray = array(); 00202 00203 foreach ( $linkNodes as $link ) 00204 { 00205 // We are looking for external 'http://'-style links, not the internal 00206 // object or node links. 00207 if ( $link->hasAttribute( 'url_id' ) ) 00208 { 00209 $urlIdArray[] = $link->getAttribute( 'url_id' ); 00210 } 00211 } 00212 00213 if ( count( $urlIdArray ) > 0 ) 00214 { 00215 eZSimplifiedXMLInput::updateUrlObjectLinks( $attr, $urlIdArray ); 00216 } 00217 } 00218 } 00219 00220 /*! 00221 Validates the input and returns true if the input was 00222 valid for this datatype. 00223 */ 00224 function validateObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute ) 00225 { 00226 /// Get object for input validation 00227 // To do: only validate, not save data 00228 $xmlText = $this->objectAttributeContent( $contentObjectAttribute ); 00229 $input = $xmlText->attribute( 'input' ); 00230 $isValid = $input->validateInput( $http, $base, $contentObjectAttribute ); 00231 00232 return $isValid; 00233 } 00234 00235 function fetchClassAttributeHTTPInput( $http, $base, $classAttribute ) 00236 { 00237 $column = $base . self::COLS_VARIABLE . $classAttribute->attribute( 'id' ); 00238 if ( $http->hasPostVariable( $column ) ) 00239 { 00240 $columnValue = $http->postVariable( $column ); 00241 $classAttribute->setAttribute( self::COLS_FIELD, $columnValue ); 00242 return true; 00243 } 00244 return false; 00245 } 00246 00247 /*! 00248 Fetches the http post var string input and stores it in the data instance. 00249 */ 00250 function fetchObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute ) 00251 { 00252 // To do: Data should be saved here. 00253 /*$xmlText = $this->objectAttributeContent( $contentObjectAttribute ); 00254 $input = $xmlText->attribute( 'input' ); 00255 $isValid = $input->validateInput( $http, $base, $contentObjectAttribute );*/ 00256 return true; 00257 } 00258 00259 /*! 00260 Initializes the object attribute with some data after object attribute is already stored. 00261 It means that for initial version you allready have an attribute_id and you can store data somewhere using this id. 00262 \note Default implementation does nothing. 00263 */ 00264 function postInitializeObjectAttribute( $objectAttribute, $currentVersion, $originalContentObjectAttribute ) 00265 { 00266 } 00267 00268 /*! 00269 Store the content. 00270 */ 00271 function storeObjectAttribute( $attribute ) 00272 { 00273 $attribute->setAttribute( 'data_int', self::VERSION_TIMESTAMP ); 00274 } 00275 00276 /*! 00277 \reimp 00278 */ 00279 function viewTemplate( $contentobjectAttribute ) 00280 { 00281 $template = $this->DataTypeString; 00282 $suffix = $this->viewTemplateSuffix( $contentobjectAttribute ); 00283 if ( $suffix ) 00284 { 00285 $template .= '_' . $suffix; 00286 } 00287 return $template; 00288 } 00289 00290 /*! 00291 \reimp 00292 */ 00293 function editTemplate( $contentobjectAttribute ) 00294 { 00295 $template = $this->DataTypeString; 00296 $suffix = $this->editTemplateSuffix( $contentobjectAttribute ); 00297 if ( $suffix ) 00298 $template .= '_' . $suffix; 00299 return $template; 00300 } 00301 00302 /*! 00303 \reimp 00304 */ 00305 function informationTemplate( $contentobjectAttribute ) 00306 { 00307 $template = $this->DataTypeString; 00308 $suffix = $this->informationTemplateSuffix( $contentobjectAttribute ); 00309 if ( $suffix ) 00310 $template .= '_' . $suffix; 00311 return $template; 00312 } 00313 00314 /*! 00315 \reimp 00316 */ 00317 function viewTemplateSuffix( &$contentobjectAttribute ) 00318 { 00319 $content = $this->objectAttributeContent( $contentobjectAttribute ); 00320 $outputHandler = $content->attribute( 'output' ); 00321 return $outputHandler->viewTemplateSuffix( $contentobjectAttribute ); 00322 } 00323 00324 /*! 00325 \reimp 00326 */ 00327 function editTemplateSuffix( &$contentobjectAttribute ) 00328 { 00329 $content = $this->objectAttributeContent( $contentobjectAttribute ); 00330 $inputHandler = $content->attribute( 'input' ); 00331 return $inputHandler->editTemplateSuffix( $contentobjectAttribute ); 00332 } 00333 00334 /*! 00335 \reimp 00336 */ 00337 function informationTemplateSuffix( &$contentobjectAttribute ) 00338 { 00339 $content = $this->objectAttributeContent( $contentobjectAttribute ); 00340 $inputHandler = $content->attribute( 'input' ); 00341 return $inputHandler->informationTemplateSuffix( $contentobjectAttribute ); 00342 } 00343 00344 /*! 00345 \return the RAW XML text from the attribute \a $contentobjectAttribute. 00346 If the XML format is older than the current one it will 00347 be upgraded to the current before being returned. 00348 */ 00349 static function rawXMLText( $contentObjectAttribute ) 00350 { 00351 $text = $contentObjectAttribute->attribute( 'data_text' ); 00352 $timestamp = $contentObjectAttribute->attribute( 'data_int' ); 00353 if ( $timestamp < self::VERSION_30_TIMESTAMP ) 00354 { 00355 //include_once( 'lib/ezi18n/classes/eztextcodec.php' ); 00356 $charset = 'UTF-8'; 00357 $codec = eZTextCodec::instance( false, $charset ); 00358 $text = $codec->convertString( $text ); 00359 $timestamp = self::VERSION_30_TIMESTAMP; 00360 } 00361 return $text; 00362 } 00363 00364 /*! 00365 \static 00366 \return the XML structure in \a $domDocument as text. 00367 It will take of care of the necessary charset conversions 00368 for content storage. 00369 */ 00370 static function domString( $domDocument ) 00371 { 00372 return $domDocument->saveXML(); 00373 } 00374 00375 /*! 00376 Returns the content. 00377 */ 00378 function objectAttributeContent( $contentObjectAttribute ) 00379 { 00380 //include_once( 'kernel/classes/datatypes/ezxmltext/ezxmltext.php' ); 00381 $xmlText = new eZXMLText( eZXMLTextType::rawXMLText( $contentObjectAttribute ), $contentObjectAttribute ); 00382 return $xmlText; 00383 } 00384 00385 /*! 00386 Returns the meta data used for storing search indeces. 00387 */ 00388 function metaData( $contentObjectAttribute ) 00389 { 00390 $metaData = ""; 00391 00392 $dom = new DOMDocument( '1.0', 'utf-8' ); 00393 $text = eZXMLTextType::rawXMLText( $contentObjectAttribute ); 00394 if ( trim( $text ) == '' ) 00395 { 00396 return $metaData; 00397 } 00398 $success = $dom->loadXML( $text ); 00399 00400 if ( $success ) 00401 { 00402 $metaData = trim( eZXMLTextType::concatTextContent( $dom->documentElement ) ); 00403 } 00404 return $metaData; 00405 } 00406 00407 /** 00408 * Recursively drills down in the xml tree in $node and 00409 * concatenates text content from the DOMNodes with a space 00410 * in-between to make sure search words from two different lines 00411 * are merged. 00412 * 00413 * @param DOMNode $node 00414 * @return string 00415 */ 00416 static function concatTextContent( $node ) 00417 { 00418 $retString = ''; 00419 if ( !( $node instanceof DOMNode ) ) 00420 { 00421 return $retString; 00422 } 00423 if ( $node->hasChildNodes() ) 00424 { 00425 $childArray = $node->childNodes; 00426 foreach ( $childArray as $child ) 00427 { 00428 $retString .= eZXMLTextType::concatTextContent( $child ); 00429 } 00430 } 00431 elseif ( $node->nodeType === XML_TEXT_NODE ) 00432 { 00433 return $node->textContent . ' '; 00434 } 00435 return $retString; 00436 } 00437 00438 /*! 00439 \return string representation of an contentobjectattribute data for simplified export 00440 00441 */ 00442 function toString( $contentObjectAttribute ) 00443 { 00444 return $contentObjectAttribute->attribute( 'data_text' ); 00445 } 00446 00447 function fromString( $contentObjectAttribute, $string ) 00448 { 00449 return $contentObjectAttribute->setAttribute( 'data_text', $string ); 00450 } 00451 00452 00453 /*! 00454 Returns the text. 00455 */ 00456 function title( $contentObjectAttribute, $value = null ) 00457 { 00458 $text = eZXMLTextType::rawXMLText( $contentObjectAttribute ); 00459 00460 $dom = new DOMDocument( '1.0', 'utf-8' ); 00461 $success = $dom->loadXML( $text ); 00462 00463 // Get first text element of xml 00464 if ( !$success ) 00465 { 00466 return $text; 00467 } 00468 00469 $root = $dom->documentElement; 00470 $section = $root->firstChild; 00471 $textDom = false; 00472 if ( $section ) 00473 { 00474 $textDom = $section->firstChild; 00475 } 00476 00477 if ( $textDom and $textDom->hasChildNodes ) 00478 { 00479 $text = $textDom->firstChild->textContent; 00480 } 00481 elseif ( $textDom ) 00482 { 00483 $text = $textDom->textContent; 00484 } 00485 00486 return $text; 00487 } 00488 00489 function hasObjectAttributeContent( $contentObjectAttribute ) 00490 { 00491 $content = $this->objectAttributeContent( $contentObjectAttribute ); 00492 if ( is_object( $content ) and 00493 !$content->attribute( 'is_empty' ) ) 00494 return true; 00495 return false; 00496 } 00497 00498 /*! 00499 \reimp 00500 */ 00501 function isIndexable() 00502 { 00503 return true; 00504 } 00505 00506 /*! 00507 \reimp 00508 */ 00509 function isInformationCollector() 00510 { 00511 return false; 00512 } 00513 00514 /*! 00515 \reimp 00516 Makes sure content/datatype/.../ezxmltags/... are included. 00517 */ 00518 function templateList() 00519 { 00520 return array( array( 'regexp', 00521 '#^content/datatype/[a-zA-Z]+/ezxmltags/#' ) ); 00522 } 00523 00524 /*! 00525 \reimp 00526 */ 00527 function serializeContentClassAttribute( $classAttribute, $attributeNode, $attributeParametersNode ) 00528 { 00529 $textColumns = $classAttribute->attribute( self::COLS_FIELD ); 00530 $dom = $attributeParametersNode->ownerDocument; 00531 $textColumnCountNode = $dom->createElement( 'text-column-count' ); 00532 $textColumnCountNode->appendChild( $dom->createTextNode( $textColumns ) ); 00533 $attributeParametersNode->appendChild( $textColumnCountNode ); 00534 } 00535 00536 /*! 00537 \reimp 00538 */ 00539 function unserializeContentClassAttribute( $classAttribute, $attributeNode, $attributeParametersNode ) 00540 { 00541 $textColumns = $attributeParametersNode->getElementsByTagName( 'text-column-count' )->item( 0 )->textContent; 00542 $classAttribute->setAttribute( self::COLS_FIELD, $textColumns ); 00543 } 00544 00545 /*! 00546 */ 00547 function customObjectAttributeHTTPAction( $http, $action, $contentObjectAttribute, $parameters ) 00548 { 00549 $content = $this->objectAttributeContent( $contentObjectAttribute ); 00550 $inputHandler = $content->attribute( 'input' ); 00551 $inputHandler->customObjectAttributeHTTPAction( $http, $action, $contentObjectAttribute ); 00552 } 00553 00554 /*! 00555 \reimp 00556 \return a DOM representation of the content object attribute 00557 */ 00558 function serializeContentObjectAttribute( $package, $objectAttribute ) 00559 { 00560 00561 $DOMNode = $this->createContentObjectAttributeDOMNode( $objectAttribute ); 00562 $xmlString = $objectAttribute->attribute( 'data_text' ); 00563 00564 if ( $xmlString != '' ) 00565 { 00566 $doc = new DOMDocument( '1.0', 'utf-8' ); 00567 $success = $doc->loadXML( $xmlString ); 00568 00569 /* For all links found in the XML, do the following: 00570 * - add "href" attribute fetching it from ezurl table. 00571 * - remove "id" attribute. 00572 */ 00573 00574 //include_once( 'kernel/classes/datatypes/ezurl/ezurlobjectlink.php' ); 00575 //include_once( 'kernel/classes/datatypes/ezurl/ezurl.php' ); 00576 00577 $links = $doc->getElementsByTagName( 'link' ); 00578 $embeds = $doc->getElementsByTagName( 'embed' ); 00579 $objects = $doc->getElementsByTagName( 'object' ); 00580 $embedsInline = $doc->getElementsByTagName( 'embed-inline' ); 00581 00582 eZXMLTextType::transformLinksToRemoteLinks( $links ); 00583 eZXMLTextType::transformLinksToRemoteLinks( $embeds ); 00584 eZXMLTextType::transformLinksToRemoteLinks( $objects ); 00585 eZXMLTextType::transformLinksToRemoteLinks( $embedsInline ); 00586 00587 $importedRootNode = $DOMNode->ownerDocument->importNode( $doc->documentElement, true ); 00588 $DOMNode->appendChild( $importedRootNode ); 00589 } 00590 00591 return $DOMNode; 00592 } 00593 00594 static function transformLinksToRemoteLinks( DOMNodeList $nodeList ) 00595 { 00596 foreach ( $nodeList as $node ) 00597 { 00598 $linkID = $node->getAttribute( 'url_id' ); 00599 $isObject = ( $node->localName == 'object' ); 00600 $objectID = $isObject ? $node->getAttribute( 'id' ) : $node->getAttribute( 'object_id' ); 00601 $nodeID = $node->getAttribute( 'node_id' ); 00602 00603 if ( $linkID ) 00604 { 00605 $urlObj = eZURL::fetch( $linkID ); 00606 if ( !$urlObj ) // an error occured 00607 { 00608 continue; 00609 } 00610 $url = $urlObj->attribute( 'url' ); 00611 $node->setAttribute( 'href', $url ); 00612 $node->removeAttribute( 'url_id' ); 00613 } 00614 elseif ( $objectID ) 00615 { 00616 $object = eZContentObject::fetch( $objectID, false ); 00617 if ( is_array( $object ) ) 00618 { 00619 $node->setAttribute( 'object_remote_id', $object['remote_id'] ); 00620 } 00621 00622 if ( $isObject ) 00623 { 00624 $node->removeAttribute( 'id' ); 00625 } 00626 else 00627 { 00628 $node->removeAttribute( 'object_id' ); 00629 } 00630 } 00631 elseif ( $nodeID ) 00632 { 00633 $nodeData = eZContentObjectTreeNode::fetch( $nodeID, false, false ); 00634 if ( is_array( $nodeData ) ) 00635 { 00636 $node->setAttribute( 'node_remote_id', $nodeData['remote_id'] ); 00637 } 00638 $node->removeAttribute( 'node_id' ); 00639 } 00640 } 00641 } 00642 00643 /*! 00644 \reimp 00645 \param contentobject attribute object 00646 \param domnode object 00647 */ 00648 function unserializeContentObjectAttribute( $package, $objectAttribute, $attributeNode ) 00649 { 00650 /* For all links found in the XML, do the following: 00651 * Search for url specified in 'href' link attribute (in ezurl table). 00652 * If the url not found then create a new one. 00653 * Then associate the found (or created) URL with the object attribute by creating new url-object link. 00654 * After that, remove "href" attribute, add new "id" attribute. 00655 * This new 'id' will always refer to the existing url object. 00656 */ 00657 //include_once( 'kernel/classes/datatypes/ezurl/ezurlobjectlink.php' ); 00658 //include_once( 'kernel/classes/datatypes/ezurl/ezurl.php' ); 00659 00660 $linkNodes = $attributeNode->getElementsByTagName( 'link' ); 00661 00662 foreach ( $linkNodes as $linkNode ) 00663 { 00664 $href = $linkNode->getAttribute( 'href' ); 00665 if ( !$href ) 00666 continue; 00667 $urlObj = eZURL::urlByURL( $href ); 00668 00669 if ( !$urlObj ) 00670 { 00671 $urlObj = eZURL::create( $href ); 00672 $urlObj->store(); 00673 } 00674 00675 $linkNode->removeAttribute( 'href' ); 00676 $linkNode->setAttribute( 'url_id', $urlObj->attribute( 'id' ) ); 00677 $urlObjectLink = eZURLObjectLink::create( $urlObj->attribute( 'id' ), 00678 $objectAttribute->attribute( 'id' ), 00679 $objectAttribute->attribute( 'version' ) ); 00680 $urlObjectLink->store(); 00681 } 00682 00683 foreach ( $attributeNode->childNodes as $childNode ) 00684 { 00685 if ( $childNode->nodeType == XML_ELEMENT_NODE ) 00686 { 00687 $xmlString = $childNode->ownerDocument->saveXML( $childNode ); 00688 $objectAttribute->setAttribute( 'data_text', $xmlString ); 00689 break; 00690 } 00691 } 00692 } 00693 00694 function postUnserializeContentObjectAttribute( $package, $objectAttribute ) 00695 { 00696 $xmlString = $objectAttribute->attribute( 'data_text' ); 00697 $doc = new DOMDocument( '1.0', 'utf-8' ); 00698 $success = $doc->loadXML( $xmlString ); 00699 00700 if ( !$success ) 00701 { 00702 return false; 00703 } 00704 00705 $links = $doc->getElementsByTagName( 'link' ); 00706 $objects = $doc->getElementsByTagName( 'object' ); 00707 $embeds = $doc->getElementsByTagName( 'embed' ); 00708 $embedsInline = $doc->getElementsByTagName( 'embed-inline' ); 00709 00710 $modified = array(); 00711 $modified[] = eZXMLTextType::transformRemoteLinksToLinks( $links, $objectAttribute ); 00712 $modified[] = eZXMLTextType::transformRemoteLinksToLinks( $objects, $objectAttribute ); 00713 $modified[] = eZXMLTextType::transformRemoteLinksToLinks( $embeds, $objectAttribute ); 00714 $modified[] = eZXMLTextType::transformRemoteLinksToLinks( $embedsInline, $objectAttribute ); 00715 00716 if ( in_array( true, $modified ) ) 00717 { 00718 $objectAttribute->setAttribute( 'data_text', eZXMLTextType::domString( $doc ) ); 00719 return true; 00720 } 00721 else 00722 { 00723 return false; 00724 } 00725 } 00726 00727 static function transformRemoteLinksToLinks( DOMNodeList $nodeList, $objectAttribute ) 00728 { 00729 $modified = false; 00730 00731 $contentObject = $objectAttribute->attribute( 'object' ); 00732 foreach ( $nodeList as $node ) 00733 { 00734 $objectRemoteID = $node->getAttribute( 'object_remote_id' ); 00735 $nodeRemoteID = $node->getAttribute( 'node_remote_id' ); 00736 if ( $objectRemoteID ) 00737 { 00738 $objectArray = eZContentObject::fetchByRemoteID( $objectRemoteID, false ); 00739 if ( !is_array( $objectArray ) ) 00740 { 00741 eZDebug::writeWarning( "Can't fetch object with remoteID = $objectRemoteID", 'eZXMLTextType::unserialize' ); 00742 continue; 00743 } 00744 00745 $objectID = $objectArray['id']; 00746 if ( $node->localName == 'object' ) 00747 $node->setAttribute( 'id', $objectID ); 00748 else 00749 $node->setAttribute( 'object_id', $objectID ); 00750 $node->removeAttribute( 'object_remote_id' ); 00751 $modified = true; 00752 00753 // add as related object 00754 if ( $contentObject ) 00755 { 00756 $relationType = $node->localName == 'link' ? eZContentObject::RELATION_LINK : eZContentObject::RELATION_EMBED; 00757 $contentObject->addContentObjectRelation( $objectID, $objectAttribute->attribute( 'version' ), 0, $relationType ); 00758 } 00759 } 00760 elseif ( $nodeRemoteID ) 00761 { 00762 $nodeArray = eZContentObjectTreeNode::fetchByRemoteID( $nodeRemoteID, false ); 00763 if ( !is_array( $nodeArray ) ) 00764 { 00765 eZDebug::writeWarning( "Can't fetch node with remoteID = $nodeRemoteID", 'eZXMLTextType::unserialize' ); 00766 continue; 00767 } 00768 00769 $nodeID = $nodeArray['node_id']; 00770 $node->setAttribute( 'node_id', $nodeID ); 00771 $node->removeAttribute( 'node_remote_id' ); 00772 $modified = true; 00773 00774 // add as related object 00775 if ( $contentObject ) 00776 { 00777 $node = eZContentObjectTreeNode::fetch( $nodeID, false, false ); 00778 if ( $node ) 00779 { 00780 $relationType = $node->nodeName == 'link' ? eZContentObject::RELATION_LINK : eZContentObject::RELATION_EMBED; 00781 $contentObject->addContentObjectRelation( $node['contentobject_id'], $objectAttribute->attribute( 'version' ), 0, $relationType ); 00782 } 00783 } 00784 } 00785 } 00786 00787 return $modified; 00788 } 00789 00790 /*! 00791 Delete stored object attribute, this will clean up the ezurls and ezobjectlinks 00792 */ 00793 function deleteStoredObjectAttribute( $contentObjectAttribute, $version = null ) 00794 { 00795 $contentObjectAttributeID = $contentObjectAttribute->attribute( "id" ); 00796 00797 $db = eZDB::instance(); 00798 00799 /* First we remove the link between the keyword and the object 00800 * attribute to be removed */ 00801 //include_once( 'kernel/classes/datatypes/ezurl/ezurlobjectlink.php' ); 00802 if ( $version == null ) 00803 { 00804 eZPersistentObject::removeObject( eZURLObjectLink::definition(), 00805 array( 'contentobject_attribute_id' => $contentObjectAttributeID ) ); 00806 00807 } 00808 else 00809 { 00810 eZPersistentObject::removeObject( eZURLObjectLink::definition(), 00811 array( 'contentobject_attribute_id' => $contentObjectAttributeID, 00812 'contentobject_attribute_version' => $version ) ); 00813 } 00814 00815 /* Here we figure out which which URLs are not in use at all */ 00816 if ( $db->databaseName() == 'oracle' ) 00817 { 00818 $res = $db->arrayQuery( "SELECT DISTINCT id 00819 FROM ezurl, ezurl_object_link 00820 WHERE ezurl.id = ezurl_object_link.url_id(+) 00821 AND url_id IS NULL" ); 00822 } 00823 else 00824 { 00825 $res = $db->arrayQuery(" SELECT DISTINCT id 00826 FROM ezurl LEFT JOIN ezurl_object_link ON (ezurl.id = ezurl_object_link.url_id) 00827 WHERE url_id IS NULL" ); 00828 } 00829 00830 /* And if there are some, we delete them */ 00831 if ( count( $res ) ) 00832 { 00833 $unusedUrlIDs = array(); 00834 foreach ( $res as $record ) 00835 $unusedUrlIDs[] = $record['id']; 00836 $unusedUrlIDString = implode( ', ', $unusedUrlIDs ); 00837 00838 $db->query( "DELETE FROM ezurl WHERE id IN ($unusedUrlIDString)" ); 00839 } 00840 } 00841 00842 /*! 00843 \reimp 00844 */ 00845 function diff( $old, $new, $options = false ) 00846 { 00847 //include_once( 'lib/ezdiff/classes/ezdiff.php' ); 00848 $diff = new eZDiff(); 00849 $diff->setDiffEngineType( $diff->engineType( 'xml' ) ); 00850 $diff->initDiffEngine(); 00851 $diffObject = $diff->diff( $old, $new ); 00852 return $diffObject; 00853 } 00854 00855 } 00856 00857 eZDataType::register( eZXMLTextType::DATA_TYPE_STRING, "eZXMLTextType" ); 00858 00859 ?>