[ Index ]
 

Code source de eZ Publish 3.9.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/kernel/classes/datatypes/ezobjectrelationlist/ -> ezobjectrelationlisttype.php (source)

   1  <?php
   2  //
   3  // Definition of eZObjectRelationListType class
   4  //
   5  // Created on: <16-Apr-2002 11:08:14 amos>
   6  //
   7  // SOFTWARE NAME: eZ publish
   8  // SOFTWARE RELEASE: 3.9.0
   9  // BUILD VERSION: 17785
  10  // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS
  11  // SOFTWARE LICENSE: GNU General Public License v2.0
  12  // NOTICE: >
  13  //   This program is free software; you can redistribute it and/or
  14  //   modify it under the terms of version 2.0  of the GNU General
  15  //   Public License as published by the Free Software Foundation.
  16  //
  17  //   This program is distributed in the hope that it will be useful,
  18  //   but WITHOUT ANY WARRANTY; without even the implied warranty of
  19  //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20  //   GNU General Public License for more details.
  21  //
  22  //   You should have received a copy of version 2.0 of the GNU General
  23  //   Public License along with this program; if not, write to the Free
  24  //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  25  //   MA 02110-1301, USA.
  26  //
  27  //
  28  
  29  /*!
  30    \class eZObjectRelationListType ezobjectrelationlisttype.php
  31    \ingroup eZDatatype
  32    \brief A content datatype which handles object relations
  33  
  34  Bugs/missing features:
  35  - No identifier support yet
  36  - Validation and fixup for "Add new object" functionality
  37  - Proper embed views for admin classes
  38  - No translation page support yet (maybe?)
  39  
  40  */
  41  
  42  include_once ( 'kernel/classes/ezdatatype.php' );
  43  include_once ( 'kernel/classes/ezcontentobject.php' );
  44  include_once ( 'lib/ezutils/classes/ezintegervalidator.php' );
  45  include_once ( 'lib/ezutils/classes/ezinputvalidator.php' );
  46  include_once ( 'lib/ezi18n/classes/eztranslatormanager.php' );
  47  include_once ( 'lib/ezxml/classes/ezxml.php' );
  48  
  49  define( "EZ_DATATYPESTRING_OBJECT_RELATION_LIST", "ezobjectrelationlist" );
  50  
  51  class eZObjectRelationListType extends eZDataType
  52  {
  53      /*!
  54       Initializes with a string id and a description.
  55      */
  56      function eZObjectRelationListType()
  57      {
  58          $this->eZDataType( EZ_DATATYPESTRING_OBJECT_RELATION_LIST, ezi18n( 'kernel/classes/datatypes', "Object relations", 'Datatype name' ),
  59                             array( 'serialize_supported' => true ) );
  60      }
  61  
  62      /*!
  63       Validates the input and returns true if the input was
  64       valid for this datatype.
  65      */
  66      function validateObjectAttributeHTTPInput( &$http, $base, &$contentObjectAttribute )
  67      {
  68          $inputParameters =& $contentObjectAttribute->inputParameters();
  69          $contentClassAttribute =& $contentObjectAttribute->contentClassAttribute();
  70          $parameters = $contentObjectAttribute->validationParameters();
  71          if ( isset( $parameters['prefix-name'] ) and
  72               $parameters['prefix-name'] )
  73              $parameters['prefix-name'][] = $contentClassAttribute->attribute( 'name' );
  74          else
  75              $parameters['prefix-name'] = array( $contentClassAttribute->attribute( 'name' ) );
  76  
  77          $status = EZ_INPUT_VALIDATOR_STATE_ACCEPTED;
  78          $postVariableName = $base . "_data_object_relation_list_" . $contentObjectAttribute->attribute( "id" );
  79          $contentClassAttribute =& $contentObjectAttribute->contentClassAttribute();
  80          $classContent = $contentClassAttribute->content();
  81          // Check if selection type is not browse
  82          if ( $classContent['selection_type'] != 0 )
  83          {
  84              $selectedObjectIDArray = $http->hasPostVariable( $postVariableName ) ? $http->postVariable( $postVariableName ) : false;
  85              if ( $contentObjectAttribute->validateIsRequired() and $selectedObjectIDArray === false )
  86              {
  87                  $contentObjectAttribute->setValidationError( ezi18n( 'kernel/classes/datatypes',
  88                                                                       'Missing objectrelation list input.' ) );
  89                  return EZ_INPUT_VALIDATOR_STATE_INVALID;
  90              }
  91              return $status;
  92          }
  93  
  94          $content =& $contentObjectAttribute->content();
  95          if ( $contentObjectAttribute->validateIsRequired() and count( $content['relation_list'] ) == 0 )
  96          {
  97              $contentObjectAttribute->setValidationError( ezi18n( 'kernel/classes/datatypes',
  98                                                                   'Missing objectrelation list input.' ) );
  99              return EZ_INPUT_VALIDATOR_STATE_INVALID;
 100          }
 101  
 102          for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
 103          {
 104              $relationItem = $content['relation_list'][$i];
 105              if ( $relationItem['is_modified'] )
 106              {
 107                  $subObjectID = $relationItem['contentobject_id'];
 108                  $subObjectVersion = $relationItem['contentobject_version'];
 109                  $attributeBase = $base . '_ezorl_edit_object_' . $subObjectID;
 110                  $object =& eZContentObject::fetch( $subObjectID );
 111                  if ( $object )
 112                  {
 113                      $attributes =& $object->contentObjectAttributes( true, $subObjectVersion );
 114  
 115                      $validationResult = $object->validateInput( $attributes, $attributeBase,
 116                                                                  $inputParameters, $parameters );
 117                      $inputValidated = $validationResult['input-validated'];
 118                      $content['temp'][$subObjectID]['require-fixup'] = $validationResult['require-fixup'];
 119                      $statusMap = $validationResult['status-map'];
 120                      foreach ( $statusMap as $statusItem )
 121                      {
 122                          $statusValue = $statusItem['value'];
 123                          $statusAttribute =& $statusItem['attribute'];
 124                          if ( $statusValue == EZ_INPUT_VALIDATOR_STATE_INTERMEDIATE and
 125                               $status == EZ_INPUT_VALIDATOR_STATE_ACCEPTED )
 126                              $status = EZ_INPUT_VALIDATOR_STATE_INTERMEDIATE;
 127                          else if ( $statusValue == EZ_INPUT_VALIDATOR_STATE_INVALID )
 128                          {
 129                              $contentObjectAttribute->setHasValidationError( false );
 130                              $status = EZ_INPUT_VALIDATOR_STATE_INVALID;
 131                          }
 132                      }
 133  
 134                      $content['temp'][$subObjectID]['attributes'] =& $attributes;
 135                      $content['temp'][$subObjectID]['object'] =& $object;
 136                  }
 137              }
 138          }
 139          return $status;
 140      }
 141  
 142      /*!
 143       Validates the input and returns true if the input was
 144       valid for this datatype.
 145      */
 146      function fixupObjectAttributeHTTPInput( &$http, $base, &$contentObjectAttribute )
 147      {
 148          $content =& $contentObjectAttribute->content();
 149          for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
 150          {
 151              $relationItem = $content['relation_list'][$i];
 152              if ( $relationItem['is_modified'] )
 153              {
 154                  $subObjectID = $relationItem['contentobject_id'];
 155                  $subObjectVersion = $relationItem['contentobject_version'];
 156                  $attributeBase = $base . '_ezorl_edit_object_' . $subObjectID;
 157                  $object =& $content['temp'][$subObjectID]['object'];
 158                  $requireFixup = $content['temp'][$subObjectID]['require-fixup'];
 159                  if ( $object and
 160                       $requireFixup )
 161                  {
 162                      $attributes =& $content['temp'][$subObjectID]['attributes'];
 163                      $object->fixupInput( $contentObjectAttributes, $attributeBase );
 164                  }
 165              }
 166          }
 167      }
 168  
 169      /*!
 170       Fetches the http post var string input and stores it in the data instance.
 171      */
 172      function fetchObjectAttributeHTTPInput( &$http, $base, &$contentObjectAttribute )
 173      {
 174          $content =& $contentObjectAttribute->content();
 175          // new object creation
 176          $newObjectPostVariableName = "attribute_" . $contentObjectAttribute->attribute( "id" ) . "_new_object_name";
 177          if ( $http->hasPostVariable( $newObjectPostVariableName ) )
 178          {
 179              $name = $http->postVariable( $newObjectPostVariableName );
 180              if ( !empty( $name ) )
 181              {
 182                  $content['new_object'] = $name;
 183              }
 184          }
 185          $singleSelectPostVariableName = "single_select_" . $contentObjectAttribute->attribute( "id" );
 186          if ( $http->hasPostVariable( $singleSelectPostVariableName ) )
 187              $content['singleselect'] = true;
 188  
 189          $postVariableName = $base . "_data_object_relation_list_" . $contentObjectAttribute->attribute( "id" );
 190          $contentClassAttribute =& $contentObjectAttribute->contentClassAttribute();
 191          $classContent = $contentClassAttribute->content();
 192          // Check if selection type is not browse
 193          if ( $classContent['selection_type'] != 0 )
 194          {
 195              $selectedObjectIDArray = $http->hasPostVariable( $postVariableName ) ? $http->postVariable( $postVariableName ) : false;
 196              $priority = 0;
 197              // We should clear content
 198              $content['relation_list'] = array();
 199              // If we got an empty object id list
 200              if ( $selectedObjectIDArray === false or ( isset( $selectedObjectIDArray[0] ) and $selectedObjectIDArray[0] == 'no_relation' ) )
 201              {
 202                  $contentObjectAttribute->setContent( $content );
 203                  $contentObjectAttribute->store();
 204                  return true;
 205              }
 206  
 207              foreach ( $selectedObjectIDArray as $objectID )
 208              {
 209                  // Check if the given object ID has a numeric value, if not go to the next object.
 210                  if ( !is_numeric( $objectID ) )
 211                  {
 212                      eZDebug::writeError( "Related object ID (objectID): '$objectID', is not a numeric value.",
 213                                           "eZObjectRelationListType::fetchObjectAttributeHTTPInput" );
 214  
 215                      continue;
 216                  }
 217                  ++$priority;
 218                  $content['relation_list'][] = $this->appendObject( $objectID, $priority, $contentObjectAttribute );
 219                  $contentObjectAttribute->setContent( $content );
 220                  $contentObjectAttribute->store();
 221              }
 222              return true;
 223          }
 224  
 225          $contentObjectAttributeID = $contentObjectAttribute->attribute( 'id' );
 226          $priorityBase = $base . '_priority';
 227          $priorities = array();
 228          if ( $http->hasPostVariable( $priorityBase ) )
 229              $priorities = $http->postVariable( $priorityBase );
 230          $reorderedRelationList = array();
 231          // Contains existing priorities
 232          $existsPriorities = array();
 233  
 234          for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
 235          {
 236              $priorities[$contentObjectAttributeID][$i] = (int) $priorities[$contentObjectAttributeID][$i];
 237              $existsPriorities[$i] = $priorities[$contentObjectAttributeID][$i];
 238  
 239              // Change objects' priorities providing their uniqueness.
 240              for ( $j = 0; $j < count( $content['relation_list'] ); ++$j )
 241              {
 242                  if ( $i == $j ) continue;
 243                  if ( $priorities[$contentObjectAttributeID][$i] == $priorities[$contentObjectAttributeID][$j] )
 244                  {
 245                      $index = $priorities[$contentObjectAttributeID][$i];
 246                      while ( in_array( $index, $existsPriorities ) )
 247                          ++$index;
 248                      $priorities[$contentObjectAttributeID][$j] = $index;
 249                  }
 250              }
 251              $relationItem = $content['relation_list'][$i];
 252              if ( $relationItem['is_modified'] )
 253              {
 254                  $subObjectID = $relationItem['contentobject_id'];
 255                  $subObjectVersion = $relationItem['contentobject_version'];
 256                  $attributeBase = $base . '_ezorl_edit_object_' . $subObjectID;
 257                  $object =& $content['temp'][$subObjectID]['object'];
 258                  if ( $object )
 259                  {
 260                      $attributes =& $content['temp'][$subObjectID]['attributes'];
 261  
 262                      $customActionAttributeArray = array();
 263                      $fetchResult = $object->fetchInput( $attributes, $attributeBase,
 264                                                          $customActionAttributeArray,
 265                                                          $contentObjectAttribute->inputParameters() );
 266                      unset( $attributeInputMap );
 267                      $attributeInputMap =& $fetchResult['attribute-input-map'];
 268                      $content['temp'][$subObjectID]['attribute-input-map'] =& $attributeInputMap;
 269                      $content['temp'][$subObjectID]['attributes'] =& $attributes;
 270                      $content['temp'][$subObjectID]['object'] =& $object;
 271                  }
 272              }
 273              if ( isset( $priorities[$contentObjectAttributeID][$i] ) )
 274                  $relationItem['priority'] = $priorities[$contentObjectAttributeID][$i];
 275              $reorderedRelationList[$relationItem['priority']] = $relationItem;
 276          }
 277          ksort( $reorderedRelationList );
 278          unset( $content['relation_list'] );
 279          $content['relation_list'] = array();
 280          reset( $reorderedRelationList );
 281          $i = 0;
 282          while ( list( $key, $relationItem ) = each( $reorderedRelationList ) )
 283          {
 284              $content['relation_list'][] = $relationItem;
 285              $content['relation_list'][$i]['priority'] = $i + 1;
 286              ++$i;
 287          }
 288          $contentObjectAttribute->setContent( $content );
 289          return true;
 290      }
 291  
 292      function createNewObject( &$contentObjectAttribute, $name )
 293      {
 294          $classAttribute =& $contentObjectAttribute->attribute( 'contentclass_attribute' );
 295          $classContent = $classAttribute->content();
 296          $classID = $classContent['object_class'];
 297          if ( !isset( $classID ) or !is_numeric( $classID ) )
 298              return false;
 299  
 300          $defaultPlacementNode = ( is_array( $classContent['default_placement'] ) and isset( $classContent['default_placement']['node_id'] ) ) ? $classContent['default_placement']['node_id'] : false;
 301          if ( !$defaultPlacementNode )
 302          {
 303              eZDebug::writeError( 'Default placement is missing', 'eZObjectRelationListType::createNewObject' );
 304              return false;
 305          }
 306  
 307          $node =& eZContentObjectTreeNode::fetch( $defaultPlacementNode );
 308          // Check if current user can create a new node as child of this node.
 309          if ( !$node or !$node->canCreate() )
 310          {
 311              eZDebug::writeError( 'Default placement is wrong or the current user can\'t create a new node as child of this node.', 'eZObjectRelationListType::createNewObject' );
 312              return false;
 313          }
 314  
 315          $classList =& $node->canCreateClassList( false );
 316          $canCreate = false;
 317          // Check if current user can create object of class (with $classID)
 318          foreach ( $classList as $class )
 319          {
 320              if ( $class['id'] == $classID )
 321              {
 322                  $canCreate = true;
 323                  break;
 324              }
 325          }
 326          if ( !$canCreate )
 327          {
 328              eZDebug::writeError( 'The current user is not allowed to create objects of class (ID=' . $classID . ')', 'eZObjectRelationListType::createNewObject' );
 329              return false;
 330          }
 331  
 332          $class =& eZContentClass::fetch( $classID );
 333          if ( !$class )
 334              return false;
 335  
 336          $currentObject =& $contentObjectAttribute->attribute( 'object' );
 337          $sectionID = $currentObject->attribute( 'section_id' );
 338          //instantiate object, same section, currentuser as owner (i.e. provide false as param)
 339          $newObjectInstance =& $class->instantiate( false, $sectionID );
 340          $nodeassignment = $newObjectInstance->createNodeAssignment( $defaultPlacementNode, true );
 341          $nodeassignment->store();
 342          $newObjectInstance->sync();
 343          include_once ( "lib/ezutils/classes/ezoperationhandler.php" );
 344          $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $newObjectInstance->attribute( 'id' ), 'version' => 1 ) );
 345          // so it updates the attributes
 346          $newObjectInstance->rename( $name );
 347  
 348          return $newObjectInstance->attribute( 'id' );
 349      }
 350  
 351      /*!
 352      */
 353      function storeObjectAttribute( &$attribute )
 354      {
 355          $content = $attribute->content();
 356          if ( isset( $content['new_object'] ) )
 357          {
 358              $newID = $this->createNewObject( $attribute, $content['new_object'] );
 359              // if this is a single element selection mode (radio or dropdown), then the newly created item is the only one selected
 360              if ( $newID )
 361              {
 362                  if ( isset( $content['singleselect'] ) )
 363                      $content['relation_list'] = array();
 364                  $content['relation_list'][] = $this->appendObject( $newID, 0, $attribute );
 365              }
 366              unset( $content['new_object'] );
 367              $attribute->setContent( $content );
 368              $attribute->store();
 369          }
 370  
 371          $contentClassAttributeID = $attribute->ContentClassAttributeID;
 372          $contentObjectID = $attribute->ContentObjectID;
 373          $contentObjectVersion = $attribute->Version;
 374  
 375          $obj = $attribute->object();
 376          //get eZContentObjectVersion
 377          $currVerobj = $obj->version( $contentObjectVersion );
 378  
 379          // create translation List
 380          // $translationList will contain for example eng-GB, ita-IT etc.
 381          $translationList =& $currVerobj->translations( false );
 382  
 383          // get current language_code
 384          $langCode = $attribute->attribute( 'language_code' );
 385          // get count of LanguageCode in translationList
 386          $countTsl = count( $translationList );
 387          // order by asc
 388          sort( $translationList );
 389  
 390          if ( ( $countTsl == 1 ) or ( $countTsl > 1 and $translationList[0] == $langCode ) )
 391          {
 392               eZContentObject::removeContentObjectRelation( false, $contentObjectVersion, $contentObjectID, $contentClassAttributeID, EZ_CONTENT_OBJECT_RELATION_ATTRIBUTE );
 393          }
 394  
 395          for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
 396          {
 397              $relationItem =& $content['relation_list'][$i];
 398  
 399              // Installing content object, postUnserialize is not called yet,
 400              // so object's ID is unknown.
 401              if ( !$relationItem['contentobject_id'] || !isset( $relationItem['contentobject_id'] ) )
 402                  continue;
 403  
 404              $subObjectID = $relationItem['contentobject_id'];
 405              $subObjectVersion = $relationItem['contentobject_version'];
 406  
 407              eZContentObject::addContentObjectRelation( $subObjectID, $contentObjectVersion, $contentObjectID, $contentClassAttributeID, EZ_CONTENT_OBJECT_RELATION_ATTRIBUTE );
 408  
 409              if ( $relationItem['is_modified'] )
 410              {
 411                  // handling sub-objects
 412                  $object =& $content['temp'][$subObjectID]['object'];
 413                  if ( $object )
 414                  {
 415                      $attributes =& $content['temp'][$subObjectID]['attributes'];
 416                      $attributeInputMap =& $content['temp'][$subObjectID]['attribute-input-map'];
 417                      $object->storeInput( $attributes,
 418                                           $attributeInputMap );
 419                      $version = eZContentObjectVersion::fetchVersion( $subObjectVersion, $subObjectID );
 420                      if ( $version )
 421                      {
 422                          $version->setAttribute( 'modified', time() );
 423                          $version->setAttribute( 'status', EZ_VERSION_STATUS_DRAFT );
 424                          $version->store();
 425                      }
 426  
 427                      $object->setAttribute( 'status', EZ_CONTENT_OBJECT_STATUS_DRAFT );
 428                      $object->store();
 429                  }
 430              }
 431          }
 432          return eZObjectRelationListType::storeObjectAttributeContent( $attribute, $content );
 433      }
 434  
 435      /*!
 436       \reimp
 437      */
 438      function onPublish( &$contentObjectAttribute, &$contentObject, &$publishedNodes )
 439      {
 440          $content = $contentObjectAttribute->content();
 441          for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
 442          {
 443              $relationItem =& $content['relation_list'][$i];
 444              if ( $relationItem['is_modified'] )
 445              {
 446                  $subObjectID = $relationItem['contentobject_id'];
 447                  $subObjectVersion = $relationItem['contentobject_version'];
 448                  $object =& eZContentObject::fetch( $subObjectID );
 449  
 450                  if ( $object )
 451                  {
 452                      $class =& $object->contentClass();
 453                      $time = time();
 454  
 455                      // Make the previous version archived
 456                      $currentVersion =& $object->currentVersion();
 457                      $currentVersion->setAttribute( 'status', EZ_VERSION_STATUS_ARCHIVED );
 458                      $currentVersion->setAttribute( 'modified', $time );
 459                      $currentVersion->store();
 460  
 461                      $version = eZContentObjectVersion::fetchVersion( $subObjectVersion, $subObjectID );
 462                      $version->setAttribute( 'modified', $time );
 463                      $version->setAttribute( 'status', EZ_VERSION_STATUS_PUBLISHED );
 464                      $version->store();
 465                      $object->setAttribute( 'status', EZ_CONTENT_OBJECT_STATUS_PUBLISHED );
 466                      if ( !$object->attribute( 'published' ) )
 467                          $object->setAttribute( 'published', $time );
 468                      $object->setAttribute( 'modified', $time );
 469                      $object->setAttribute( 'current_version', $version->attribute( 'version' ) );
 470                      $object->setAttribute( 'is_published', true );
 471                      $objectName = $class->contentObjectName( $object, $version->attribute( 'version' ) );
 472                      $object->setName( $objectName, $version->attribute( 'version' ) );
 473                      $object->store();
 474                  }
 475                  if ( $relationItem['parent_node_id'] > 0 )
 476                  {
 477                      if ( !eZNodeAssignment::fetch( $object->attribute( 'id' ), $object->attribute( 'current_version' ), $relationItem['parent_node_id'], false ) )
 478                      {
 479                          $nodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $object->attribute( 'id' ),
 480                                                                             'contentobject_version' => $object->attribute( 'current_version' ),
 481                                                                             'parent_node' => $relationItem['parent_node_id'],
 482                                                                             'sort_field' => 2,
 483                                                                             'sort_order' => 0,
 484                                                                             'is_main' => 1 ) );
 485                          $nodeAssignment->store();
 486                      }
 487                      $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $object->attribute( 'id' ),
 488                                                                                                   'version' => $object->attribute( 'current_version' ) ) );
 489                      $objectNodeID = $object->attribute( 'main_node_id' );
 490                      $content['relation_list'][$i]['node_id'] = $objectNodeID;
 491                  }
 492                  else
 493                  {
 494                      if ( !eZNodeAssignment::fetch( $object->attribute( 'id' ), $object->attribute( 'current_version' ), $contentObject->attribute( 'main_node_id' ), false ) )
 495                      {
 496                          $nodeAssignment = eZNodeAssignment::create( array( 'contentobject_id' => $object->attribute( 'id' ),
 497                                                                             'contentobject_version' => $object->attribute( 'current_version' ),
 498                                                                             'parent_node' => $contentObject->attribute( 'main_node_id' ),
 499                                                                             'sort_field' => 2,
 500                                                                             'sort_order' => 0,
 501                                                                             'is_main' => 1 ) );
 502                          $nodeAssignment->store();
 503                      }
 504                  }
 505                  $content['relation_list'][$i]['is_modified'] = false;
 506              }
 507          }
 508          eZObjectRelationListType::storeObjectAttributeContent( $contentObjectAttribute, $content );
 509          $contentObjectAttribute->setContent( $content );
 510          $contentObjectAttribute->store();
 511      }
 512  
 513      function initializeObjectAttribute( &$contentObjectAttribute, $currentVersion, &$originalContentObjectAttribute )
 514      {
 515          if ( $currentVersion != false )
 516          {
 517              $dataText = $originalContentObjectAttribute->attribute( 'data_text' );
 518              $contentObjectAttribute->setAttribute( 'data_text', $dataText );
 519  
 520              if ( $contentObjectAttribute->attribute( 'contentobject_id' ) != $originalContentObjectAttribute->attribute( 'contentobject_id' ) )
 521              {
 522                  $classContent = eZObjectRelationListType::defaultClassAttributeContent();
 523                  if ( !$classContent['default_placement'] )
 524                  {
 525                      $content = $originalContentObjectAttribute->content();
 526                      for ( $i = 0; $i < count( $content['relation_list'] ); $i++ )
 527                      {
 528                          $relationItem =& $content['relation_list'][$i];
 529  
 530                          // create related object copies only if they are subobjects
 531                          if ( !isset( $relationItem['node_id'] ) )
 532                          {
 533                              $object =& eZContentObject::fetch( $relationItem['contentobject_id'] );
 534                              $newObject =& $object->copy( true );
 535                              $relationItem['contentobject_id'] = $newObject->attribute( 'id' );
 536                          }
 537                      }
 538                      $contentObjectAttribute->setContent( $content );
 539                      $contentObjectAttribute->store();
 540                  }
 541              }
 542          }
 543      }
 544  
 545      /*!
 546       \reimp
 547      */
 548      function validateClassAttributeHTTPInput( &$http, $base, &$classAttribute )
 549      {
 550          return EZ_INPUT_VALIDATOR_STATE_ACCEPTED;
 551      }
 552  
 553      /*!
 554       \reimp
 555      */
 556      function fixupClassAttributeHTTPInput( &$http, $base, &$classAttribute )
 557      {
 558      }
 559  
 560      /*!
 561       \reimp
 562      */
 563      function fetchClassAttributeHTTPInput( &$http, $base, &$classAttribute )
 564      {
 565          $content = $classAttribute->content();
 566          $postVariable = 'ContentClass_ezobjectrelationlist_class_list_' . $classAttribute->attribute( 'id' );
 567          if ( $http->hasPostVariable( $postVariable ) )
 568          {
 569              $constrainedList = $http->postVariable( $postVariable );
 570              $constrainedClassList = array();
 571              foreach ( $constrainedList as $constraint )
 572              {
 573                  if ( trim( $constraint ) != '' )
 574                      $constrainedClassList[] = $constraint;
 575              }
 576              $content['class_constraint_list'] = $constrainedClassList;
 577          }
 578          $typeVariable = 'ContentClass_ezobjectrelationlist_type_' . $classAttribute->attribute( 'id' );
 579          if ( $http->hasPostVariable( $typeVariable ) )
 580          {
 581              $type = $http->postVariable( $typeVariable );
 582              $content['type'] = $type;
 583          }
 584          $selectionTypeVariable = 'ContentClass_ezobjectrelationlist_selection_type_' . $classAttribute->attribute( 'id' );
 585          if ( $http->hasPostVariable( $selectionTypeVariable ) )
 586          {
 587              $selectionType = $http->postVariable( $selectionTypeVariable );
 588              $content['selection_type'] = $selectionType;
 589          }
 590          $objectClassVariable = 'ContentClass_ezobjectrelation_object_class_' . $classAttribute->attribute( 'id' );
 591          if ( $http->hasPostVariable( $objectClassVariable ) )
 592          {
 593              $content['object_class'] = $http->postVariable( $objectClassVariable );
 594          }
 595  
 596          $classAttribute->setContent( $content );
 597          $classAttribute->store();
 598          return true;
 599      }
 600  
 601      /*!
 602       \reimp
 603      */
 604      function initializeClassAttribute( &$classAttribute )
 605      {
 606          $xmlText = $classAttribute->attribute( 'data_text5' );
 607          if ( trim( $xmlText ) == '' )
 608          {
 609              $content = eZObjectRelationListType::defaultClassAttributeContent();
 610              return eZObjectRelationListType::storeClassAttributeContent( $classAttribute, $content );
 611          }
 612      }
 613  
 614      /*!
 615       \reimp
 616      */
 617      function preStoreClassAttribute( &$classAttribute, $version )
 618      {
 619          $content = $classAttribute->content();
 620          return eZObjectRelationListType::storeClassAttributeContent( $classAttribute, $content );
 621      }
 622  
 623      function storeClassAttributeContent( &$classAttribute, $content )
 624      {
 625          if ( is_array( $content ) )
 626          {
 627              $doc = eZObjectRelationListType::createClassDOMDocument( $content );
 628              eZObjectRelationListType::storeClassDOMDocument( $doc, $classAttribute );
 629              return true;
 630          }
 631          return false;
 632      }
 633  
 634      function storeObjectAttributeContent( &$objectAttribute, $content )
 635      {
 636          if ( is_array( $content ) )
 637          {
 638              $doc = eZObjectRelationListType::createObjectDOMDocument( $content );
 639              eZObjectRelationListType::storeObjectDOMDocument( $doc, $objectAttribute );
 640              return true;
 641          }
 642          return false;
 643      }
 644  
 645      function storeClassDOMDocument( &$doc, &$classAttribute )
 646      {
 647          $docText = eZObjectRelationListType::domString( $doc );
 648          $classAttribute->setAttribute( 'data_text5', $docText );
 649      }
 650  
 651      function storeObjectDOMDocument( &$doc, &$objectAttribute )
 652      {
 653          $docText = eZObjectRelationListType::domString( $doc );
 654          $objectAttribute->setAttribute( 'data_text', $docText );
 655      }
 656  
 657      /*!
 658       \static
 659       \return the XML structure in \a $domDocument as text.
 660               It will take of care of the necessary charset conversions
 661               for content storage.
 662      */
 663      function domString( &$domDocument )
 664      {
 665          $ini =& eZINI::instance();
 666          $xmlCharset = $ini->variable( 'RegionalSettings', 'ContentXMLCharset' );
 667          if ( $xmlCharset == 'enabled' )
 668          {
 669              include_once ( 'lib/ezi18n/classes/eztextcodec.php' );
 670              $charset = eZTextCodec::internalCharset();
 671          }
 672          else if ( $xmlCharset == 'disabled' )
 673              $charset = true;
 674          else
 675              $charset = $xmlCharset;
 676          if ( $charset !== true )
 677          {
 678              include_once ( 'lib/ezi18n/classes/ezcharsetinfo.php' );
 679              $charset = eZCharsetInfo::realCharsetCode( $charset );
 680          }
 681          $domString = $domDocument->toString( $charset );
 682          return $domString;
 683      }
 684  
 685      function createClassDOMDocument( $content )
 686      {
 687          $doc = new eZDOMDocument( 'ObjectRelationList' );
 688          $root = $doc->createElementNode( 'related-objects' );
 689          $constraints = $doc->createElementNode( 'constraints' );
 690          foreach ( $content['class_constraint_list'] as $constraintClassIdentifier )
 691          {
 692              unset( $constraintElement );
 693              $constraintElement = $doc->createElementNode( 'allowed-class',
 694                                                             array( 'contentclass-identifier' => $constraintClassIdentifier ) );
 695              $constraints->appendChild( $constraintElement );
 696          }
 697          $root->appendChild( $constraints );
 698          $constraintType = $doc->createElementNode( 'type', array( 'value' => $content['type'] ) );
 699          $root->appendChild( $constraintType );
 700          $selectionType = $doc->createElementNode( 'selection_type', array( 'value' => $content['selection_type'] ) );
 701          $root->appendChild( $selectionType );
 702          $objectClass = $doc->createElementNode( 'object_class', array( 'value' => $content['object_class'] ) );
 703          $root->appendChild( $objectClass );
 704  
 705          $placementAttributes = array();
 706          if ( $content['default_placement'] )
 707              $placementAttributes['node-id'] = $content['default_placement']['node_id'];
 708          $root->appendChild( $doc->createElementNode( 'contentobject-placement',
 709                                                       $placementAttributes ) );
 710          $doc->setRoot( $root );
 711          return $doc;
 712      }
 713  
 714      function createObjectDOMDocument( $content )
 715      {
 716          $doc = new eZDOMDocument( 'ObjectRelationList' );
 717          $root = $doc->createElementNode( 'related-objects' );
 718          $relationList = $doc->createElementNode( 'relation-list' );
 719          foreach ( $content['relation_list'] as $relationItem )
 720          {
 721              unset( $relationElement );
 722              $relationElement = $doc->createElementNode( 'relation-item' );
 723              $relationElement->appendAttributes( $relationItem,
 724                                                  eZObjectRelationListType::contentObjectArrayXMLMap() );
 725              $relationList->appendChild( $relationElement );
 726          }
 727          $root->appendChild( $relationList );
 728          $doc->setRoot( $root );
 729          return $doc;
 730      }
 731  
 732      function contentObjectArrayXMLMap()
 733      {
 734          return array( 'identifier' => 'identifier',
 735                        'priority' => 'priority',
 736                        'contentobject-id' => 'contentobject_id',
 737                        'contentobject-version' => 'contentobject_version',
 738                        'node-id' => 'node_id',
 739                        'parent-node-id' => 'parent_node_id',
 740                        'contentclass-id' => 'contentclass_id',
 741                        'contentclass-identifier' => 'contentclass_identifier',
 742                        'is-modified' => 'is_modified',
 743                        'contentobject-remote-id' => 'contentobject_remote_id' );
 744      }
 745  
 746      /*!
 747       \reimp
 748      */
 749      function deleteStoredObjectAttribute( &$objectAttribute, $version = null )
 750      {
 751          $content =& $objectAttribute->content();
 752          if ( is_array( $content ) and
 753               is_array( $content['relation_list'] ) )
 754          {
 755              $db =& eZDB::instance();
 756              $db->begin();
 757              foreach ( $content['relation_list'] as $deletionItem )
 758              {
 759                  eZObjectRelationListType::removeRelationObject( $objectAttribute, $deletionItem );
 760              }
 761              $db->commit();
 762          }
 763      }
 764  
 765      /*!
 766       \reimp
 767      */
 768      function customObjectAttributeHTTPAction( $http, $action, &$contentObjectAttribute, $parameters )
 769      {
 770          $contentobjectID = false;
 771          if ( eZDataType::fetchActionValue( $action, 'new_class', $classID ) or
 772               $action == 'new_class' )
 773          {
 774              if ( $action == 'new_class' )
 775              {
 776                  $base = $parameters['base_name'];
 777                  $classVariableName = $base . '_new_class';
 778                  if ( $http->hasPostVariable( $classVariableName ) )
 779                  {
 780                      $classVariable = $http->postVariable( $classVariableName );
 781                      $classID = $classVariable[$contentObjectAttribute->attribute( 'id' )];
 782                      $class = eZContentClass::fetch( $classID );
 783                  }
 784                  else
 785                      return false;
 786              }
 787              else
 788                  $class = eZContentClass::fetch( $classID );
 789              if ( $class )
 790              {
 791                  $classAttribute =& $contentObjectAttribute->attribute( 'contentclass_attribute' );
 792                  $class_content = $classAttribute->content();
 793                  $content = $contentObjectAttribute->content();
 794                  $priority = 0;
 795                  for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
 796                  {
 797                      if ( $content['relation_list'][$i]['priority'] > $priority )
 798                          $priority = $content['relation_list'][$i]['priority'];
 799                  }
 800  
 801                  $base = $parameters['base_name'];
 802                  $nodePlacement = false;
 803                  $nodePlacementName = $base . '_object_initial_node_placement';
 804                  if ( $http->hasPostVariable( $nodePlacementName ) )
 805                  {
 806                      $nodePlacementMap = $http->postVariable( $nodePlacementName );
 807                      if ( isset( $nodePlacementMap[$contentObjectAttribute->attribute( 'id' )] ) )
 808                          $nodePlacement = $nodePlacementMap[$contentObjectAttribute->attribute( 'id' )];
 809                  }
 810                  $relationItem = eZObjectRelationListType::createInstance( $class,
 811                                                                            $priority + 1,
 812                                                                            $contentObjectAttribute,
 813                                                                            $nodePlacement );
 814                  if ( $class_content['default_placement'] )
 815                  {
 816                      $relationItem['parent_node_id'] = $class_content['default_placement']['node_id'];
 817                  }
 818  
 819                  $content['relation_list'][] = $relationItem;
 820  
 821                  $hasAttributeInput = false;
 822                  $attributeInputVariable = $base . '_has_attribute_input';
 823                  if ( $http->hasPostVariable( $attributeInputVariable ) )
 824                  {
 825                      $attributeInputMap = $http->postVariable( $attributeInputVariable );
 826                      if ( isset( $attributeInputMap[$contentObjectAttribute->attribute( 'id' )] ) )
 827                          $hasAttributeInput = $attributeInputMap[$contentObjectAttribute->attribute( 'id' )];
 828                  }
 829  
 830                  if ( $hasAttributeInput )
 831                  {
 832                      $object =& $relationItem['object'];
 833                      $attributes =& $object->contentObjectAttributes();
 834                      foreach ( array_keys( $attributes ) as $key )
 835                      {
 836                          $attribute =& $attributes[$key];
 837                          $attributeBase = $base . '_ezorl_init_class_' . $object->attribute( 'contentclass_id' ) . '_attr_' . $attribute->attribute( 'contentclassattribute_id' );
 838                          $oldAttributeID = $attribute->attribute( 'id' );
 839                          $attribute->setAttribute( 'id', false );
 840                          if ( $attribute->fetchInput( $http, $attributeBase ) )
 841                          {
 842                              $attribute->setAttribute( 'id', $oldAttributeID );
 843                              $attribute->store();
 844                          }
 845                      }
 846                  }
 847  
 848                  $contentObjectAttribute->setContent( $content );
 849                  $contentObjectAttribute->store();
 850              }
 851              else
 852                  eZDebug::writeError( "Unknown class ID $classID, cannot instantiate object",
 853                                       'eZObjectRelationListType::customObjectAttributeHTTPAction' );
 854          }
 855          else if ( eZDataType::fetchActionValue( $action, 'edit_objects', $contentobjectID ) or
 856                    $action == 'edit_objects' or
 857                    $action == 'remove_objects' )
 858          {
 859              $base = $parameters['base_name'];
 860              $selectionBase = $base . '_selection';
 861              $selections = array();
 862              $http =& eZHTTPTool::instance();
 863              if ( $http->hasPostVariable( $selectionBase ) )
 864              {
 865                  $selectionMap = $http->postVariable( $selectionBase );
 866                  $selections = $selectionMap[$contentObjectAttribute->attribute( 'id' )];
 867              }
 868              if ( $contentobjectID !== false )
 869                  $selections[] = $contentobjectID;
 870              if ( $action == 'edit_objects' or
 871                   eZDataType::fetchActionValue( $action, 'edit_objects', $contentobjectID ) )
 872              {
 873                  $content = $contentObjectAttribute->content();
 874                  $relationList =& $content['relation_list'];
 875                  for ( $i = 0; $i < count( $relationList ); ++$i )
 876                  {
 877                      $relationItem =& $relationList[$i];
 878                      if ( !$relationItem['is_modified'] and
 879                           in_array( $relationItem['contentobject_id'], $selections ) )
 880                      {
 881                          $object =& eZContentObject::fetch( $relationItem['contentobject_id'] );
 882                          if ( $object->attribute( 'can_edit' ) )
 883                          {
 884                              $relationItem['is_modified'] = true;
 885                              $version = $object->createNewVersion( $relationItem['contentobject_version'] );
 886                              $relationItem['contentobject_version'] = $version->attribute( 'version' );
 887                          }
 888                      }
 889                  }
 890                  $contentObjectAttribute->setContent( $content );
 891                  $contentObjectAttribute->store();
 892              }
 893              else if ( $action == 'remove_objects' )
 894              {
 895                  $content = $contentObjectAttribute->content();
 896                  $relationList =& $content['relation_list'];
 897                  $newRelationList = array();
 898                  for ( $i = 0; $i < count( $relationList ); ++$i )
 899                  {
 900                      $relationItem = $relationList[$i];
 901                      if ( in_array( $relationItem['contentobject_id'], $selections ) )
 902                      {
 903                          eZObjectRelationListType::removeRelationObject( $contentObjectAttribute, $relationItem );
 904                      }
 905                      else
 906                          $newRelationList[] = $relationItem;
 907                  }
 908                  $content['relation_list'] =& $newRelationList;
 909                  $contentObjectAttribute->setContent( $content );
 910                  $contentObjectAttribute->store();
 911              }
 912          }
 913          else if ( $action == 'browse_objects' )
 914          {
 915              $module =& $parameters['module'];
 916              $redirectionURI = $parameters['current-redirection-uri'];
 917  
 918              $ini = eZINI::instance( 'content.ini' );
 919              $browseType = 'AddRelatedObjectListToDataType';
 920              $browseTypeINIVariable = $ini->variable( 'ObjectRelationDataTypeSettings', 'ClassAttributeStartNode' );
 921              foreach ( $browseTypeINIVariable as $value )
 922              {
 923                  list( $classAttributeID, $type ) = explode( ';',$value );
 924                  if ( is_numeric( $classAttributeID ) and
 925                       $classAttributeID == $contentObjectAttribute->attribute( 'contentclassattribute_id' ) and
 926                       strlen( $type ) > 0 )
 927                  {
 928                      $browseType = $type;
 929                      break;
 930                  }
 931              }
 932  
 933              // Fetch the list of "allowed" classes .
 934              // A user can select objects of only those allowed classes when browsing.
 935              $classAttribute =& $contentObjectAttribute->attribute( 'contentclass_attribute' );
 936              $classContent   =& $classAttribute->content();
 937              if ( isset( $classContent['class_constraint_list'] ) )
 938                  $classConstraintList =& $classContent['class_constraint_list'];
 939              else
 940                  $classConstraintList = array();
 941  
 942              include_once ( 'kernel/classes/ezcontentbrowse.php' );
 943              $browseParameters = array( 'action_name' => 'AddRelatedObject_' . $contentObjectAttribute->attribute( 'id' ),
 944                                         'type' =>  $browseType,
 945                                         'browse_custom_action' => array( 'name' => 'CustomActionButton[' . $contentObjectAttribute->attribute( 'id' ) . '_set_object_relation_list]',
 946                                                                          'value' => $contentObjectAttribute->attribute( 'id' ) ),
 947                                         'persistent_data' => array( 'HasObjectInput' => 0 ),
 948                                         'from_page' => $redirectionURI );
 949              $base = $parameters['base_name'];
 950              $nodePlacementName = $base . '_browse_for_object_start_node';
 951              if ( $http->hasPostVariable( $nodePlacementName ) )
 952              {
 953                  $nodePlacement = $http->postVariable( $nodePlacementName );
 954                  if ( isset( $nodePlacement[$contentObjectAttribute->attribute( 'id' )] ) )
 955                      $browseParameters['start_node'] = eZContentBrowse::nodeAliasID( $nodePlacement[$contentObjectAttribute->attribute( 'id' )] );
 956              }
 957              if ( count($classConstraintList) > 0 )
 958                  $browseParameters['class_array'] = $classConstraintList;
 959  
 960              eZContentBrowse::browse( $browseParameters,
 961                                       $module );
 962          }
 963          else if ( $action == 'set_object_relation_list' )
 964          {
 965              if ( !$http->hasPostVariable( 'BrowseCancelButton' ) )
 966              {
 967                  $selectedObjectIDArray = $http->postVariable( "SelectedObjectIDArray" );
 968                  $content = $contentObjectAttribute->content();
 969                  $priority = 0;
 970                  for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
 971                  {
 972                      if ( $content['relation_list'][$i]['priority'] > $priority )
 973                          $priority = $content['relation_list'][$i]['priority'];
 974                  }
 975  
 976                  foreach ( $selectedObjectIDArray as $objectID )
 977                  {
 978                      // Check if the given object ID has a numeric value, if not go to the next object.
 979                      if ( !is_numeric( $objectID ) )
 980                      {
 981                          eZDebug::writeError( "Related object ID (objectID): '$objectID', is not a numeric value.",
 982                              "eZObjectRelationListType::customObjectAttributeHTTPAction" );
 983  
 984                          continue;
 985                      }
 986  
 987                      /* Here we check if current object is already in the related objects list.
 988                       * If so, we don't add it again.
 989                       * FIXME: Stupid linear search. Maybe there's some better way?
 990                       */
 991                      $found = false;
 992                      foreach ( $content['relation_list'] as $i )
 993                      {
 994                          if ( $i['contentobject_id'] == $objectID )
 995                          {
 996                              $found = true;
 997                              break;
 998                          }
 999                      }
1000                      if ( $found )
1001                          continue;
1002  
1003                      ++$priority;
1004                      $content['relation_list'][] = $this->appendObject( $objectID, $priority, $contentObjectAttribute );
1005                      $contentObjectAttribute->setContent( $content );
1006                      $contentObjectAttribute->store();
1007                  }
1008              }
1009          }
1010          else
1011          {
1012              eZDebug::writeError( "Unknown custom HTTP action: " . $action,
1013                                   'eZObjectRelationListType' );
1014          }
1015      }
1016  
1017      /*!
1018       \reimp
1019      */
1020      function handleCustomObjectHTTPActions( &$http, $attributeDataBaseName,
1021                                              $customActionAttributeArray, $customActionParameters )
1022      {
1023          $contentObjectAttribute =& $customActionParameters['contentobject_attribute'];
1024          $content =& $contentObjectAttribute->content();
1025          for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
1026          {
1027              $relationItem = $content['relation_list'][$i];
1028              $subObjectID = $relationItem['contentobject_id'];
1029              $subObjectVersion = $relationItem['contentobject_version'];
1030  
1031              $attributeBase = $attributeDataBaseName . '_ezorl_edit_object_' . $subObjectID;
1032              $object =& $content['temp'][$subObjectID]['object'];
1033              if ( eZContentObject::recursionProtect( $subObjectID ) )
1034              {
1035                  if ( !$object )
1036                      $object =& eZContentObject::fetch( $subObjectID );
1037                  if ( $object )
1038                      $object->handleAllCustomHTTPActions( $attributeBase,
1039                                                           $customActionAttributeArray,
1040                                                           $customActionParameters,
1041                                                           $subObjectVersion );
1042              }
1043          }
1044      }
1045  
1046      /*!
1047       \static
1048       \return \c true if the relation item \a $relationItem exist in the content tree.
1049      */
1050      function isItemPublished( &$relationItem )
1051      {
1052          return is_numeric( $relationItem['node_id'] ) and $relationItem['node_id'] > 0;
1053      }
1054  
1055      /*!
1056       \private
1057       Removes the relation object \a $deletionItem if the item is owned solely by this
1058       version and is not published in the content tree.
1059      */
1060      function removeRelationObject( &$contentObjectAttribute, &$deletionItem )
1061      {
1062          if ( eZObjectRelationListType::isItemPublished( $deletionItem ) )
1063          {
1064              return;
1065          }
1066  
1067          $hostObject =& $contentObjectAttribute->attribute( 'object' );
1068          $hostObjectVersions =& $hostObject->versions();
1069          $isDeletionAllowed = true;
1070  
1071          // check if the relation item to be deleted is unique in the domain of all host-object versions
1072          foreach ( $hostObjectVersions as $version )
1073          {
1074              if ( $isDeletionAllowed and
1075                   $version->attribute( 'version' ) != $contentObjectAttribute->attribute( 'version' ) )
1076              {
1077                  $relationAttribute = eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(),
1078                                                                             null,
1079                                                                             array( 'version' => $version->attribute( 'version' ),
1080                                                                                    'contentobject_id' => $hostObject->attribute( 'id' ),
1081                                                                                    'contentclassattribute_id' => $contentObjectAttribute->attribute( 'contentclassattribute_id' ) ) );
1082  
1083                  if ( count( $relationAttribute ) > 0 )
1084                  {
1085                      $relationContent =& $relationAttribute[0]->content();
1086                      if ( is_array( $relationContent ) and
1087                           is_array( $relationContent['relation_list'] ) )
1088                      {
1089                          $relationContentCount = count( $relationContent['relation_list'] );
1090                          for ( $i = 0; $i < $relationContentCount; ++$i )
1091                          {
1092                              if ( $deletionItem['contentobject_id'] == $relationContent['relation_list'][$i]['contentobject_id'] &&
1093                                   $deletionItem['contentobject_version'] == $relationContent['relation_list'][$i]['contentobject_version'] )
1094                              {
1095                                  $isDeletionAllowed = false;
1096                                  break 2;
1097                              }
1098                          }
1099                      }
1100                  }
1101              }
1102          }
1103  
1104          if ( $isDeletionAllowed )
1105          {
1106              $subObjectVersion = eZContentObjectVersion::fetchVersion( $deletionItem['contentobject_version'],
1107                                                                         $deletionItem['contentobject_id'] );
1108              if ( get_class( $subObjectVersion ) == 'ezcontentobjectversion' )
1109              {
1110                  $subObjectVersion->remove();
1111              }
1112              else
1113              {
1114                  eZDebug::writeError( 'Cleanup of subobject-version failed. Could not fetch object from relation list.\n' .
1115                                       'Requested subobject id: ' . $relationItem['contentobject_id'] . '\n' .
1116                                       'Requested Subobject version: ' . $relationItem['contentobject_version'],
1117                                       'eZObjectRelationListType::removeRelationObject' );
1118              }
1119          }
1120      }
1121  
1122  
1123      function createInstance( &$class, $priority, &$contentObjectAttribute, $nodePlacement = false )
1124      {
1125          $currentObject =& $contentObjectAttribute->attribute( 'object' );
1126          $sectionID = $currentObject->attribute( 'section_id' );
1127          $object = $class->instantiate( false, $sectionID );
1128          if ( !is_numeric( $nodePlacement ) or $nodePlacement <= 0 )
1129              $nodePlacement = false;
1130          $object->sync();
1131          $relationItem = array( 'identifier' => false,
1132                                 'priority' => $priority,
1133                                 'contentobject_id' => $object->attribute( 'id' ),
1134                                 'contentobject_version' => $object->attribute( 'current_version' ),
1135                                 'node_id' => false,
1136                                 'parent_node_id' => $nodePlacement,
1137                                 'contentclass_id' => $class->attribute( 'id' ),
1138                                 'contentclass_identifier' => $class->attribute( 'identifier' ),
1139                                 'is_modified' => true );
1140          $relationItem['object'] =& $object;
1141          return $relationItem;
1142      }
1143  
1144      function appendObject( $objectID, $priority, &$contentObjectAttribute )
1145      {
1146          $object =& eZContentObject::fetch( $objectID );
1147          $class =& $object->attribute( 'content_class' );
1148          $sectionID = $object->attribute( 'section_id' );
1149          $relationItem = array( 'identifier' => false,
1150                                 'priority' => $priority,
1151                                 'contentobject_id' => $object->attribute( 'id' ),
1152                                 'contentobject_version' => $object->attribute( 'current_version' ),
1153                                 'node_id' => $object->attribute( 'main_node_id' ),
1154                                 'parent_node_id' => $object->attribute( 'main_parent_node_id' ),
1155                                 'contentclass_id' => $class->attribute( 'id' ),
1156                                 'contentclass_identifier' => $class->attribute( 'identifier' ),
1157                                 'is_modified' => false );
1158          $relationItem['object'] =& $object;
1159          return $relationItem;
1160      }
1161  
1162      /*!
1163       Returns the content.
1164      */
1165      function &objectAttributeContent( &$contentObjectAttribute )
1166      {
1167          $xmlText = $contentObjectAttribute->attribute( 'data_text' );
1168          if ( trim( $xmlText ) == '' )
1169          {
1170              $objectAttributeContent = eZObjectRelationListType::defaultObjectAttributeContent();
1171              return $objectAttributeContent;
1172          }
1173          $doc =& eZObjectRelationListType::parseXML( $xmlText );
1174          $content = eZObjectRelationListType::createObjectContentStructure( $doc );
1175  
1176          return $content;
1177      }
1178  
1179      /*!
1180       \reimp
1181      */
1182      function &classAttributeContent( &$classAttribute )
1183      {
1184          $xmlText = $classAttribute->attribute( 'data_text5' );
1185          if ( trim( $xmlText ) == '' )
1186          {
1187              $classAttributeContent = eZObjectRelationListType::defaultClassAttributeContent();
1188              return $classAttributeContent;
1189          }
1190          $doc =& eZObjectRelationListType::parseXML( $xmlText );
1191          $content = eZObjectRelationListType::createClassContentStructure( $doc );
1192          return $content;
1193      }
1194  
1195      function &parseXML( $xmlText )
1196      {
1197          $xml = new eZXML();
1198          $dom =& $xml->domTree( $xmlText );
1199          return $dom;
1200      }
1201  
1202      function defaultClassAttributeContent()
1203      {
1204          return array( 'object_class' => '',
1205                        'selection_type' => 0,
1206                        'type' => 0,
1207                        'class_constraint_list' => array(),
1208                        'default_placement' => false );
1209      }
1210  
1211      function defaultObjectAttributeContent()
1212      {
1213          return array( 'relation_list' => array() );
1214      }
1215  
1216      function createClassContentStructure( &$doc )
1217      {
1218          $content = eZObjectRelationListType::defaultClassAttributeContent();
1219          $root =& $doc->root();
1220          $objectPlacement =& $root->elementByName( 'contentobject-placement' );
1221  
1222          if ( $objectPlacement and $objectPlacement->hasAttributes() )
1223          {
1224              $nodeID = $objectPlacement->attributeValue( 'node-id' );
1225              $content['default_placement'] = array( 'node_id' => $nodeID );
1226          }
1227          $constraints =& $root->elementByName( 'constraints' );
1228          if ( $constraints )
1229          {
1230              $allowedClassList = $constraints->elementsByName( 'allowed-class' );
1231              foreach( $allowedClassList as $allowedClass )
1232              {
1233                  $content['class_constraint_list'][] = $allowedClass->attributeValue( 'contentclass-identifier' );
1234              }
1235          }
1236          $type =& $root->elementByName( 'type' );
1237          if ( $type )
1238          {
1239              $content['type'] = $type->attributeValue( 'value' );
1240          }
1241          $selectionType =& $root->elementByName( 'selection_type' );
1242          if ( $selectionType )
1243          {
1244              $content['selection_type'] = $selectionType->attributeValue( 'value' );
1245          }
1246          $objectClass =& $root->elementByName( 'object_class' );
1247          if ( $objectClass )
1248          {
1249              $content['object_class'] = $objectClass->attributeValue( 'value' );
1250          }
1251  
1252          return $content;
1253      }
1254  
1255      function createObjectContentStructure( &$doc )
1256      {
1257          $content = eZObjectRelationListType::defaultObjectAttributeContent();
1258          $root =& $doc->root();
1259          $relationList =& $root->elementByName( 'relation-list' );
1260          if ( $relationList )
1261          {
1262              $relationItems = $relationList->elementsByName( 'relation-item' );
1263              foreach( $relationItems as $relationItem )
1264              {
1265                  $content['relation_list'][] = $relationItem->attributeValues( eZObjectRelationListType::contentObjectArrayXMLMap(),
1266                                                                                false );
1267              }
1268          }
1269          return $content;
1270      }
1271  
1272      /*!
1273       \reimp
1274      */
1275      function customClassAttributeHTTPAction( &$http, $action, &$classAttribute )
1276      {
1277          switch ( $action )
1278          {
1279              case 'browse_for_placement':
1280              {
1281                  $module =& $classAttribute->currentModule();
1282                  include_once ( 'kernel/classes/ezcontentbrowse.php' );
1283                  $customActionName = 'CustomActionButton[' . $classAttribute->attribute( 'id' ) . '_browsed_for_placement]';
1284                  eZContentBrowse::browse( array( 'action_name' => 'SelectObjectRelationListNode',
1285                                                  'content' => array( 'contentclass_id' => $classAttribute->attribute( 'contentclass_id' ),
1286                                                                      'contentclass_attribute_id' => $classAttribute->attribute( 'id' ),
1287                                                                      'contentclass_version' => $classAttribute->attribute( 'version' ),
1288                                                                      'contentclass_attribute_identifier' => $classAttribute->attribute( 'identifier' ) ),
1289                                                  'persistent_data' => array( $customActionName => '',
1290                                                                              'ContentClassHasInput' => false ),
1291                                                  'description_template' => 'design:class/datatype/browse_objectrelationlist_placement.tpl',
1292                                                  'from_page' => $module->currentRedirectionURI() ),
1293                                           $module );
1294              } break;
1295              case 'browsed_for_placement':
1296              {
1297                  include_once ( 'kernel/classes/ezcontentbrowse.php' );
1298                  $nodeSelection = eZContentBrowse::result( 'SelectObjectRelationListNode' );
1299                  if ( $nodeSelection and count( $nodeSelection ) > 0 )
1300                  {
1301                      $nodeID = $nodeSelection[0];
1302                      $content = $classAttribute->content();
1303                      $content['default_placement'] = array( 'node_id' => $nodeID );
1304                      $classAttribute->setContent( $content );
1305                  }
1306              } break;
1307              case 'disable_placement':
1308              {
1309                  $content =& $classAttribute->content();
1310                  $content['default_placement'] = false;
1311                  $classAttribute->setContent( $content );
1312              } break;
1313              default:
1314              {
1315                  eZDebug::writeError( "Unknown objectrelationlist action '$action'", 'eZContentObjectRelationListType::customClassAttributeHTTPAction' );
1316              } break;
1317          }
1318      }
1319  
1320      /*!
1321       Returns the meta data used for storing search indeces.
1322      */
1323      function metaData( $contentObjectAttribute )
1324      {
1325          $metaDataArray = array();
1326          $content =& $contentObjectAttribute->content();
1327          for ( $i = 0; $i < count( $content['relation_list'] ); ++$i )
1328          {
1329              $relationItem = $content['relation_list'][$i];
1330              $subObjectID = $relationItem['contentobject_id'];
1331              if ( !$subObjectID )
1332                  continue;
1333  
1334              $attributes =& $content['temp'][$subObjectID]['attributes'];
1335              if ( !$attributes )
1336              {
1337                  $subObjectVersion = $relationItem['contentobject_version'];
1338                  $object =& eZContentObject::fetch( $subObjectID );
1339                  if ( eZContentObject::recursionProtect( $subObjectID ) )
1340                  {
1341                      if ( !$object )
1342                      {
1343                          continue;
1344                      }
1345                      $attributes =& $object->contentObjectAttributes( true, $subObjectVersion );
1346                  }
1347              }
1348  
1349              $metaDataArray = array_merge( $metaDataArray, eZContentObjectAttribute::metaDataArray( $attributes ) );
1350          }
1351  
1352          return $metaDataArray;
1353      }
1354  
1355      /*!
1356       \return string representation of an contentobjectattribute data for simplified export
1357  
1358      */
1359      function toString( $contentObjectAttribute )
1360      {
1361          $objectAttributeContent = $contentObjectAttribute->attribute( 'content' );
1362          $objectIDList = array();
1363          foreach( $objectAttributeContent['relation_list'] as $objectInfo )
1364          {
1365              $objectIDList[] = $objectInfo['contentobject_id'];
1366          }
1367          return implode( '-', $objectIDList );
1368      }
1369  
1370      function fromString( &$contentObjectAttribute, $string )
1371      {
1372          $objectIDList = explode( '-', $string );
1373  
1374          $content = eZObjectRelationListType::defaultObjectAttributeContent();
1375          $priority = 0;
1376          foreach( $objectIDList as $objectID )
1377          {
1378              $object = eZContentObject::fetch( $objectID );
1379              if ( $object )
1380              {
1381                  ++$priority;
1382                  $content['relation_list'][] = $this->appendObject( $objectID, $priority, $contentObjectAttribute );
1383              }
1384              else
1385              {
1386                  eZDebug::writeWarning( $objectID, "Can not create relation because object is missing" );
1387              }
1388          }
1389          $contentObjectAttribute->setContent( $content );
1390          return true;
1391      }
1392  
1393      function hasObjectAttributeContent( &$contentObjectAttribute )
1394      {
1395          $content =& $contentObjectAttribute->content();
1396          return count( $content['relation_list'] ) > 0;
1397      }
1398  
1399      /*!
1400       \reimp
1401      */
1402      function isIndexable()
1403      {
1404          return true;
1405      }
1406  
1407      /*!
1408       Returns the content of the string for use as a title
1409      */
1410      function title( &$contentObjectAttribute )
1411      {
1412          return false;
1413      }
1414  
1415      /*!
1416       \reimp
1417      */
1418      function serializeContentClassAttribute( &$classAttribute, &$attributeNode, &$attributeParametersNode )
1419      {
1420          $content =& $classAttribute->content();
1421          if ( $content['default_placement'] )
1422              $attributeParametersNode->appendChild( eZDOMDocument::createElementNode( 'default-placement',
1423                                                                                       array( 'node-id' => $content['default_placement']['node_id'] ) ) );
1424          if ( is_numeric( $content['type'] ) )
1425              $attributeParametersNode->appendChild( eZDOMDocument::createElementTextNode( 'type', $content['type'] ) );
1426          else
1427              $attributeParametersNode->appendChild( eZDOMDocument::createElementTextNode( 'type', '0' ) );
1428          $classConstraintsNode = eZDOMDocument::createElementNode( 'class-constraints' );
1429          $attributeParametersNode->appendChild( $classConstraintsNode );
1430          foreach ( $content['class_constraint_list'] as $classConstraint )
1431          {
1432              $classConstraintIdentifier = $classConstraint;
1433              $classConstraintsNode->appendChild( eZDOMDocument::createElementNode( 'class-constraint',
1434                                                                                    array( 'class-identifier' => $classConstraintIdentifier ) ) );
1435          }
1436      }
1437  
1438      /*!
1439       \reimp
1440      */
1441      function unserializeContentClassAttribute( &$classAttribute, &$attributeNode, &$attributeParametersNode )
1442      {
1443          $content =& $classAttribute->content();
1444          $defaultPlacementNode = $attributeParametersNode->elementByName( 'default-placement' );
1445          $content['default_placement'] = false;
1446          if ( $defaultPlacementNode )
1447              $content['default_placement'] = $defaultPlacementNode->attributeValue( 'node-id' );
1448          $content['type'] = $attributeParametersNode->elementTextContentByName( 'type' );
1449          $classConstraintsNode =& $attributeParametersNode->elementByName( 'class-constraints' );
1450          $classConstraintList = $classConstraintsNode->children();
1451          $content['class_constraint_list'] = array();
1452          foreach ( $classConstraintList as $classConstraintNode )
1453          {
1454              $classIdentifier = $classConstraintNode->attributeValue( 'class-identifier' );
1455              $content['class_constraint_list'][] = $classIdentifier;
1456          }
1457          $this->storeClassAttributeContent( $classAttribute, $content );
1458      }
1459  
1460      /*!
1461       For each relation export its priority and content object remote_id, like this:
1462        <related-objects>
1463          <relation-list>
1464            <relation-item priority="1"
1465                           contentobject-remote-id="faaeb9be3bd98ed09f606fc16d144eca" />
1466            <relation-item priority="2"
1467                           contentobject-remote-id="1bb4fe25487f05527efa8bfd394cecc7" />
1468          </relation-list>
1469       To do this we fetch content XML and strip all the relation attributes except of "priority" from there,
1470       and add "contentobject-remote-id" attribute.
1471       \reimp
1472      */
1473      function serializeContentObjectAttribute( &$package, &$objectAttribute )
1474      {
1475          $node = $this->createContentObjectAttributeDOMNode( $objectAttribute );
1476  
1477          $xml = new eZXML();
1478          $domDocument = $xml->domTree( $objectAttribute->attribute( 'data_text' ) );
1479          $rootNode =& $domDocument->root();
1480          $relationList =& $rootNode->elementByName( 'relation-list' );
1481          if ( $relationList )
1482          {
1483              require_once ( 'kernel/classes/ezcontentobject.php' );
1484              $relationItems = $relationList->elementsByName( 'relation-item' );
1485              foreach( $relationItems as $i => $relationItem )
1486              {
1487                  // Add related object remote id as attribute to the relation item.
1488                  $relatedObjectID = $relationItem->attributeValue( 'contentobject-id' );
1489                  $relatedObject = eZContentObject::fetch( $relatedObjectID );
1490                  $relatedObjectRemoteID = $relatedObject->attribute( 'remote_id' );
1491                  require_once ( 'kernel/classes/ezcontentobject.php' );
1492                  $relationItems[$i]->setAttribute( 'contentobject-remote-id', $relatedObjectRemoteID );
1493  
1494                  // Remove all other relation item attributes except of "priority".
1495                  foreach ( $relationItem->attributes() as $attribute )
1496                  {
1497                      $attrName = $attribute->name();
1498                      if ( $attrName != 'priority' && $attrName != 'contentobject-remote-id' )
1499                          $relationItems[$i]->removeAttribute( $attrName );
1500                  }
1501              }
1502          }
1503  
1504          $node->appendChild( $rootNode );
1505  
1506          return $node;
1507      }
1508  
1509      /*!
1510       \reimp
1511      */
1512      function unserializeContentObjectAttribute( &$package, &$objectAttribute, $attributeNode )
1513      {
1514          $rootNode = $attributeNode->firstChild();
1515  
1516          if ( $rootNode->attributeValue( 'local_name' ) == 'data-text' )
1517              $xmlString = '';
1518          else
1519          {
1520              $xmlString = $rootNode->toString( 0 );
1521          }
1522  
1523          $objectAttribute->setAttribute( 'data_text', $xmlString );
1524      }
1525  
1526      function postUnserializeContentObjectAttribute( &$package, &$objectAttribute )
1527      {
1528          $xmlString = $objectAttribute->attribute( 'data_text' );
1529          $doc =& $this->parseXML( $xmlString );
1530          $rootNode =& $doc->root();
1531  
1532          $relationList =& $rootNode->elementByName( 'relation-list' );
1533          if ( !$relationList )
1534              return false;
1535  
1536          require_once ( 'kernel/classes/ezcontentobject.php' );
1537          $relationItems = $relationList->elementsByName( 'relation-item' );
1538          foreach( $relationItems as $i => $relationItem )
1539          {
1540              $relatedObjectRemoteID = $relationItem->attributeValue( 'contentobject-remote-id' );
1541              $object = eZContentObject::fetchByRemoteID( $relatedObjectRemoteID );
1542  
1543              if ( $object === null )
1544              {
1545                  eZDebug::writeWarning( "Object with remote id '$relatedObjectRemoteID' not found: removing the link.",
1546                                         'eZObjectRelationListType::unserializeContentObjectAttribute()' );
1547                  unset( $relationItems[$i] );
1548                  continue;
1549              }
1550  
1551              $relationItems[$i]->setAttribute( 'contentobject-id',        $object->attribute( 'id' ) );
1552              $relationItems[$i]->setAttribute( 'contentobject-version',   $object->attribute( 'current_version' ) );
1553              $relationItems[$i]->setAttribute( 'node-id',                 $object->attribute( 'main_node_id' ) );
1554              $relationItems[$i]->setAttribute( 'parent-node-id',          $object->attribute( 'main_parent_node_id' ) );
1555              $relationItems[$i]->setAttribute( 'contentclass-id',         $object->attribute( 'contentclass_id' ) );
1556              $relationItems[$i]->setAttribute( 'contentclass-identifier', $object->attribute( 'class_identifier' ) );
1557          }
1558  
1559          $newXmlString = $rootNode->toString( 0 );
1560  
1561          $objectAttribute->setAttribute( 'data_text', $newXmlString );
1562          return true;
1563      }
1564  
1565      /*!
1566       Removes objects with given ID from the relations list
1567      */
1568      function removeRelatedObjectItem( &$contentObjectAttribute, $objectID )
1569      {
1570          $xmlText = $contentObjectAttribute->attribute( 'data_text' );
1571          if ( trim( $xmlText ) == '' ) return;
1572  
1573          $doc =& eZObjectRelationListType::parseXML( $xmlText );
1574  
1575          $return = false;
1576          $root =& $doc->root();
1577          $relationList =& $root->elementByName( 'relation-list' );
1578          if ( $relationList )
1579          {
1580              $relationItems = $relationList->elementsByName( 'relation-item' );
1581              if ( count( $relationItems ) )
1582              {
1583                  foreach( array_keys( $relationItems ) as $key )
1584                  {
1585                      $relationItem =& $relationItems[$key];
1586                      if ( $relationItem->attributeValue( 'contentobject-id' ) == $objectID )
1587                      {
1588                          $relationList->removeChild( $relationItem );
1589                          $return = true;
1590                      }
1591                  }
1592              }
1593          }
1594          eZObjectRelationListType::storeObjectDOMDocument( $doc, $contentObjectAttribute );
1595          return $return;
1596      }
1597  
1598      /// \privatesection
1599  }
1600  
1601  eZDataType::register( EZ_DATATYPESTRING_OBJECT_RELATION_LIST, "ezobjectrelationlisttype" );
1602  
1603  ?>


Généré le : Sat Feb 24 10:30:04 2007 par Balluche grâce à PHPXref 0.7