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