eZ Publish  [4.0]
ezxmltexttype.php
Go to the documentation of this file.
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">&lt;font color=&quot;red&quot;&gt;red text&lt;/font&gt;</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 ?>