|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZObjectRelationListType class 00004 // 00005 // Created on: <16-Apr-2002 11:08:14 amos> 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 eZObjectRelationListType ezobjectrelationlisttype.php 00033 \ingroup eZDatatype 00034 \brief A content datatype which handles object relations 00035 00036 Bugs/missing/deprecated features: 00037 - No identifier support yet 00038 - Validation and fixup for "Add new object" functionality 00039 - Proper embed views for admin classes 00040 - No translation page support yet (maybe?) 00041 - is_modified is deprecated and is used for BC only. 00042 00043 */ 00044 00045 //include_once( 'kernel/classes/ezdatatype.php' ); 00046 //include_once( 'kernel/classes/ezcontentobject.php' ); 00047 //include_once( 'lib/ezutils/classes/ezintegervalidator.php' ); 00048 //include_once( 'lib/ezutils/classes/ezinputvalidator.php' ); 00049 //include_once( 'lib/ezi18n/classes/eztranslatormanager.php' ); 00050 00051 class eZObjectRelationListType extends eZDataType 00052 { 00053 const DATA_TYPE_STRING = "ezobjectrelationlist"; 00054 00055 /*! 00056 Initializes with a string id and a description. 00057 */ 00058 function eZObjectRelationListType() 00059 { 00060 $this->eZDataType( self::DATA_TYPE_STRING, ezi18n( 'kernel/classes/datatypes', "Object relations", 'Datatype name' ), 00061 array( 'serialize_supported' => true ) ); 00062 } 00063 00064 /*! 00065 Validates the input and returns true if the input was 00066 valid for this datatype. 00067 */ 00068 function validateObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute ) 00069 { 00070 $inputParameters = $contentObjectAttribute->inputParameters(); 00071 $contentClassAttribute = $contentObjectAttribute->contentClassAttribute(); 00072 $parameters = $contentObjectAttribute->validationParameters(); 00073 if ( isset( $parameters['prefix-name'] ) and 00074 $parameters['prefix-name'] ) 00075 $parameters['prefix-name'][] = $contentClassAttribute->attribute( 'name' ); 00076 else 00077 $parameters['prefix-name'] = array( $contentClassAttribute->attribute( 'name' ) ); 00078 00079 $status = eZInputValidator::STATE_ACCEPTED; 00080 $postVariableName = $base . "_data_object_relation_list_" . $contentObjectAttribute->attribute( "id" ); 00081 $contentClassAttribute = $contentObjectAttribute->contentClassAttribute(); 00082 $classContent = $contentClassAttribute->content(); 00083 // Check if selection type is not browse 00084 if ( $classContent['selection_type'] != 0 ) 00085 { 00086 $selectedObjectIDArray = $http->hasPostVariable( $postVariableName ) ? $http->postVariable( $postVariableName ) : false; 00087 if ( $contentObjectAttribute->validateIsRequired() and $selectedObjectIDArray === false ) 00088 { 00089 $contentObjectAttribute->setValidationError( ezi18n( 'kernel/classes/datatypes', 00090 'Missing objectrelation list input.' ) ); 00091 return eZInputValidator::STATE_INVALID; 00092 } 00093 return $status; 00094 } 00095 00096 $content = $contentObjectAttribute->content(); 00097 if ( $contentObjectAttribute->validateIsRequired() and count( $content['relation_list'] ) == 0 ) 00098 { 00099 $contentObjectAttribute->setValidationError( ezi18n( 'kernel/classes/datatypes', 00100 'Missing objectrelation list input.' ) ); 00101 return eZInputValidator::STATE_INVALID; 00102 } 00103 00104 for ( $i = 0; $i < count( $content['relation_list'] ); ++$i ) 00105 { 00106 $relationItem = $content['relation_list'][$i]; 00107 if ( $relationItem['is_modified'] ) 00108 { 00109 $subObjectID = $relationItem['contentobject_id']; 00110 $subObjectVersion = $relationItem['contentobject_version']; 00111 $attributeBase = $base . '_ezorl_edit_object_' . $subObjectID; 00112 $object = eZContentObject::fetch( $subObjectID ); 00113 if ( $object ) 00114 { 00115 $attributes = $object->contentObjectAttributes( true, 00116 $subObjectVersion, 00117 $contentObjectAttribute->attribute( 'language_code' ) ); 00118 $validationResult = $object->validateInput( $attributes, $attributeBase, 00119 $inputParameters, $parameters ); 00120 $inputValidated = $validationResult['input-validated']; 00121 $content['temp'][$subObjectID]['require-fixup'] = $validationResult['require-fixup']; 00122 $statusMap = $validationResult['status-map']; 00123 foreach ( $statusMap as $statusItem ) 00124 { 00125 $statusValue = $statusItem['value']; 00126 if ( $statusValue == eZInputValidator::STATE_INTERMEDIATE and 00127 $status == eZInputValidator::STATE_ACCEPTED ) 00128 $status = eZInputValidator::STATE_INTERMEDIATE; 00129 else if ( $statusValue == eZInputValidator::STATE_INVALID ) 00130 { 00131 $contentObjectAttribute->setHasValidationError( false ); 00132 $status = eZInputValidator::STATE_INVALID; 00133 } 00134 } 00135 00136 $content['temp'][$subObjectID]['attributes'] = $attributes; 00137 $content['temp'][$subObjectID]['object'] = $object; 00138 } 00139 } 00140 } 00141 00142 $contentObjectAttribute->setContent( $content ); 00143 return $status; 00144 } 00145 00146 /*! 00147 Validates the input and returns true if the input was 00148 valid for this datatype. 00149 */ 00150 function fixupObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute ) 00151 { 00152 $content = $contentObjectAttribute->content(); 00153 for ( $i = 0; $i < count( $content['relation_list'] ); ++$i ) 00154 { 00155 $relationItem = $content['relation_list'][$i]; 00156 if ( $relationItem['is_modified'] ) 00157 { 00158 $subObjectID = $relationItem['contentobject_id']; 00159 $attributeBase = $base . '_ezorl_edit_object_' . $subObjectID; 00160 $object = $content['temp'][$subObjectID]['object']; 00161 $requireFixup = $content['temp'][$subObjectID]['require-fixup']; 00162 if ( $object and 00163 $requireFixup ) 00164 { 00165 $attributes = $content['temp'][$subObjectID]['attributes']; 00166 $object->fixupInput( $attributes, $attributeBase ); 00167 } 00168 } 00169 } 00170 } 00171 00172 /*! 00173 Fetches the http post var string input and stores it in the data instance. 00174 */ 00175 function fetchObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute ) 00176 { 00177 $content = $contentObjectAttribute->content(); 00178 // new object creation 00179 $newObjectPostVariableName = "attribute_" . $contentObjectAttribute->attribute( "id" ) . "_new_object_name"; 00180 if ( $http->hasPostVariable( $newObjectPostVariableName ) ) 00181 { 00182 $name = $http->postVariable( $newObjectPostVariableName ); 00183 if ( !empty( $name ) ) 00184 { 00185 $content['new_object'] = $name; 00186 } 00187 } 00188 $singleSelectPostVariableName = "single_select_" . $contentObjectAttribute->attribute( "id" ); 00189 if ( $http->hasPostVariable( $singleSelectPostVariableName ) ) 00190 $content['singleselect'] = true; 00191 00192 $postVariableName = $base . "_data_object_relation_list_" . $contentObjectAttribute->attribute( "id" ); 00193 $contentClassAttribute = $contentObjectAttribute->contentClassAttribute(); 00194 $classContent = $contentClassAttribute->content(); 00195 // Check if selection type is not browse 00196 if ( $classContent['selection_type'] != 0 ) 00197 { 00198 $selectedObjectIDArray = $http->hasPostVariable( $postVariableName ) ? $http->postVariable( $postVariableName ) : false; 00199 $priority = 0; 00200 // We should clear content 00201 $content['relation_list'] = array(); 00202 // If we got an empty object id list 00203 if ( $selectedObjectIDArray === false or ( isset( $selectedObjectIDArray[0] ) and $selectedObjectIDArray[0] == 'no_relation' ) ) 00204 { 00205 $contentObjectAttribute->setContent( $content ); 00206 $contentObjectAttribute->store(); 00207 return true; 00208 } 00209 00210 foreach ( $selectedObjectIDArray as $objectID ) 00211 { 00212 // Check if the given object ID has a numeric value, if not go to the next object. 00213 if ( !is_numeric( $objectID ) ) 00214 { 00215 eZDebug::writeError( "Related object ID (objectID): '$objectID', is not a numeric value.", 00216 "eZObjectRelationListType::fetchObjectAttributeHTTPInput" ); 00217 00218 continue; 00219 } 00220 ++$priority; 00221 $content['relation_list'][] = $this->appendObject( $objectID, $priority, $contentObjectAttribute ); 00222 } 00223 00224 $contentObjectAttribute->setContent( $content ); 00225 return true; 00226 } 00227 00228 $contentObjectAttributeID = $contentObjectAttribute->attribute( 'id' ); 00229 $priorityBase = $base . '_priority'; 00230 $priorities = array(); 00231 if ( $http->hasPostVariable( $priorityBase ) ) 00232 $priorities = $http->postVariable( $priorityBase ); 00233 $reorderedRelationList = array(); 00234 // Contains existing priorities 00235 $existsPriorities = array(); 00236 00237 for ( $i = 0; $i < count( $content['relation_list'] ); ++$i ) 00238 { 00239 $priorities[$contentObjectAttributeID][$i] = (int) $priorities[$contentObjectAttributeID][$i]; 00240 $existsPriorities[$i] = $priorities[$contentObjectAttributeID][$i]; 00241 00242 // Change objects' priorities providing their uniqueness. 00243 for ( $j = 0; $j < count( $content['relation_list'] ); ++$j ) 00244 { 00245 if ( $i == $j ) continue; 00246 if ( $priorities[$contentObjectAttributeID][$i] == $priorities[$contentObjectAttributeID][$j] ) 00247 { 00248 $index = $priorities[$contentObjectAttributeID][$i]; 00249 while ( in_array( $index, $existsPriorities ) ) 00250 ++$index; 00251 $priorities[$contentObjectAttributeID][$j] = $index; 00252 } 00253 } 00254 $relationItem = $content['relation_list'][$i]; 00255 if ( $relationItem['is_modified'] ) 00256 { 00257 $subObjectID = $relationItem['contentobject_id']; 00258 $attributeBase = $base . '_ezorl_edit_object_' . $subObjectID; 00259 $object = $content['temp'][$subObjectID]['object']; 00260 if ( $object ) 00261 { 00262 $attributes = $content['temp'][$subObjectID]['attributes']; 00263 00264 $customActionAttributeArray = array(); 00265 $fetchResult = $object->fetchInput( $attributes, $attributeBase, 00266 $customActionAttributeArray, 00267 $contentObjectAttribute->inputParameters() ); 00268 $content['temp'][$subObjectID]['attribute-input-map'] = $fetchResult['attribute-input-map']; 00269 $content['temp'][$subObjectID]['attributes'] = $attributes; 00270 $content['temp'][$subObjectID]['object'] = $object; 00271 } 00272 } 00273 if ( isset( $priorities[$contentObjectAttributeID][$i] ) ) 00274 $relationItem['priority'] = $priorities[$contentObjectAttributeID][$i]; 00275 $reorderedRelationList[$relationItem['priority']] = $relationItem; 00276 } 00277 ksort( $reorderedRelationList ); 00278 unset( $content['relation_list'] ); 00279 $content['relation_list'] = array(); 00280 reset( $reorderedRelationList ); 00281 $i = 0; 00282 while ( list( $key, $relationItem ) = each( $reorderedRelationList ) ) 00283 { 00284 $content['relation_list'][] = $relationItem; 00285 $content['relation_list'][$i]['priority'] = $i + 1; 00286 ++$i; 00287 } 00288 $contentObjectAttribute->setContent( $content ); 00289 return true; 00290 } 00291 00292 function createNewObject( $contentObjectAttribute, $name ) 00293 { 00294 $classAttribute = $contentObjectAttribute->attribute( 'contentclass_attribute' ); 00295 $classContent = $classAttribute->content(); 00296 $classID = $classContent['object_class']; 00297 if ( !isset( $classID ) or !is_numeric( $classID ) ) 00298 return false; 00299 00300 $defaultPlacementNode = ( is_array( $classContent['default_placement'] ) and isset( $classContent['default_placement']['node_id'] ) ) ? $classContent['default_placement']['node_id'] : false; 00301 if ( !$defaultPlacementNode ) 00302 { 00303 eZDebug::writeError( 'Default placement is missing', 'eZObjectRelationListType::createNewObject' ); 00304 return false; 00305 } 00306 00307 $node = eZContentObjectTreeNode::fetch( $defaultPlacementNode ); 00308 // Check if current user can create a new node as child of this node. 00309 if ( !$node or !$node->canCreate() ) 00310 { 00311 eZDebug::writeError( 'Default placement is wrong or the current user can\'t create a new node as child of this node.', 'eZObjectRelationListType::createNewObject' ); 00312 return false; 00313 } 00314 00315 $classList = $node->canCreateClassList( false ); 00316 $canCreate = false; 00317 // Check if current user can create object of class (with $classID) 00318 foreach ( $classList as $class ) 00319 { 00320 if ( $class['id'] == $classID ) 00321 { 00322 $canCreate = true; 00323 break; 00324 } 00325 } 00326 if ( !$canCreate ) 00327 { 00328 eZDebug::writeError( 'The current user is not allowed to create objects of class (ID=' . $classID . ')', 'eZObjectRelationListType::createNewObject' ); 00329 return false; 00330 } 00331 00332 $class = eZContentClass::fetch( $classID ); 00333 if ( !$class ) 00334 return false; 00335 00336 $currentObject = $contentObjectAttribute->attribute( 'object' ); 00337 $sectionID = $currentObject->attribute( 'section_id' ); 00338 //instantiate object, same section, currentuser as owner (i.e. provide false as param) 00339 $newObjectInstance = $class->instantiate( false, $sectionID ); 00340 $nodeassignment = $newObjectInstance->createNodeAssignment( $defaultPlacementNode, true ); 00341 $nodeassignment->store(); 00342 $newObjectInstance->sync(); 00343 //include_once( "lib/ezutils/classes/ezoperationhandler.php" ); 00344 $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $newObjectInstance->attribute( 'id' ), 'version' => 1 ) ); 00345 // so it updates the attributes 00346 $newObjectInstance->rename( $name ); 00347 00348 return $newObjectInstance->attribute( 'id' ); 00349 } 00350 00351 /*! 00352 */ 00353 function storeObjectAttribute( $attribute ) 00354 { 00355 $content = $attribute->content(); 00356 if ( isset( $content['new_object'] ) ) 00357 { 00358 $newID = $this->createNewObject( $attribute, $content['new_object'] ); 00359 // if this is a single element selection mode (radio or dropdown), then the newly created item is the only one selected 00360 if ( $newID ) 00361 { 00362 if ( isset( $content['singleselect'] ) ) 00363 $content['relation_list'] = array(); 00364 $content['relation_list'][] = $this->appendObject( $newID, 0, $attribute ); 00365 } 00366 unset( $content['new_object'] ); 00367 $attribute->setContent( $content ); 00368 } 00369 00370 $contentClassAttributeID = $attribute->ContentClassAttributeID; 00371 $contentObjectID = $attribute->ContentObjectID; 00372 $contentObjectVersion = $attribute->Version; 00373 00374 $obj = $attribute->object(); 00375 //get eZContentObjectVersion 00376 $currVerobj = $obj->version( $contentObjectVersion ); 00377 00378 // create translation List 00379 // $translationList will contain for example eng-GB, ita-IT etc. 00380 $translationList = $currVerobj->translations( false ); 00381 00382 // get current language_code 00383 $langCode = $attribute->attribute( 'language_code' ); 00384 // get count of LanguageCode in translationList 00385 $countTsl = count( $translationList ); 00386 // order by asc 00387 sort( $translationList ); 00388 00389 if ( ( $countTsl == 1 ) or ( $countTsl > 1 and $translationList[0] == $langCode ) ) 00390 { 00391 eZContentObject::fetch( $contentObjectID )->removeContentObjectRelation( false, $contentObjectVersion, $contentClassAttributeID, eZContentObject::RELATION_ATTRIBUTE ); 00392 } 00393 00394 foreach( $content['relation_list'] as $relationItem ) 00395 { 00396 // Installing content object, postUnserialize is not called yet, 00397 // so object's ID is unknown. 00398 if ( !$relationItem['contentobject_id'] || !isset( $relationItem['contentobject_id'] ) ) 00399 continue; 00400 00401 $subObjectID = $relationItem['contentobject_id']; 00402 $subObjectVersion = $relationItem['contentobject_version']; 00403 00404 eZContentObject::fetch( $contentObjectID )->addContentObjectRelation( $subObjectID, $contentObjectVersion, $contentClassAttributeID, eZContentObject::RELATION_ATTRIBUTE ); 00405 00406 if ( $relationItem['is_modified'] && isset( $content['temp'][$subObjectID]['object' ] ) ) 00407 { 00408 // handling sub-objects 00409 $object = $content['temp'][$subObjectID]['object']; 00410 if ( $object ) 00411 { 00412 $attributes = $content['temp'][$subObjectID]['attributes']; 00413 $attributeInputMap = $content['temp'][$subObjectID]['attribute-input-map']; 00414 $object->storeInput( $attributes, 00415 $attributeInputMap ); 00416 $version = eZContentObjectVersion::fetchVersion( $subObjectVersion, $subObjectID ); 00417 if ( $version ) 00418 { 00419 $version->setAttribute( 'modified', time() ); 00420 $version->setAttribute( 'status', eZContentObjectVersion::STATUS_DRAFT ); 00421 $version->store(); 00422 } 00423 00424 $object->setAttribute( 'status', eZContentObject::STATUS_DRAFT ); 00425 $object->store(); 00426 } 00427 } 00428 } 00429 return eZObjectRelationListType::storeObjectAttributeContent( $attribute, $content ); 00430 } 00431 00432 /*! 00433 \reimp 00434 */ 00435 function onPublish( $contentObjectAttribute, $contentObject, $publishedNodes ) 00436 { 00437 $content = $contentObjectAttribute->content(); 00438 foreach( $content['relation_list'] as $key => $relationItem ) 00439 { 00440 if ( $relationItem['is_modified'] ) 00441 { 00442 $subObjectID = $relationItem['contentobject_id']; 00443 $subObjectVersion = $relationItem['contentobject_version']; 00444 $object = eZContentObject::fetch( $subObjectID ); 00445 00446 $time = time(); 00447 $version = eZContentObjectVersion::fetchVersion( $subObjectVersion, $subObjectID ); 00448 $version->setAttribute( 'modified', $time ); 00449 $version->store(); 00450 00451 if ( $relationItem['parent_node_id'] > 0 ) 00452 { 00453 // action 1: edit a normal object 00454 if ( !eZNodeAssignment::fetch( $object->attribute( 'id' ), $object->attribute( 'current_version' ), $relationItem['parent_node_id'], false ) ) 00455 { 00456 $nodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $object->attribute( 'id' ), 00457 'contentobject_version' => $object->attribute( 'current_version' ), 00458 'parent_node' => $relationItem['parent_node_id'], 00459 'sort_field' => 2, 00460 'sort_order' => 0, 00461 'is_main' => 1 ) ); 00462 $nodeAssignment->store(); 00463 } 00464 $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $object->attribute( 'id' ), 00465 'version' => $subObjectVersion ) ); 00466 $objectNodeID = $object->attribute( 'main_node_id' ); 00467 $content['relation_list'][$key]['node_id'] = $objectNodeID; 00468 } 00469 else 00470 { 00471 // action 2: edit a nodeless object (or creating a new node 00472 // Make the previous version archived 00473 $currentVersion = $object->currentVersion(); 00474 $currentVersion->setAttribute( 'status', eZContentObjectVersion::STATUS_ARCHIVED ); 00475 $currentVersion->setAttribute( 'modified', $time ); 00476 $currentVersion->store(); 00477 00478 $version->setAttribute( 'status', eZContentObjectVersion::STATUS_PUBLISHED ); 00479 $version->store(); 00480 00481 $object->setAttribute( 'status', eZContentObject::STATUS_PUBLISHED ); 00482 if ( !$object->attribute( 'published' ) ) 00483 $object->setAttribute( 'published', $time ); 00484 $object->setAttribute( 'modified', $time ); 00485 $object->setAttribute( 'current_version', $subObjectVersion ); 00486 $object->setAttribute( 'is_published', true ); 00487 $class = $object->contentClass(); 00488 $objectName = $class->contentObjectName( $object, $version->attribute( 'version' ) ); 00489 $object->setName( $objectName, $version->attribute( 'version' ) ); 00490 $object->store(); 00491 00492 if ( !eZNodeAssignment::fetch( $object->attribute( 'id' ), $object->attribute( 'current_version' ), $contentObject->attribute( 'main_node_id' ), false ) ) 00493 { 00494 $nodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $object->attribute( 'id' ), 00495 'contentobject_version' => $object->attribute( 'current_version' ), 00496 'parent_node' => $contentObject->attribute( 'main_node_id' ), 00497 'sort_field' => 2, 00498 'sort_order' => 0, 00499 'is_main' => 1 ) ); 00500 $nodeAssignment->store(); 00501 } 00502 } 00503 $content['relation_list'][$key]['is_modified'] = false; 00504 } 00505 } 00506 eZObjectRelationListType::storeObjectAttributeContent( $contentObjectAttribute, $content ); 00507 $contentObjectAttribute->setContent( $content ); 00508 $contentObjectAttribute->store(); 00509 } 00510 00511 function initializeObjectAttribute( $contentObjectAttribute, $currentVersion, $originalContentObjectAttribute ) 00512 { 00513 00514 static $copiedRelatedAccordance; 00515 if ( !isset( $copiedRelatedAccordance ) ) 00516 $copiedRelatedAccordance = array(); 00517 00518 if ( $currentVersion != false ) 00519 { 00520 $dataText = $originalContentObjectAttribute->attribute( 'data_text' ); 00521 $contentObjectAttribute->setAttribute( 'data_text', $dataText ); 00522 $contentObjectID = $contentObjectAttribute->attribute( 'contentobject_id' ); 00523 $originalContentObjectID = $originalContentObjectAttribute->attribute( 'contentobject_id' ); 00524 00525 if ( $contentObjectID != $originalContentObjectID ) 00526 { 00527 $classContent = eZObjectRelationListType::defaultClassAttributeContent(); 00528 if ( !$classContent['default_placement'] ) 00529 { 00530 $content = $originalContentObjectAttribute->content(); 00531 $contentModified = false; 00532 00533 foreach ( $content['relation_list'] as $key => $relationItem ) 00534 { 00535 // create related object copies only if they are subobjects 00536 $object = eZContentObject::fetch( $relationItem['contentobject_id'] ); 00537 if ( !$object instanceof eZContentObject ) 00538 { 00539 unset( $content['relation_list'][$key] ); 00540 $contentModified = true; 00541 continue; 00542 } 00543 00544 $mainNode = $object->attribute( 'main_node' ); 00545 if ( $mainNode instanceof eZContentObjectTreeNode ) 00546 { 00547 $node = ( is_numeric( $relationItem['node_id'] ) and $relationItem['node_id'] ) ? 00548 eZContentObjectTreeNode::fetch( $relationItem['node_id'] ) : null; 00549 00550 if ( !$node or $node->attribute( 'contentobject_id' ) != $relationItem['contentobject_id'] ) 00551 { 00552 $content['relation_list'][$key]['node_id'] = $mainNode->attribute( 'node_id' ); 00553 $node = $mainNode; 00554 $contentModified = true; 00555 } 00556 00557 if ( $node instanceof eZContentObjectTreeNode ) 00558 $parentNodeID = $node->attribute( 'parent_node_id' ); 00559 else 00560 $parentNodeID = -1; 00561 00562 if ( $relationItem['parent_node_id'] != $parentNodeID ) 00563 { 00564 $content['relation_list'][$key]['parent_node_id'] = $parentNodeID; 00565 $contentModified = true; 00566 } 00567 } 00568 else 00569 { 00570 if ( !isset( $copiedRelatedAccordance[ $relationItem['contentobject_id'] ] ) ) 00571 $copiedRelatedAccordance[ $relationItem['contentobject_id'] ] = array(); 00572 00573 if ( isset( $copiedRelatedAccordance[ $relationItem['contentobject_id'] ] ) and 00574 isset( $copiedRelatedAccordance[ $relationItem['contentobject_id'] ][ $contentObjectID ] ) ) 00575 { 00576 $newObjectID = $copiedRelatedAccordance[ $relationItem['contentobject_id'] ][ $contentObjectID ][ 'to' ]; 00577 } 00578 else 00579 { 00580 $newObject = $object->copy( true ); 00581 $newObjectID = $newObject->attribute( 'id' ); 00582 $copiedRelatedAccordance[ $relationItem['contentobject_id'] ][ $contentObjectID ] = array( 'to' => $newObjectID, 00583 'from' => $originalContentObjectID ); 00584 } 00585 $content['relation_list'][$key]['contentobject_id'] = $newObjectID; 00586 $contentModified = true; 00587 } 00588 } 00589 00590 if ( $contentModified ) 00591 { 00592 $contentObjectAttribute->setContent( $content ); 00593 $contentObjectAttribute->store(); 00594 } 00595 } 00596 } 00597 } 00598 } 00599 00600 /*! 00601 \reimp 00602 */ 00603 function validateClassAttributeHTTPInput( $http, $base, $classAttribute ) 00604 { 00605 return eZInputValidator::STATE_ACCEPTED; 00606 } 00607 00608 /*! 00609 \reimp 00610 */ 00611 function fixupClassAttributeHTTPInput( $http, $base, $classAttribute ) 00612 { 00613 } 00614 00615 /*! 00616 \reimp 00617 */ 00618 function fetchClassAttributeHTTPInput( $http, $base, $classAttribute ) 00619 { 00620 $content = $classAttribute->content(); 00621 $postVariable = 'ContentClass_ezobjectrelationlist_class_list_' . $classAttribute->attribute( 'id' ); 00622 if ( $http->hasPostVariable( $postVariable ) ) 00623 { 00624 $constrainedList = $http->postVariable( $postVariable ); 00625 $constrainedClassList = array(); 00626 foreach ( $constrainedList as $constraint ) 00627 { 00628 if ( trim( $constraint ) != '' ) 00629 $constrainedClassList[] = $constraint; 00630 } 00631 $content['class_constraint_list'] = $constrainedClassList; 00632 } 00633 $typeVariable = 'ContentClass_ezobjectrelationlist_type_' . $classAttribute->attribute( 'id' ); 00634 if ( $http->hasPostVariable( $typeVariable ) ) 00635 { 00636 $type = $http->postVariable( $typeVariable ); 00637 $content['type'] = $type; 00638 } 00639 $selectionTypeVariable = 'ContentClass_ezobjectrelationlist_selection_type_' . $classAttribute->attribute( 'id' ); 00640 if ( $http->hasPostVariable( $selectionTypeVariable ) ) 00641 { 00642 $selectionType = $http->postVariable( $selectionTypeVariable ); 00643 $content['selection_type'] = $selectionType; 00644 } 00645 $objectClassVariable = 'ContentClass_ezobjectrelation_object_class_' . $classAttribute->attribute( 'id' ); 00646 if ( $http->hasPostVariable( $objectClassVariable ) ) 00647 { 00648 $content['object_class'] = $http->postVariable( $objectClassVariable ); 00649 } 00650 00651 $classAttribute->setContent( $content ); 00652 $classAttribute->store(); 00653 return true; 00654 } 00655 00656 /*! 00657 \reimp 00658 */ 00659 function initializeClassAttribute( $classAttribute ) 00660 { 00661 $xmlText = $classAttribute->attribute( 'data_text5' ); 00662 if ( trim( $xmlText ) == '' ) 00663 { 00664 $content = eZObjectRelationListType::defaultClassAttributeContent(); 00665 return eZObjectRelationListType::storeClassAttributeContent( $classAttribute, $content ); 00666 } 00667 } 00668 00669 /*! 00670 \reimp 00671 */ 00672 function preStoreClassAttribute( $classAttribute, $version ) 00673 { 00674 $content = $classAttribute->content(); 00675 return eZObjectRelationListType::storeClassAttributeContent( $classAttribute, $content ); 00676 } 00677 00678 function storeClassAttributeContent( $classAttribute, $content ) 00679 { 00680 if ( is_array( $content ) ) 00681 { 00682 $doc = eZObjectRelationListType::createClassDOMDocument( $content ); 00683 eZObjectRelationListType::storeClassDOMDocument( $doc, $classAttribute ); 00684 return true; 00685 } 00686 return false; 00687 } 00688 00689 function storeObjectAttributeContent( $objectAttribute, $content ) 00690 { 00691 if ( is_array( $content ) ) 00692 { 00693 $doc = eZObjectRelationListType::createObjectDOMDocument( $content ); 00694 eZObjectRelationListType::storeObjectDOMDocument( $doc, $objectAttribute ); 00695 return true; 00696 } 00697 return false; 00698 } 00699 00700 static function storeClassDOMDocument( $doc, $classAttribute ) 00701 { 00702 $docText = eZObjectRelationListType::domString( $doc ); 00703 $classAttribute->setAttribute( 'data_text5', $docText ); 00704 } 00705 00706 static function storeObjectDOMDocument( $doc, $objectAttribute ) 00707 { 00708 $docText = eZObjectRelationListType::domString( $doc ); 00709 $objectAttribute->setAttribute( 'data_text', $docText ); 00710 } 00711 00712 /*! 00713 \static 00714 \return the XML structure in \a $domDocument as text. 00715 It will take of care of the necessary charset conversions 00716 for content storage. 00717 */ 00718 static function domString( $domDocument ) 00719 { 00720 $ini = eZINI::instance(); 00721 $xmlCharset = $ini->variable( 'RegionalSettings', 'ContentXMLCharset' ); 00722 if ( $xmlCharset == 'enabled' ) 00723 { 00724 //include_once( 'lib/ezi18n/classes/eztextcodec.php' ); 00725 $charset = eZTextCodec::internalCharset(); 00726 } 00727 else if ( $xmlCharset == 'disabled' ) 00728 $charset = true; 00729 else 00730 $charset = $xmlCharset; 00731 if ( $charset !== true ) 00732 { 00733 //include_once( 'lib/ezi18n/classes/ezcharsetinfo.php' ); 00734 $charset = eZCharsetInfo::realCharsetCode( $charset ); 00735 } 00736 $domString = $domDocument->saveXML(); 00737 return $domString; 00738 } 00739 00740 static function createClassDOMDocument( $content ) 00741 { 00742 $doc = new DOMDocument( '1.0', 'utf-8' ); 00743 $root = $doc->createElement( 'related-objects' ); 00744 $constraints = $doc->createElement( 'constraints' ); 00745 foreach ( $content['class_constraint_list'] as $constraintClassIdentifier ) 00746 { 00747 unset( $constraintElement ); 00748 $constraintElement = $doc->createElement( 'allowed-class' ); 00749 $constraintElement->setAttribute( 'contentclass-identifier', $constraintClassIdentifier ); 00750 $constraints->appendChild( $constraintElement ); 00751 } 00752 $root->appendChild( $constraints ); 00753 $constraintType = $doc->createElement( 'type' ); 00754 $constraintType->setAttribute( 'value', $content['type'] ); 00755 $root->appendChild( $constraintType ); 00756 $selectionType = $doc->createElement( 'selection_type' ); 00757 $selectionType->setAttribute( 'value', $content['selection_type'] ); 00758 $root->appendChild( $selectionType ); 00759 $objectClass = $doc->createElement( 'object_class' ); 00760 $objectClass->setAttribute( 'value', $content['object_class'] ); 00761 $root->appendChild( $objectClass ); 00762 00763 $placementNode = $doc->createElement( 'contentobject-placement' ); 00764 if ( $content['default_placement'] ) 00765 { 00766 $placementNode->setAttribute( 'node-id', $content['default_placement']['node_id'] ); 00767 } 00768 $root->appendChild( $placementNode ); 00769 $doc->appendChild( $root ); 00770 return $doc; 00771 } 00772 00773 static function createObjectDOMDocument( $content ) 00774 { 00775 $doc = new DOMDocument( '1.0', 'utf-8' ); 00776 $root = $doc->createElement( 'related-objects' ); 00777 $relationList = $doc->createElement( 'relation-list' ); 00778 $attributeDefinitions = eZObjectRelationListType::contentObjectArrayXMLMap(); 00779 00780 foreach ( $content['relation_list'] as $relationItem ) 00781 { 00782 unset( $relationElement ); 00783 $relationElement = $doc->createElement( 'relation-item' ); 00784 00785 foreach ( $attributeDefinitions as $attributeXMLName => $attributeKey ) 00786 { 00787 if ( isset( $relationItem[$attributeKey] ) && $relationItem[$attributeKey] !== false ) 00788 { 00789 $value = $relationItem[$attributeKey]; 00790 $relationElement->setAttribute( $attributeXMLName, $value ); 00791 } 00792 } 00793 00794 $relationList->appendChild( $relationElement ); 00795 } 00796 $root->appendChild( $relationList ); 00797 $doc->appendChild( $root ); 00798 return $doc; 00799 } 00800 00801 static function contentObjectArrayXMLMap() 00802 { 00803 return array( 'identifier' => 'identifier', 00804 'priority' => 'priority', 00805 'in-trash' => 'in_trash', 00806 'contentobject-id' => 'contentobject_id', 00807 'contentobject-version' => 'contentobject_version', 00808 'node-id' => 'node_id', 00809 'parent-node-id' => 'parent_node_id', 00810 'contentclass-id' => 'contentclass_id', 00811 'contentclass-identifier' => 'contentclass_identifier', 00812 'is-modified' => 'is_modified', 00813 'contentobject-remote-id' => 'contentobject_remote_id' ); 00814 } 00815 00816 /*! 00817 \reimp 00818 */ 00819 function deleteStoredObjectAttribute( $objectAttribute, $version = null ) 00820 { 00821 $content = $objectAttribute->content(); 00822 if ( is_array( $content ) and 00823 is_array( $content['relation_list'] ) ) 00824 { 00825 $db = eZDB::instance(); 00826 $db->begin(); 00827 foreach ( $content['relation_list'] as $deletionItem ) 00828 { 00829 eZObjectRelationListType::removeRelationObject( $objectAttribute, $deletionItem ); 00830 } 00831 $db->commit(); 00832 } 00833 } 00834 00835 /*! 00836 \reimp 00837 */ 00838 function customObjectAttributeHTTPAction( $http, $action, $contentObjectAttribute, $parameters ) 00839 { 00840 $contentobjectID = false; 00841 if ( eZDataType::fetchActionValue( $action, 'new_class', $classID ) or 00842 $action == 'new_class' ) 00843 { 00844 if ( $action == 'new_class' ) 00845 { 00846 $base = $parameters['base_name']; 00847 $classVariableName = $base . '_new_class'; 00848 if ( $http->hasPostVariable( $classVariableName ) ) 00849 { 00850 $classVariable = $http->postVariable( $classVariableName ); 00851 $classID = $classVariable[$contentObjectAttribute->attribute( 'id' )]; 00852 $class = eZContentClass::fetch( $classID ); 00853 } 00854 else 00855 return false; 00856 } 00857 else 00858 $class = eZContentClass::fetch( $classID ); 00859 if ( $class ) 00860 { 00861 $classAttribute = $contentObjectAttribute->attribute( 'contentclass_attribute' ); 00862 $class_content = $classAttribute->content(); 00863 $content = $contentObjectAttribute->content(); 00864 $priority = 0; 00865 for ( $i = 0; $i < count( $content['relation_list'] ); ++$i ) 00866 { 00867 if ( $content['relation_list'][$i]['priority'] > $priority ) 00868 $priority = $content['relation_list'][$i]['priority']; 00869 } 00870 00871 $base = $parameters['base_name']; 00872 $nodePlacement = false; 00873 $nodePlacementName = $base . '_object_initial_node_placement'; 00874 if ( $http->hasPostVariable( $nodePlacementName ) ) 00875 { 00876 $nodePlacementMap = $http->postVariable( $nodePlacementName ); 00877 if ( isset( $nodePlacementMap[$contentObjectAttribute->attribute( 'id' )] ) ) 00878 $nodePlacement = $nodePlacementMap[$contentObjectAttribute->attribute( 'id' )]; 00879 } 00880 $relationItem = eZObjectRelationListType::createInstance( $class, 00881 $priority + 1, 00882 $contentObjectAttribute, 00883 $nodePlacement ); 00884 if ( $class_content['default_placement'] ) 00885 { 00886 $relationItem['parent_node_id'] = $class_content['default_placement']['node_id']; 00887 } 00888 00889 $content['relation_list'][] = $relationItem; 00890 00891 $hasAttributeInput = false; 00892 $attributeInputVariable = $base . '_has_attribute_input'; 00893 if ( $http->hasPostVariable( $attributeInputVariable ) ) 00894 { 00895 $attributeInputMap = $http->postVariable( $attributeInputVariable ); 00896 if ( isset( $attributeInputMap[$contentObjectAttribute->attribute( 'id' )] ) ) 00897 $hasAttributeInput = $attributeInputMap[$contentObjectAttribute->attribute( 'id' )]; 00898 } 00899 00900 if ( $hasAttributeInput ) 00901 { 00902 $object = $relationItem['object']; 00903 $attributes = $object->contentObjectAttributes(); 00904 foreach ( $attributes as $attribute ) 00905 { 00906 $attributeBase = $base . '_ezorl_init_class_' . $object->attribute( 'contentclass_id' ) . '_attr_' . $attribute->attribute( 'contentclassattribute_id' ); 00907 $oldAttributeID = $attribute->attribute( 'id' ); 00908 $attribute->setAttribute( 'id', false ); 00909 if ( $attribute->fetchInput( $http, $attributeBase ) ) 00910 { 00911 $attribute->setAttribute( 'id', $oldAttributeID ); 00912 $attribute->store(); 00913 } 00914 } 00915 } 00916 00917 $contentObjectAttribute->setContent( $content ); 00918 $contentObjectAttribute->store(); 00919 } 00920 else 00921 00922 eZDebug::writeError( "Unknown class ID $classID, cannot instantiate object", 00923 'eZObjectRelationListType::customObjectAttributeHTTPAction' ); 00924 } 00925 else if ( eZDataType::fetchActionValue( $action, 'edit_objects', $contentobjectID ) or 00926 $action == 'edit_objects' or 00927 $action == 'remove_objects' ) 00928 { 00929 $base = $parameters['base_name']; 00930 $selectionBase = $base . '_selection'; 00931 $selections = array(); 00932 $http = eZHTTPTool::instance(); 00933 if ( $http->hasPostVariable( $selectionBase ) ) 00934 { 00935 $selectionMap = $http->postVariable( $selectionBase ); 00936 $selections = $selectionMap[$contentObjectAttribute->attribute( 'id' )]; 00937 } 00938 if ( $contentobjectID !== false ) 00939 $selections[] = $contentobjectID; 00940 if ( $action == 'edit_objects' or 00941 eZDataType::fetchActionValue( $action, 'edit_objects', $contentobjectID ) ) 00942 { 00943 $content = $contentObjectAttribute->content(); 00944 foreach ( $content['relation_list'] as $key => $relationItem ) 00945 { 00946 if ( !$relationItem['is_modified'] and 00947 in_array( $relationItem['contentobject_id'], $selections ) ) 00948 { 00949 $object = eZContentObject::fetch( $relationItem['contentobject_id'] ); 00950 if ( $object->attribute( 'can_edit' ) ) 00951 { 00952 $content['relation_list'][$key]['is_modified'] = true; 00953 $translationSourceBase = $base . '_translation_source_' . 00954 $contentObjectAttribute->attribute( 'id' ) . '_' . 00955 $relationItem['contentobject_id']; 00956 $languageFrom = false; 00957 if( $http->hasPostVariable( $translationSourceBase ) && 00958 $http->postVariable( $translationSourceBase ) !== '' ) 00959 { 00960 $languageFrom = $http->postVariable( $translationSourceBase ); 00961 } 00962 00963 $version = $object->createNewVersionIn( $contentObjectAttribute->attribute( 'language_code' ), $languageFrom ); 00964 $content['relation_list'][$key]['contentobject_version'] = $version->attribute( 'version' ); 00965 } 00966 } 00967 } 00968 $contentObjectAttribute->setContent( $content ); 00969 $contentObjectAttribute->store(); 00970 } 00971 else if ( $action == 'remove_objects' ) 00972 { 00973 $content = $contentObjectAttribute->content(); 00974 $relationList = $content['relation_list']; 00975 $newRelationList = array(); 00976 foreach( $relationList as $relationItem ) 00977 { 00978 if ( in_array( $relationItem['contentobject_id'], $selections ) ) 00979 { 00980 eZObjectRelationListType::removeRelationObject( $contentObjectAttribute, $relationItem ); 00981 } 00982 else 00983 { 00984 $newRelationList[] = $relationItem; 00985 } 00986 } 00987 $content['relation_list'] = $newRelationList; 00988 $contentObjectAttribute->setContent( $content ); 00989 $contentObjectAttribute->store(); 00990 } 00991 } 00992 else if ( $action == 'browse_objects' ) 00993 { 00994 $module = $parameters['module']; 00995 $redirectionURI = $parameters['current-redirection-uri']; 00996 00997 $ini = eZINI::instance( 'content.ini' ); 00998 $browseType = 'AddRelatedObjectListToDataType'; 00999 $browseTypeINIVariable = $ini->variable( 'ObjectRelationDataTypeSettings', 'ClassAttributeStartNode' ); 01000 foreach ( $browseTypeINIVariable as $value ) 01001 { 01002 list( $classAttributeID, $type ) = explode( ';',$value ); 01003 if ( is_numeric( $classAttributeID ) and 01004 $classAttributeID == $contentObjectAttribute->attribute( 'contentclassattribute_id' ) and 01005 strlen( $type ) > 0 ) 01006 { 01007 $browseType = $type; 01008 break; 01009 } 01010 } 01011 01012 // Fetch the list of "allowed" classes . 01013 // A user can select objects of only those allowed classes when browsing. 01014 $classAttribute = $contentObjectAttribute->attribute( 'contentclass_attribute' ); 01015 $classContent = $classAttribute->content(); 01016 if ( isset( $classContent['class_constraint_list'] ) ) 01017 { 01018 $classConstraintList = $classContent['class_constraint_list']; 01019 } 01020 else 01021 { 01022 $classConstraintList = array(); 01023 } 01024 01025 //include_once( 'kernel/classes/ezcontentbrowse.php' ); 01026 $browseParameters = array( 'action_name' => 'AddRelatedObject_' . $contentObjectAttribute->attribute( 'id' ), 01027 'type' => $browseType, 01028 'browse_custom_action' => array( 'name' => 'CustomActionButton[' . $contentObjectAttribute->attribute( 'id' ) . '_set_object_relation_list]', 01029 'value' => $contentObjectAttribute->attribute( 'id' ) ), 01030 'persistent_data' => array( 'HasObjectInput' => 0 ), 01031 'from_page' => $redirectionURI ); 01032 $base = $parameters['base_name']; 01033 $nodePlacementName = $base . '_browse_for_object_start_node'; 01034 if ( $http->hasPostVariable( $nodePlacementName ) ) 01035 { 01036 $nodePlacement = $http->postVariable( $nodePlacementName ); 01037 if ( isset( $nodePlacement[$contentObjectAttribute->attribute( 'id' )] ) ) 01038 $browseParameters['start_node'] = eZContentBrowse::nodeAliasID( $nodePlacement[$contentObjectAttribute->attribute( 'id' )] ); 01039 } 01040 if ( count($classConstraintList) > 0 ) 01041 $browseParameters['class_array'] = $classConstraintList; 01042 01043 eZContentBrowse::browse( $browseParameters, 01044 $module ); 01045 } 01046 else if ( $action == 'set_object_relation_list' ) 01047 { 01048 if ( !$http->hasPostVariable( 'BrowseCancelButton' ) ) 01049 { 01050 $selectedObjectIDArray = $http->postVariable( "SelectedObjectIDArray" ); 01051 $content = $contentObjectAttribute->content(); 01052 $priority = 0; 01053 for ( $i = 0; $i < count( $content['relation_list'] ); ++$i ) 01054 { 01055 if ( $content['relation_list'][$i]['priority'] > $priority ) 01056 $priority = $content['relation_list'][$i]['priority']; 01057 } 01058 01059 foreach ( $selectedObjectIDArray as $objectID ) 01060 { 01061 // Check if the given object ID has a numeric value, if not go to the next object. 01062 if ( !is_numeric( $objectID ) ) 01063 { 01064 eZDebug::writeError( "Related object ID (objectID): '$objectID', is not a numeric value.", 01065 "eZObjectRelationListType::customObjectAttributeHTTPAction" ); 01066 01067 continue; 01068 } 01069 01070 /* Here we check if current object is already in the related objects list. 01071 * If so, we don't add it again. 01072 * FIXME: Stupid linear search. Maybe there's some better way? 01073 */ 01074 $found = false; 01075 foreach ( $content['relation_list'] as $i ) 01076 { 01077 if ( $i['contentobject_id'] == $objectID ) 01078 { 01079 $found = true; 01080 break; 01081 } 01082 } 01083 if ( $found ) 01084 continue; 01085 01086 ++$priority; 01087 $content['relation_list'][] = $this->appendObject( $objectID, $priority, $contentObjectAttribute ); 01088 $contentObjectAttribute->setContent( $content ); 01089 $contentObjectAttribute->store(); 01090 } 01091 } 01092 } 01093 else 01094 { 01095 eZDebug::writeError( "Unknown custom HTTP action: " . $action, 01096 'eZObjectRelationListType' ); 01097 } 01098 } 01099 01100 /*! 01101 \reimp 01102 */ 01103 function handleCustomObjectHTTPActions( $http, $attributeDataBaseName, 01104 $customActionAttributeArray, $customActionParameters ) 01105 { 01106 $contentObjectAttribute = $customActionParameters['contentobject_attribute']; 01107 $content = $contentObjectAttribute->content(); 01108 foreach( $content['relation_list'] as $relationItem ) 01109 { 01110 if ( $relationItem['is_modified'] ) 01111 { 01112 $subObjectID = $relationItem['contentobject_id']; 01113 $subObjectVersion = $relationItem['contentobject_version']; 01114 01115 $attributeBase = $attributeDataBaseName . '_ezorl_edit_object_' . $subObjectID; 01116 if ( eZContentObject::recursionProtect( $subObjectID ) ) 01117 { 01118 if ( isset ( $content['temp'] ) ) 01119 $object = $content['temp'][$subObjectID]['object']; 01120 else 01121 $object = eZContentObject::fetch( $subObjectID ); 01122 if ( $object ) 01123 $object->handleAllCustomHTTPActions( $attributeBase, 01124 $customActionAttributeArray, 01125 $customActionParameters, 01126 $subObjectVersion ); 01127 } 01128 } 01129 } 01130 } 01131 01132 /*! 01133 \static 01134 \return \c true if the relation item \a $relationItem exist in the content tree. 01135 */ 01136 static function isItemPublished( $relationItem ) 01137 { 01138 return is_numeric( $relationItem['node_id'] ) and $relationItem['node_id'] > 0; 01139 } 01140 01141 /*! 01142 \private 01143 Removes the relation object \a $deletionItem if the item is owned solely by this 01144 version and is not published in the content tree. 01145 */ 01146 function removeRelationObject( $contentObjectAttribute, $deletionItem ) 01147 { 01148 if ( eZObjectRelationListType::isItemPublished( $deletionItem ) ) 01149 { 01150 return; 01151 } 01152 01153 $hostObject = $contentObjectAttribute->attribute( 'object' ); 01154 $hostObjectVersions = $hostObject->versions(); 01155 $isDeletionAllowed = true; 01156 01157 // check if the relation item to be deleted is unique in the domain of all host-object versions 01158 foreach ( $hostObjectVersions as $version ) 01159 { 01160 if ( $isDeletionAllowed and 01161 $version->attribute( 'version' ) != $contentObjectAttribute->attribute( 'version' ) ) 01162 { 01163 $relationAttribute = eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(), 01164 null, 01165 array( 'version' => $version->attribute( 'version' ), 01166 'contentobject_id' => $hostObject->attribute( 'id' ), 01167 'contentclassattribute_id' => $contentObjectAttribute->attribute( 'contentclassattribute_id' ) ) ); 01168 01169 if ( count( $relationAttribute ) > 0 ) 01170 { 01171 $relationContent = $relationAttribute[0]->content(); 01172 if ( is_array( $relationContent ) and 01173 is_array( $relationContent['relation_list'] ) ) 01174 { 01175 foreach( $relationContent['relation_list'] as $relationItem ) 01176 { 01177 if ( $deletionItem['contentobject_id'] == $relationItem['contentobject_id'] && 01178 $deletionItem['contentobject_version'] == $relationItem['contentobject_version'] ) 01179 { 01180 $isDeletionAllowed = false; 01181 break 2; 01182 } 01183 } 01184 } 01185 } 01186 } 01187 } 01188 01189 if ( $isDeletionAllowed ) 01190 { 01191 $subObjectVersion = eZContentObjectVersion::fetchVersion( $deletionItem['contentobject_version'], 01192 $deletionItem['contentobject_id'] ); 01193 if ( $subObjectVersion instanceof eZContentObjectVersion ) 01194 { 01195 $subObjectVersion->removeThis(); 01196 } 01197 else 01198 { 01199 eZDebug::writeError( 'Cleanup of subobject-version failed. Could not fetch object from relation list.\n' . 01200 'Requested subobject id: ' . $deletionItem['contentobject_id'] . '\n' . 01201 'Requested Subobject version: ' . $deletionItem['contentobject_version'], 01202 'eZObjectRelationListType::removeRelationObject' ); 01203 } 01204 } 01205 } 01206 01207 01208 function createInstance( $class, $priority, $contentObjectAttribute, $nodePlacement = false ) 01209 { 01210 $currentObject = $contentObjectAttribute->attribute( 'object' ); 01211 $sectionID = $currentObject->attribute( 'section_id' ); 01212 $object = $class->instantiate( false, $sectionID, false, $contentObjectAttribute->attribute( 'language_code' ) ); 01213 if ( !is_numeric( $nodePlacement ) or $nodePlacement <= 0 ) 01214 $nodePlacement = false; 01215 $object->sync(); 01216 $relationItem = array( 'identifier' => false, 01217 'priority' => $priority, 01218 'in_trash' => false, 01219 'contentobject_id' => $object->attribute( 'id' ), 01220 'contentobject_version' => $object->attribute( 'current_version' ), 01221 'contentobject_remote_id' => $object->attribute( 'remote_id' ), 01222 'node_id' => false, 01223 'parent_node_id' => $nodePlacement, 01224 'contentclass_id' => $class->attribute( 'id' ), 01225 'contentclass_identifier' => $class->attribute( 'identifier' ), 01226 'is_modified' => true ); 01227 $relationItem['object'] = $object; 01228 return $relationItem; 01229 } 01230 01231 function appendObject( $objectID, $priority, $contentObjectAttribute ) 01232 { 01233 $object = eZContentObject::fetch( $objectID ); 01234 $class = $object->attribute( 'content_class' ); 01235 $sectionID = $object->attribute( 'section_id' ); 01236 $relationItem = array( 'identifier' => false, 01237 'priority' => $priority, 01238 'in_trash' => false, 01239 'contentobject_id' => $object->attribute( 'id' ), 01240 'contentobject_version' => $object->attribute( 'current_version' ), 01241 'contentobject_remote_id' => $object->attribute( 'remote_id' ), 01242 'node_id' => $object->attribute( 'main_node_id' ), 01243 'parent_node_id' => $object->attribute( 'main_parent_node_id' ), 01244 'contentclass_id' => $class->attribute( 'id' ), 01245 'contentclass_identifier' => $class->attribute( 'identifier' ), 01246 'is_modified' => false ); 01247 $relationItem['object'] = $object; 01248 return $relationItem; 01249 } 01250 01251 01252 function fixRelatedObjectItem ( $contentObjectAttribute, $objectID, $mode ) 01253 { 01254 switch ( $mode ) 01255 { 01256 case 'move': 01257 { 01258 eZObjectRelationListType::fixRelationsMove( $objectID, $contentObjectAttribute ); 01259 } break; 01260 01261 case 'trash': 01262 { 01263 eZObjectRelationListType::fixRelationsTrash( $objectID, $contentObjectAttribute ); 01264 } break; 01265 01266 case 'restore': 01267 { 01268 eZObjectRelationListType::fixRelationsRestore( $objectID, $contentObjectAttribute ); 01269 } break; 01270 01271 case 'remove': 01272 { 01273 eZObjectRelationListType::fixRelationsRemove( $objectID, $contentObjectAttribute ); 01274 } break; 01275 01276 case 'swap': 01277 { 01278 eZObjectRelationListType::fixRelationsSwap( $objectID, $contentObjectAttribute ); 01279 } break; 01280 01281 default: 01282 { 01283 eZDebug::writeWarning( $mode, 'Unknown mode eZObjectRelationListType::fixRelatedObjectItem()' ); 01284 } break; 01285 } 01286 } 01287 01288 function fixRelationsMove ( $objectID, $contentObjectAttribute ) 01289 { 01290 $this->fixRelationsSwap( $objectID, $contentObjectAttribute ); 01291 } 01292 01293 function fixRelationsTrash ( $objectID, $contentObjectAttribute ) 01294 { 01295 $content = $contentObjectAttribute->attribute( 'content' ); 01296 foreach ( array_keys( $content['relation_list'] ) as $key ) 01297 { 01298 if ( $content['relation_list'][$key]['contentobject_id'] == $objectID ) 01299 { 01300 $content['relation_list'][$key]['in_trash'] = true; 01301 $content['relation_list'][$key]['node_id'] = null; 01302 $content['relation_list'][$key]['parent_node_id']= null; 01303 } 01304 } 01305 eZObjectRelationListType::storeObjectAttributeContent( $contentObjectAttribute, $content ); 01306 $contentObjectAttribute->setContent( $content ); 01307 $contentObjectAttribute->storeData(); 01308 } 01309 01310 function fixRelationsRestore ( $objectID, $contentObjectAttribute ) 01311 { 01312 $content = $contentObjectAttribute->content(); 01313 01314 foreach ( array_keys( $content['relation_list'] ) as $key ) 01315 { 01316 if ( $content['relation_list'][$key]['contentobject_id'] == $objectID ) 01317 { 01318 $priority = $content['relation_list'][$key]['priority']; 01319 $content['relation_list'][$key] = $this->appendObject( $objectID, $priority, $contentObjectAttribute); 01320 } 01321 } 01322 eZObjectRelationListType::storeObjectAttributeContent( $contentObjectAttribute, $content ); 01323 $contentObjectAttribute->setContent( $content ); 01324 $contentObjectAttribute->storeData(); 01325 } 01326 01327 function fixRelationsRemove ( $objectID, $contentObjectAttribute ) 01328 { 01329 $this->removeRelatedObjectItem( $contentObjectAttribute, $objectID ); 01330 $contentObjectAttribute->storeData(); 01331 } 01332 01333 function fixRelationsSwap ( $objectID, $contentObjectAttribute ) 01334 { 01335 $content =& $contentObjectAttribute->content(); 01336 01337 foreach ( array_keys( $content['relation_list'] ) as $key ) 01338 { 01339 $relatedObject =& $content['relation_list'][$key]; 01340 if ( $relatedObject['contentobject_id'] == $objectID ) 01341 { 01342 $priority = $content['relation_list'][$key]['priority']; 01343 $content['relation_list'][$key] = $this->appendObject($objectID, $priority, $contentObjectAttribute ); 01344 } 01345 } 01346 01347 eZObjectRelationListType::storeObjectAttributeContent( $contentObjectAttribute, $content ); 01348 $contentObjectAttribute->setContent( $content ); 01349 $contentObjectAttribute->storeData(); 01350 } 01351 01352 01353 /*! 01354 Returns the content. 01355 */ 01356 function objectAttributeContent( $contentObjectAttribute ) 01357 { 01358 $xmlText = $contentObjectAttribute->attribute( 'data_text' ); 01359 if ( trim( $xmlText ) == '' ) 01360 { 01361 $objectAttributeContent = eZObjectRelationListType::defaultObjectAttributeContent(); 01362 return $objectAttributeContent; 01363 } 01364 $doc = eZObjectRelationListType::parseXML( $xmlText ); 01365 $content = eZObjectRelationListType::createObjectContentStructure( $doc ); 01366 01367 return $content; 01368 } 01369 01370 /*! 01371 \reimp 01372 */ 01373 function classAttributeContent( $classAttribute ) 01374 { 01375 $xmlText = $classAttribute->attribute( 'data_text5' ); 01376 if ( trim( $xmlText ) == '' ) 01377 { 01378 return eZObjectRelationListType::defaultClassAttributeContent(); 01379 } 01380 $doc = eZObjectRelationListType::parseXML( $xmlText ); 01381 return eZObjectRelationListType::createClassContentStructure( $doc ); 01382 } 01383 01384 static function parseXML( $xmlText ) 01385 { 01386 $dom = new DOMDocument( '1.0', 'utf-8' ); 01387 $dom->loadXML( $xmlText ); 01388 return $dom; 01389 } 01390 01391 function defaultClassAttributeContent() 01392 { 01393 return array( 'object_class' => '', 01394 'selection_type' => 0, 01395 'type' => 0, 01396 'class_constraint_list' => array(), 01397 'default_placement' => false ); 01398 } 01399 01400 function defaultObjectAttributeContent() 01401 { 01402 return array( 'relation_list' => array() ); 01403 } 01404 01405 function createClassContentStructure( $doc ) 01406 { 01407 $content = eZObjectRelationListType::defaultClassAttributeContent(); 01408 $root = $doc->documentElement; 01409 $objectPlacement = $root->getElementsByTagName( 'contentobject-placement' )->item( 0 ); 01410 01411 if ( $objectPlacement and $objectPlacement->hasAttributes() ) 01412 { 01413 $nodeID = $objectPlacement->getAttribute( 'node-id' ); 01414 $content['default_placement'] = array( 'node_id' => $nodeID ); 01415 } 01416 $constraints = $root->getElementsByTagName( 'constraints' )->item( 0 ); 01417 if ( $constraints ) 01418 { 01419 $allowedClassList = $constraints->getElementsByTagName( 'allowed-class' ); 01420 foreach( $allowedClassList as $allowedClass ) 01421 { 01422 $content['class_constraint_list'][] = $allowedClass->getAttribute( 'contentclass-identifier' ); 01423 } 01424 } 01425 $type = $root->getElementsByTagName( 'type' )->item( 0 ); 01426 if ( $type ) 01427 { 01428 $content['type'] = $type->getAttribute( 'value' ); 01429 } 01430 $selectionType = $root->getElementsByTagName( 'selection_type' )->item( 0 ); 01431 if ( $selectionType ) 01432 { 01433 $content['selection_type'] = $selectionType->getAttribute( 'value' ); 01434 } 01435 $objectClass = $root->getElementsByTagName( 'object_class' )->item( 0 ); 01436 if ( $objectClass ) 01437 { 01438 $content['object_class'] = $objectClass->getAttribute( 'value' ); 01439 } 01440 01441 return $content; 01442 } 01443 01444 function createObjectContentStructure( $doc ) 01445 { 01446 $content = eZObjectRelationListType::defaultObjectAttributeContent(); 01447 $root = $doc->documentElement; 01448 $relationList = $root->getElementsByTagName( 'relation-list' )->item( 0 ); 01449 if ( $relationList ) 01450 { 01451 $contentObjectArrayXMLMap = eZObjectRelationListType::contentObjectArrayXMLMap(); 01452 $relationItems = $relationList->getElementsByTagName( 'relation-item' ); 01453 foreach ( $relationItems as $relationItem ) 01454 { 01455 $hash = array(); 01456 01457 foreach ( $contentObjectArrayXMLMap as $attributeXMLName => $attributeKey ) 01458 { 01459 $attributeValue = $relationItem->hasAttribute( $attributeXMLName ) ? $relationItem->getAttribute( $attributeXMLName ) : false; 01460 $hash[$attributeKey] = $attributeValue; 01461 } 01462 $content['relation_list'][] = $hash; 01463 } 01464 } 01465 return $content; 01466 } 01467 01468 /*! 01469 \reimp 01470 */ 01471 function customClassAttributeHTTPAction( $http, $action, $classAttribute ) 01472 { 01473 switch ( $action ) 01474 { 01475 case 'browse_for_placement': 01476 { 01477 $module = $classAttribute->currentModule(); 01478 //include_once( 'kernel/classes/ezcontentbrowse.php' ); 01479 $customActionName = 'CustomActionButton[' . $classAttribute->attribute( 'id' ) . '_browsed_for_placement]'; 01480 eZContentBrowse::browse( array( 'action_name' => 'SelectObjectRelationListNode', 01481 'content' => array( 'contentclass_id' => $classAttribute->attribute( 'contentclass_id' ), 01482 'contentclass_attribute_id' => $classAttribute->attribute( 'id' ), 01483 'contentclass_version' => $classAttribute->attribute( 'version' ), 01484 'contentclass_attribute_identifier' => $classAttribute->attribute( 'identifier' ) ), 01485 'persistent_data' => array( $customActionName => '', 01486 'ContentClassHasInput' => false ), 01487 'description_template' => 'design:class/datatype/browse_objectrelationlist_placement.tpl', 01488 'from_page' => $module->currentRedirectionURI() ), 01489 $module ); 01490 } break; 01491 case 'browsed_for_placement': 01492 { 01493 //include_once( 'kernel/classes/ezcontentbrowse.php' ); 01494 $nodeSelection = eZContentBrowse::result( 'SelectObjectRelationListNode' ); 01495 if ( $nodeSelection and count( $nodeSelection ) > 0 ) 01496 { 01497 $nodeID = $nodeSelection[0]; 01498 $content = $classAttribute->content(); 01499 $content['default_placement'] = array( 'node_id' => $nodeID ); 01500 $classAttribute->setContent( $content ); 01501 } 01502 } break; 01503 case 'disable_placement': 01504 { 01505 $content = $classAttribute->content(); 01506 $content['default_placement'] = false; 01507 $classAttribute->setContent( $content ); 01508 } break; 01509 default: 01510 { 01511 eZDebug::writeError( "Unknown objectrelationlist action '$action'", 'eZContentObjectRelationListType::customClassAttributeHTTPAction' ); 01512 } break; 01513 } 01514 } 01515 01516 /*! 01517 Returns the meta data used for storing search indexes. 01518 */ 01519 function metaData( $contentObjectAttribute ) 01520 { 01521 $metaDataArray = array(); 01522 $content = $contentObjectAttribute->content(); 01523 foreach( $content['relation_list'] as $relationItem ) 01524 { 01525 $subObjectID = $relationItem['contentobject_id']; 01526 if ( !$subObjectID ) 01527 continue; 01528 01529 if ( isset( $content['temp'] ) ) 01530 $attributes = $content['temp'][$subObjectID]['attributes']; 01531 else 01532 { 01533 $subObjectVersion = $relationItem['contentobject_version']; 01534 $object = eZContentObject::fetch( $subObjectID ); 01535 if ( eZContentObject::recursionProtect( $subObjectID ) ) 01536 { 01537 if ( !$object ) 01538 { 01539 continue; 01540 } 01541 $attributes = $object->contentObjectAttributes( true, $subObjectVersion ); 01542 } 01543 } 01544 01545 $attributeMetaDataArray = eZContentObjectAttribute::metaDataArray( $attributes ); 01546 $metaDataArray = array_merge( $metaDataArray, $attributeMetaDataArray ); 01547 } 01548 01549 return $metaDataArray; 01550 } 01551 01552 /*! 01553 \return string representation of an contentobjectattribute data for simplified export 01554 01555 */ 01556 function toString( $contentObjectAttribute ) 01557 { 01558 $objectAttributeContent = $contentObjectAttribute->attribute( 'content' ); 01559 $objectIDList = array(); 01560 foreach( $objectAttributeContent['relation_list'] as $objectInfo ) 01561 { 01562 $objectIDList[] = $objectInfo['contentobject_id']; 01563 } 01564 return implode( '-', $objectIDList ); 01565 } 01566 01567 function fromString( $contentObjectAttribute, $string ) 01568 { 01569 $objectIDList = explode( '-', $string ); 01570 01571 $content = eZObjectRelationListType::defaultObjectAttributeContent(); 01572 $priority = 0; 01573 foreach( $objectIDList as $objectID ) 01574 { 01575 $object = eZContentObject::fetch( $objectID ); 01576 if ( $object ) 01577 { 01578 ++$priority; 01579 $content['relation_list'][] = $this->appendObject( $objectID, $priority, $contentObjectAttribute ); 01580 } 01581 else 01582 { 01583 eZDebug::writeWarning( $objectID, "Can not create relation because object is missing" ); 01584 } 01585 } 01586 $contentObjectAttribute->setContent( $content ); 01587 return true; 01588 } 01589 01590 function hasObjectAttributeContent( $contentObjectAttribute ) 01591 { 01592 $content = $contentObjectAttribute->content(); 01593 return count( $content['relation_list'] ) > 0; 01594 } 01595 01596 /*! 01597 \reimp 01598 */ 01599 function isIndexable() 01600 { 01601 return true; 01602 } 01603 01604 /*! 01605 Returns the content of the string for use as a title, 01606 for simplicity this is the name of the first object referenced or false. 01607 */ 01608 function title( $contentObjectAttribute, $name = null ) 01609 { 01610 $objectAttributeContent = $this->objectAttributeContent( $contentObjectAttribute ); 01611 01612 if ( count( $objectAttributeContent['relation_list'] ) > 0 ) 01613 { 01614 $target = $objectAttributeContent['relation_list'][0]; 01615 $targetObject = eZContentObject::fetch( $target['contentobject_id'], false ); 01616 return $targetObject['name']; 01617 } 01618 else 01619 { 01620 return false; 01621 } 01622 } 01623 01624 /*! 01625 \reimp 01626 */ 01627 function serializeContentClassAttribute( $classAttribute, $attributeNode, $attributeParametersNode ) 01628 { 01629 $dom = $attributeParametersNode->ownerDocument; 01630 $content = $classAttribute->content(); 01631 if ( $content['default_placement'] ) 01632 { 01633 $defaultPlacementNode = $dom->createElement( 'default-placement' ); 01634 $defaultPlacementNode->setAttribute( 'node-id', $content['default_placement']['node_id'] ); 01635 $attributeParametersNode->appendChild( $defaultPlacementNode ); 01636 } 01637 01638 $type = is_numeric( $content['type'] ) ? $content['type'] : '0'; 01639 $typeNode = $dom->createElement( 'type' ); 01640 $typeNode->appendChild( $dom->createTextNode( $type ) ); 01641 $attributeParametersNode->appendChild( $typeNode ); 01642 01643 $classConstraintsNode = $dom->createElement( 'class-constraints' ); 01644 $attributeParametersNode->appendChild( $classConstraintsNode ); 01645 foreach ( $content['class_constraint_list'] as $classConstraint ) 01646 { 01647 $classConstraintIdentifier = $classConstraint; 01648 $classConstraintNode = $dom->createElement( 'class-constraint' ); 01649 $classConstraintNode->setAttribute( 'class-identifier', $classConstraintIdentifier ); 01650 $classConstraintsNode->appendChild( $classConstraintNode ); 01651 } 01652 01653 if ( isset( $content['selection_type'] ) && is_numeric( $content['selection_type'] ) ) 01654 { 01655 $selectionTypeNode = $dom->createElement( 'selection-type' ); 01656 $selectionTypeNode->appendChild( $dom->createTextNode( $content['selection_type'] ) ); 01657 $attributeParametersNode->appendChild( $selectionTypeNode ); 01658 } 01659 01660 if ( isset( $content['object_class'] ) && is_numeric( $content['object_class'] ) ) 01661 { 01662 $objectClassNode = $dom->createElement( 'object-class' ); 01663 $objectClassNode->appendChild( $dom->createTextNode( $content['object_class'] ) ); 01664 $attributeParametersNode->appendChild( $objectClassNode ); 01665 } 01666 } 01667 01668 /*! 01669 \reimp 01670 */ 01671 function unserializeContentClassAttribute( $classAttribute, $attributeNode, $attributeParametersNode ) 01672 { 01673 $content = $classAttribute->content(); 01674 $defaultPlacementNode = $attributeParametersNode->getElementsByTagName( 'default-placement' )->item( 0 ); 01675 $content['default_placement'] = false; 01676 01677 if ( $defaultPlacementNode ) 01678 { 01679 $content['default_placement'] = array( 'node_id' => $defaultPlacementNode->getAttribute( 'node-id' ) ); 01680 } 01681 $content['type'] = $attributeParametersNode->getElementsByTagName( 'type' )->item( 0 )->textContent; 01682 $classConstraintsNode = $attributeParametersNode->getElementsByTagName( 'class-constraints' )->item( 0 ); 01683 $classConstraintList = $classConstraintsNode->getElementsByTagName( 'class-constraint' ); 01684 $content['class_constraint_list'] = array(); 01685 foreach ( $classConstraintList as $classConstraintNode ) 01686 { 01687 $classIdentifier = $classConstraintNode->getAttribute( 'class-identifier' ); 01688 $content['class_constraint_list'][] = $classIdentifier; 01689 } 01690 01691 $objectClassNode = $attributeParametersNode->getElementsByTagName( 'object-class' )->item( 0 ); 01692 if ( $objectClassNode ) 01693 { 01694 $content['object_class'] = $objectClassNode->textContent; 01695 } 01696 01697 $selectionTypeNode = $attributeParametersNode->getElementsByTagName( 'selection-type' )->item( 0 ); 01698 if ( $selectionTypeNode ) 01699 { 01700 $content['selection_type'] = $selectionTypeNode->textContent; 01701 } 01702 01703 $classAttribute->setContent( $content ); 01704 $this->storeClassAttributeContent( $classAttribute, $content ); 01705 } 01706 01707 /*! 01708 For each relation export its priority and content object remote_id, like this: 01709 <related-objects> 01710 <relation-list> 01711 <relation-item priority="1" 01712 contentobject-remote-id="faaeb9be3bd98ed09f606fc16d144eca" /> 01713 <relation-item priority="2" 01714 contentobject-remote-id="1bb4fe25487f05527efa8bfd394cecc7" /> 01715 </relation-list> 01716 To do this we fetch content XML and strip all the relation attributes except of "priority" from there, 01717 and add "contentobject-remote-id" attribute. 01718 \reimp 01719 */ 01720 function serializeContentObjectAttribute( $package, $objectAttribute ) 01721 { 01722 $node = $this->createContentObjectAttributeDOMNode( $objectAttribute ); 01723 01724 eZDebug::writeDebug( $objectAttribute->attribute( 'data_text' ), 'xml string from data_text field' ); 01725 if ( $objectAttribute->attribute( 'data_text' ) === null ) 01726 { 01727 $content = array( 'relation_list' => array() ); 01728 $dom = eZObjectRelationListType::createObjectDOMDocument( $content ); 01729 } 01730 else 01731 { 01732 $dom = new DOMDocument( '1.0', 'utf-8' ); 01733 $success = $dom->loadXML( $objectAttribute->attribute( 'data_text' ) ); 01734 } 01735 $rootNode = $dom->documentElement; 01736 $relationList = $rootNode->getElementsByTagName( 'relation-list' )->item( 0 ); 01737 if ( $relationList ) 01738 { 01739 require_once( 'kernel/classes/ezcontentobject.php' ); 01740 $relationItems = $relationList->getElementsByTagName( 'relation-item' ); 01741 for ( $i = 0; $i < $relationItems->length; $i++ ) 01742 { 01743 $relationItem = $relationItems->item( $i ); 01744 // Add related object remote id as attribute to the relation item. 01745 $relatedObjectID = $relationItem->getAttribute( 'contentobject-id' ); 01746 $relatedObject = eZContentObject::fetch( $relatedObjectID ); 01747 $relatedObjectRemoteID = $relatedObject->attribute( 'remote_id' ); 01748 $relationItem->setAttribute( 'contentobject-remote-id', $relatedObjectRemoteID ); 01749 01750 $attributes = $relationItem->attributes; 01751 // Remove all other relation item attributes except of "priority". 01752 // This loop intentionally starts with the last attribute, otherwise you will get unexpected results 01753 for ( $j = $attributes->length - 1; $j >= 0; $j-- ) 01754 { 01755 $attribute = $attributes->item( $j ); 01756 $attrName = $attribute->localName; 01757 01758 eZDebug::writeDebug( $attrName ); 01759 if ( $attrName != 'priority' && $attrName != 'contentobject-remote-id' ) 01760 { 01761 $success = $relationItem->removeAttribute( $attribute->localName ); 01762 if ( !$success ) 01763 { 01764 eZDebug::writeError( 'failed removing attribute ' . $attrName . ' from relation-item element' ); 01765 } 01766 } 01767 } 01768 } 01769 } 01770 01771 eZDebug::writeDebug( $dom->saveXML(), 'old xml doc' ); 01772 01773 $importedRootNode = $node->ownerDocument->importNode( $rootNode, true ); 01774 $node->appendChild( $importedRootNode ); 01775 01776 return $node; 01777 } 01778 01779 /*! 01780 \reimp 01781 */ 01782 function unserializeContentObjectAttribute( $package, $objectAttribute, $attributeNode ) 01783 { 01784 $rootNode = $attributeNode->getElementsByTagName( 'related-objects' )->item( 0 ); 01785 $xmlString = $rootNode ? $rootNode->ownerDocument->saveXML( $rootNode ) : ''; 01786 $objectAttribute->setAttribute( 'data_text', $xmlString ); 01787 } 01788 01789 function postUnserializeContentObjectAttribute( $package, $objectAttribute ) 01790 { 01791 $xmlString = $objectAttribute->attribute( 'data_text' ); 01792 $doc = $this->parseXML( $xmlString ); 01793 $rootNode = $doc->documentElement; 01794 01795 $relationList = $rootNode->getElementsByTagName( 'relation-list' )->item( 0 ); 01796 if ( !$relationList ) 01797 return false; 01798 01799 require_once( 'kernel/classes/ezcontentobject.php' ); 01800 $relationItems = $relationList->getElementsByTagName( 'relation-item' ); 01801 for ( $i = $relationItems->length - 1; $i >= 0; $i-- ) 01802 { 01803 $relationItem = $relationItems->item( $i ); 01804 $relatedObjectRemoteID = $relationItem->getAttribute( 'contentobject-remote-id' ); 01805 $object = eZContentObject::fetchByRemoteID( $relatedObjectRemoteID ); 01806 01807 if ( $object === null ) 01808 { 01809 eZDebug::writeWarning( "Object with remote id '$relatedObjectRemoteID' not found: removing the link.", 01810 'eZObjectRelationListType::unserializeContentObjectAttribute()' ); 01811 $relationItem->parentNode->removeChild( $relationItem ); 01812 continue; 01813 } 01814 01815 $relationItem->setAttribute( 'contentobject-id', $object->attribute( 'id' ) ); 01816 $relationItem->setAttribute( 'contentobject-version', $object->attribute( 'current_version' ) ); 01817 $relationItem->setAttribute( 'node-id', $object->attribute( 'main_node_id' ) ); 01818 $relationItem->setAttribute( 'parent-node-id', $object->attribute( 'main_parent_node_id' ) ); 01819 $relationItem->setAttribute( 'contentclass-id', $object->attribute( 'contentclass_id' ) ); 01820 $relationItem->setAttribute( 'contentclass-identifier', $object->attribute( 'class_identifier' ) ); 01821 } 01822 01823 $newXmlString = $doc->saveXML( $rootNode ); 01824 01825 $objectAttribute->setAttribute( 'data_text', $newXmlString ); 01826 return true; 01827 } 01828 01829 /*! 01830 Removes objects with given ID from the relations list 01831 */ 01832 function removeRelatedObjectItem( $contentObjectAttribute, $objectID ) 01833 { 01834 $xmlText = $contentObjectAttribute->attribute( 'data_text' ); 01835 if ( trim( $xmlText ) == '' ) return; 01836 01837 $doc = eZObjectRelationListType::parseXML( $xmlText ); 01838 01839 $return = false; 01840 $root = $doc->documentElement; 01841 $relationList = $root->getElementsByTagName( 'relation-list' )->item( 0 ); 01842 if ( $relationList ) 01843 { 01844 $relationItems = $relationList->getElementsByTagName( 'relation-item' ); 01845 if ( !empty( $relationItems ) ) 01846 { 01847 foreach( $relationItems as $relationItem ) 01848 { 01849 if ( $relationItem->getAttribute( 'contentobject-id' ) == $objectID ) 01850 { 01851 $relationList->removeChild( $relationItem ); 01852 $return = true; 01853 } 01854 } 01855 } 01856 } 01857 eZObjectRelationListType::storeObjectDOMDocument( $doc, $contentObjectAttribute ); 01858 return $return; 01859 } 01860 01861 /// \privatesection 01862 } 01863 01864 eZDataType::register( eZObjectRelationListType::DATA_TYPE_STRING, "eZObjectRelationListType" ); 01865 01866 ?>