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