[ Index ]
 

Code source de eZ Publish 3.9.0

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

title

Body

[fermer]

/kernel/content/ -> copysubtree.php (source)

   1  <?php
   2  //
   3  // Created on: <23-Mar-2005 23:23:23 rl>
   4  //
   5  // SOFTWARE NAME: eZ publish
   6  // SOFTWARE RELEASE: 3.9.0
   7  // BUILD VERSION: 17785
   8  // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS
   9  // SOFTWARE LICENSE: GNU General Public License v2.0
  10  // NOTICE: >
  11  //   This program is free software; you can redistribute it and/or
  12  //   modify it under the terms of version 2.0  of the GNU General
  13  //   Public License as published by the Free Software Foundation.
  14  //
  15  //   This program is distributed in the hope that it will be useful,
  16  //   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17  //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18  //   GNU General Public License for more details.
  19  //
  20  //   You should have received a copy of version 2.0 of the GNU General
  21  //   Public License along with this program; if not, write to the Free
  22  //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  23  //   MA 02110-1301, USA.
  24  //
  25  //
  26  
  27  include_once ( 'kernel/classes/ezcontentobject.php' );
  28  include_once ( "lib/ezdb/classes/ezdb.php" );
  29  
  30  $Module =& $Params['Module'];
  31  $NodeID =& $Params['NodeID'];
  32  
  33  $http =& eZHTTPTool::instance();
  34  
  35  if ( $http->hasPostVariable( 'BrowseCancelButton' ) )
  36  {
  37      if ( $http->hasPostVariable( 'BrowseCancelURI' ) )
  38          return $Module->redirectTo( $http->postVariable( 'BrowseCancelURI' ) );
  39  }
  40  
  41  if ( $NodeID === null ) // NodeID is returned after browsing
  42  {
  43      $NodeID = $http->postVariable( 'NodeID' );
  44  }
  45  
  46  $srcNode = eZContentObjectTreeNode::fetch( $NodeID );
  47  
  48  if ( $srcNode === null )
  49      return $Module->handleError( EZ_ERROR_KERNEL_NOT_AVAILABLE, 'kernel' );
  50  
  51  if ( !$srcNode->attribute( 'can_read' ) )
  52      return $Module->handleError( EZ_ERROR_KERNEL_ACCESS_DENIED, 'kernel' );
  53  
  54  if ( $Module->isCurrentAction( 'Cancel' ) )
  55  {
  56      $parentNodeID = $srcNode->attribute( 'parent_node_id' );
  57      return $Module->redirectToView( 'view', array( 'full', $parentNodeID ) );
  58  }
  59  
  60  ///// functions START =============================================================================
  61  function copyPublishContentObject( &$sourceObject,
  62                                     &$sourceSubtreeNodeIDList,
  63                                     &$syncNodeIDListSrc, &$syncNodeIDListNew,
  64                                     &$syncObjectIDListSrc, &$syncObjectIDListNew,
  65                                     &$objectIDBlackList, &$nodeIDBlackList,
  66                                     &$notifications,
  67                                     $allVersions = false, $keepCreator = false, $keepTime = false )
  68  {
  69      $sourceObjectID = $sourceObject->attribute( 'id' );
  70  
  71      $key = array_search( $sourceObjectID, $syncObjectIDListSrc );
  72      if ( $key !== false )
  73      {
  74          eZDebug::writeDebug( "Object (ID = $sourceObjectID) has been already copied.",
  75                               "Subtree copy: copyPublishContentObject()" );
  76          return 1; // object already copied
  77      }
  78  
  79      $srcNodeList = $sourceObject->attribute( 'assigned_nodes' );
  80  
  81      // if we already failed to copy that contentobject, then just skip it:
  82      if ( in_array( $sourceObjectID, $objectIDBlackList ) )
  83          return 0;
  84      // if we already failed to copy that node, then just skip it:
  85      //if ( in_array( $sourceNodeID, $nodeIDBlackList ) )
  86      //    return 0;
  87  
  88      // if cannot read contentobject then remember it and all its nodes (nodes
  89      // which are inside subtree being copied) in black list, and skip current node:
  90      if ( !$sourceObject->attribute( 'can_read' ) )
  91      {
  92          $objectIDBlackList[] = $sourceObjectID;
  93          $notifications['Warnings'][] = ezi18n( 'kernel/content/copysubtree',
  94                                                 "Object (ID = %1) was not copied: you don't have permissions to read object.",
  95                                                 null, array( $sourceObjectID ) );
  96  
  97          $srcNodeList = $sourceObject->attribute( 'assigned_nodes' );
  98          foreach( $srcNodeList as $srcNode )
  99          {
 100              $srcNodeID = $srcNode->attribute( 'node_id' );
 101              $sourceParentNodeID = $srcNode->attribute( 'parent_node_id' );
 102  
 103              $key = array_search( $sourceParentNodeID, $sourceSubtreeNodeIDList );
 104              if ( $key !== false )
 105              {
 106                  $nodeIDBlackList[] = $srcNodeID;
 107                  $notifications['Warnings'][] = ezi18n( 'kernel/content/copysubtree',
 108                                                         "Node (ID = %1) was not copied: you don't have permissions to read object (ID = %2).",
 109                                                         null, array( $srcNodeID, $sourceObjectID ) );
 110              }
 111          }
 112          return 0;
 113      }
 114  
 115      // check if all possible parent nodes for given contentobject are already published:
 116      $isReadyToPublish = false;
 117      foreach ( $srcNodeList as $srcNode )
 118      {
 119          $srcNodeID = $srcNode->attribute( 'node_id' );
 120  
 121          if ( in_array( $srcNodeID, $nodeIDBlackList ) )
 122              continue;
 123  
 124          $srcParentNodeID = $srcNode->attribute( 'parent_node_id' );
 125  
 126          // if parent node for this node is outside
 127          // of subtree being copied, then skip this node:
 128          $key = array_search( $srcParentNodeID, $sourceSubtreeNodeIDList );
 129          if ( $key === false )
 130              continue;
 131  
 132          // if parent node for this node wasn't copied yet and is in black list
 133          // then add that node in black list and just skip it:
 134          $key = array_search( $srcParentNodeID, $nodeIDBlackList );
 135          if ( $key !== false )
 136          {
 137              $nodeIDBlackList[] = $srcNodeID;
 138              $notifications['Warnings'][] = ezi18n( 'kernel/content/copysubtree',
 139                                                     "Node (ID = %1) wasn't copied: parent node (ID = %2) wasn't copied.",
 140                                                     null, array( $srcNodeID, $srcParentNodeID ) );
 141              continue;
 142          }
 143  
 144          $key = array_search( $srcParentNodeID, $syncNodeIDListSrc );
 145          if ( $key === false )
 146          {
 147              // if parent node is not copied yet and not in black list,
 148              // then just skip sourceObject from copying for next time
 149              eZDebug::writeDebug( "Parent node (ID = $srcParentNodeID) for contentobject (ID = $sourceObjectID) is not published yet.",
 150                                   "Subtree copy: copyPublishContentObject()" );
 151              return 2;
 152          }
 153          else
 154          {
 155              $newParentNodeID = $syncNodeIDListNew[ $key ];
 156              $newParentNode = eZContentObjectTreeNode::fetch( $newParentNodeID );
 157              if ( $newParentNode === null )
 158              {
 159                  eZDebug::writeError( "Cannot fetch one of parent nodes. Error are somewhere above",
 160                                       "Subtree copy error: copyPublishContentObject()" );
 161                  return 3;
 162              }
 163  
 164              if ( $newParentNode->checkAccess( 'create', $sourceObject->attribute( 'contentclass_id' ) ) != 1 )
 165              {
 166                  $nodeIDBlackList[] = $srcNodeID;
 167                  $notifications['Warnings'][] = ezi18n( 'kernel/content/copysubtree',
 168                                                         "Node (ID = %1) was not copied: you don't have permissions to create.",
 169                                                         null, array( $srcNodeID ) );
 170  
 171                  continue;
 172              }
 173              else
 174                  $isReadyToPublish = true;
 175          }
 176      }
 177  
 178      // if all nodes of sourceObject were skiped as black list entry or
 179      // as outside of subtree being copied, then sourceObject cannot be
 180      // copied and published in any new location. So insert sourceObject
 181      // in a black list and skip it.
 182      if ( $isReadyToPublish == false )
 183      {
 184          $objectIDBlackList[] = $sourceObjectID;
 185          $notifications['Warnings'][] = ezi18n( 'kernel/content/copysubtree',
 186                                                 "Object (ID = %1) was not copied: no one nodes of object wasn't copied.",
 187                                                 null, array( $sourceObjectID) );
 188          return 0;
 189      }
 190  
 191      // make copy of source object
 192      $newObject             = $sourceObject->copy( $allVersions ); // insert source and new object's ids in $syncObjectIDList
 193      // We should reset section that will be updated in updateSectionID().
 194      // If sectionID is 0 than the object has been newly created
 195      $newObject->setAttribute( 'section_id', 0 );
 196      $newObject->store();
 197  
 198      $syncObjectIDListSrc[] = $sourceObjectID;
 199      $syncObjectIDListNew[] = $newObject->attribute( 'id' );
 200  
 201      $curVersion        = $newObject->attribute( 'current_version' );
 202      $curVersionObject  = $newObject->attribute( 'current' );
 203  
 204      $newObjAssignments = $curVersionObject->attribute( 'node_assignments' );
 205  
 206      // copy nodeassigments:
 207      $assignmentsForRemoving = array();
 208      $foundMainAssignment = false;
 209      foreach ( $newObjAssignments as $assignment )
 210      {
 211          $parentNodeID = $assignment->attribute( 'parent_node' );
 212  
 213          // if assigment is outside of subtree being copied then do not copy this assigment
 214          $key1 = array_search( $parentNodeID, $sourceSubtreeNodeIDList );
 215          $key2 = array_search( $parentNodeID, $nodeIDBlackList );
 216          if ( $key1 === false or $key2 !== false )
 217          {
 218              $assignmentsForRemoving[] = $assignment->attribute( 'id' );
 219              continue;
 220          }
 221  
 222          $key = array_search( $parentNodeID, $syncNodeIDListSrc );
 223          if ( $key === false )
 224          {
 225              eZDebug::writeError( "Cannot publish contentobject (ID=$sourceObjectID). Parent is not published yet.",
 226                                   "Subtree Copy error: copyPublishContentObject()" );
 227              return 4;
 228          }
 229  
 230          if ( $assignment->attribute( 'is_main' ) )
 231              $foundMainAssignment = true;
 232  
 233          $newParentNodeID = $syncNodeIDListNew[ $key ];
 234          $assignment->setAttribute( 'parent_node', $newParentNodeID );
 235          $assignment->store();
 236      }
 237      // remove assigments which are outside of subtree being copied:
 238      eZNodeAssignment::purgeByID( $assignmentsForRemoving );
 239  
 240      // if main nodeassigment was not copied then set as main first nodeassigment
 241      if ( $foundMainAssignment == false )
 242      {
 243          $newObjAssignments = $curVersionObject->attribute( 'node_assignments' );
 244          // We need to check if it has any assignments before changing the data.
 245          if ( isset( $newObjAssignments[0] ) )
 246          {
 247              $newObjAssignments[0]->setAttribute( 'is_main', 1 );
 248              $newObjAssignments[0]->store();
 249          }
 250      }
 251  
 252      // publish the newly created object
 253      include_once ( 'lib/ezutils/classes/ezoperationhandler.php' );
 254      $result = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $newObject->attribute( 'id' ),
 255                                                                          'version'   => $curVersion ) );
 256      // Refetch the object data since it might change in the database.
 257      $newObjectID = $newObject->attribute( 'id' );
 258      $newObject =& eZContentObject::fetch( $newObjectID );
 259      $newNodeList =& $newObject->attribute( 'assigned_nodes' );
 260      if ( count($newNodeList) == 0 )
 261      {
 262          $newObject->purge();
 263          eZDebug::writeError( "Cannot publish contentobject.",
 264                               "Subtree Copy Error!" );
 265          $notifications['Warnings'][] = ezi18n( 'kernel/content/copysubtree',
 266                                                 "Cannot publish object (ID = %1).",
 267                                                 null, array( $sourceObjectID) );
 268          return -1;
 269      }
 270  
 271      $objAssignments = $curVersionObject->attribute( 'node_assignments' );
 272      foreach ( $newNodeList as $newNode )
 273      {
 274          $newParentNode = $newNode->fetchParent();
 275          $newParentNodeID = $newParentNode->attribute( 'node_id' );
 276  
 277          $keyA = array_search( $newParentNodeID, $syncNodeIDListNew );
 278          if ( $keyA === false )
 279          {
 280              eZDebug::writeError( "Algoritm ERROR! Cannot find new parent node ID in new ID's list",
 281                                  "Subtree Copy Error!" );
 282              return -2;
 283          }
 284  
 285          $srcParentNodeID = $syncNodeIDListSrc[ $keyA ];
 286  
 287          // Update attributes of node
 288          $bSrcParentFound = false;
 289          foreach ( $srcNodeList as $srcNode )
 290          {
 291              if ( $srcNode->attribute( 'parent_node_id' ) == $srcParentNodeID )
 292              {
 293                  $newNode->setAttribute( 'priority', $srcNode->attribute( 'priority' ) );
 294                  $newNode->setAttribute( 'is_hidden', $srcNode->attribute( 'is_hidden' ) );
 295                  // Update node visibility
 296                  if ( $newParentNode->attribute( 'is_invisible' ) or $newParentNode->attribute( 'is_hidden' ) )
 297                      $newNode->setAttribute( 'is_invisible', 1 );
 298                  else
 299                      $newNode->setAttribute( 'is_invisible', $srcNode->attribute( 'is_invisible' ) );
 300  
 301                  $syncNodeIDListSrc[] = $srcNode->attribute( 'node_id' );
 302                  $syncNodeIDListNew[] = $newNode->attribute( 'node_id' );
 303                  $bSrcParentFound = true;
 304                  break;
 305              }
 306          }
 307          if ( $bSrcParentFound == false )
 308          {
 309              eZDebug::writeError( "Cannot find source parent node in list of nodes already copied.",
 310                                   "Subtree Copy Error!" );
 311          }
 312          // Create unique remote_id
 313          $newRemoteID = md5( (string)mt_rand() . (string)mktime() );
 314          $oldRemoteID = $newNode->attribute( 'remote_id' );
 315          $newNode->setAttribute( 'remote_id', $newRemoteID );
 316          // Change parent_remote_id for object assignments
 317          foreach ( $objAssignments as $assignment )
 318          {
 319              if ( $assignment->attribute( 'parent_remote_id' ) == $oldRemoteID )
 320              {
 321                   $assignment->setAttribute( 'parent_remote_id', $newRemoteID );
 322                   $assignment->store();
 323              }
 324          }
 325          $newNode->store();
 326      }
 327  
 328      // if $keepCreator == true then keep owner of contentobject being
 329      // copied and creator of its published version Unchaged
 330      $isModified = false;
 331      if ( $keepTime )
 332      {
 333          $srcPublished = $sourceObject->attribute( 'published' );
 334          $newObject->setAttribute( 'published', $srcPublished );
 335          $srcModified  = $sourceObject->attribute( 'modified' );
 336          $newObject->setAttribute( 'modified', $srcModified );
 337          $isModified = true;
 338      }
 339      if ( $keepCreator )
 340      {
 341          $srcOwnerID = $sourceObject->attribute( 'owner_id' );
 342          $newObject->setAttribute( 'owner_id', $srcOwnerID );
 343          $isModified = true;
 344      }
 345      if ( $isModified )
 346          $newObject->store();
 347  
 348      if ( $allVersions )
 349      {   // copy time of creation and midification and creator id for
 350          // all versions of content object being copied.
 351          $srcVersionsList = $sourceObject->versions();
 352  
 353          foreach ( $srcVersionsList as $srcVersionObject )
 354          {
 355              $newVersionObject = $newObject->version( $srcVersionObject->attribute( 'version' ) );
 356              if ( !is_object( $newVersionObject ) )
 357                  continue;
 358  
 359              $isModified = false;
 360              if ( $keepTime )
 361              {
 362                  $srcVersionCreated  = $srcVersionObject->attribute( 'created' );
 363                  $newVersionObject->setAttribute( 'created', $srcVersionCreated );
 364                  $srcVersionModified = $srcVersionObject->attribute( 'modified' );
 365                  $newVersionObject->setAttribute( 'modified', $srcVersionModified );
 366                  $isModified = true;
 367              }
 368              if ( $keepCreator )
 369              {
 370                  $srcVersionCreatorID = $srcVersionObject->attribute( 'creator_id' );
 371                  $newVersionObject->setAttribute( 'creator_id', $srcVersionCreatorID );
 372  
 373                  $isModified = true;
 374              }
 375              if ( $isModified )
 376                  $newVersionObject->store();
 377          }
 378      }
 379      else // if not all versions copied
 380      {
 381          $srcVersionObject = $sourceObject->attribute( 'current' );
 382          $newVersionObject = $newObject->attribute( 'current' );
 383  
 384          $isModified = false;
 385          if ( $keepTime )
 386          {
 387              $srcVersionCreated  = $srcVersionObject->attribute( 'created' );
 388              $newVersionObject->setAttribute( 'created', $srcVersionCreated );
 389              $srcVersionModified = $srcVersionObject->attribute( 'modified' );
 390              $newVersionObject->setAttribute( 'modified', $srcVersionModified );
 391              $isModified = true;
 392          }
 393          if ( $keepCreator )
 394          {
 395              $srcVersionCreatorID = $srcVersionObject->attribute( 'creator_id' );
 396              $newVersionObject->setAttribute( 'creator_id', $srcVersionCreatorID );
 397              $isModified = true;
 398          }
 399          if ( $isModified )
 400              $newVersionObject->store();
 401      }
 402  
 403      return 0; // source object was copied successfully.
 404  
 405  } // function copyPublishContentObject END
 406  
 407  
 408  function copySubtree( $srcNodeID, $dstNodeID, &$notifications, $allVersions, $keepCreator, $keepTime )
 409  {
 410      // 1. Copy subtree and form the arrays of accordance of the old and new nodes and content objects.
 411  
 412      $sourceSubTreeMainNode = ( $srcNodeID ) ? eZContentObjectTreeNode::fetch( $srcNodeID ) : false;
 413      $destinationNode = ( $dstNodeID ) ? eZContentObjectTreeNode::fetch( $dstNodeID ) : false;
 414  
 415      if ( !$sourceSubTreeMainNode )
 416      {
 417          eZDebug::writeError( "Cannot get subtree main node (nodeID = $srcNodeID).",
 418                               "Subtree copy Error!" );
 419          $notifications['Errors'][] = ezi18n( 'kernel/content/copysubtree',
 420                                              "Fatal error: cannot get subtree main node (ID = %1).",
 421                                              null, array( $srcNodeID ) );
 422          return $notifications;
 423      }
 424      if ( !$destinationNode )
 425      {
 426          eZDebug::writeError( "Cannot get destination node (nodeID = $dstNodeID).",
 427                               "Subtree copy Error!" );
 428          $notifications['Errors'][] = ezi18n( 'kernel/content/copysubtree',
 429                                              "Fatal error: cannot get destination node (ID = %1).",
 430                                              null, array( $dstNodeID ) );
 431          return $notifications;
 432      }
 433  
 434      $sourceNodeList    = array();
 435  
 436      $syncNodeIDListSrc = array(); // arrays for synchronizing between source and new IDs of nodes
 437      $syncNodeIDListNew = array();
 438      $syncObjectIDListSrc = array(); // arrays for synchronizing between source and new IDs of contentobjects
 439      $syncObjectIDListNew = array();
 440  
 441      $sourceSubTreeMainNodeID = $sourceSubTreeMainNode->attribute( 'node_id' );
 442      $sourceNodeList[] = $sourceSubTreeMainNode;
 443  
 444      $syncNodeIDListSrc[] = $sourceSubTreeMainNode->attribute( 'parent_node_id' );
 445      $syncNodeIDListNew[] = (int) $dstNodeID;
 446  
 447      $nodeIDBlackList = array(); // array of nodes which are unable to copy
 448      $objectIDBlackList = array(); // array of contentobjects which are unable to copy in any location inside new subtree
 449  
 450      $sourceNodeList = array_merge( $sourceNodeList,
 451                                     eZContentObjectTreeNode::subTree( array( 'Limitation' => array() ), $sourceSubTreeMainNodeID ) );
 452      $countNodeList = count( $sourceNodeList );
 453  
 454      $notifications['Notifications'][] = ezi18n( 'kernel/content/copysubtree',
 455                                                  "Number of nodes of source subtree - %1",
 456                                                  null, array( $countNodeList ) );
 457  
 458      // Prepare list of source node IDs. We will need it in the future
 459      // for checking node is inside or outside of the subtree being copied.
 460      $sourceNodeIDList = array();
 461      foreach ( $sourceNodeList as $sourceNode )
 462          $sourceNodeIDList[] = $sourceNode->attribute( 'node_id' );
 463  
 464      eZDebug::writeDebug( "Source NodeID = $srcNodeID, destination NodeID = $dstNodeID",
 465                           "Subtree copy: START!" );
 466  
 467      // 1. copying and publishing source subtree
 468      $k = 0;
 469      while ( count( $sourceNodeList ) > 0 )
 470      {
 471          if ( $k > $countNodeList )
 472          {
 473              eZDebug::writeError( "Too many loops while copying nodes.",
 474                                   "Subtree Copy Error!" );
 475              break;
 476          }
 477  
 478          for ( $i = 0; $i < count( $sourceNodeList ); $i)
 479          {
 480              $sourceNodeID = $sourceNodeList[ $i ]->attribute( 'node_id' );
 481  
 482              // if node was alreaty copied
 483              if ( in_array( $sourceNodeID, $syncNodeIDListSrc ) )
 484              {
 485                  array_splice( $sourceNodeList, $i, 1 );
 486                  continue;
 487              }
 488  
 489              //////////// check permissions START
 490              // if node is already in black list, then skip current node:
 491              if ( in_array( $sourceNodeID, $nodeIDBlackList ) )
 492              {
 493                  array_splice( $sourceNodeList, $i, 1 );
 494                  continue;
 495              }
 496  
 497              $sourceObject =& $sourceNodeList[ $i ]->object();
 498  
 499              $srcSubtreeNodeIDlist = ($sourceNodeID == $sourceSubTreeMainNodeID) ? $syncNodeIDListSrc : $sourceNodeIDList;
 500              $copyResult = copyPublishContentObject( $sourceObject,
 501                                                      $srcSubtreeNodeIDlist,
 502                                                      $syncNodeIDListSrc, $syncNodeIDListNew,
 503                                                      $syncObjectIDListSrc, $syncObjectIDListNew,
 504                                                      $objectIDBlackList, $nodeIDBlackList,
 505                                                      $notifications,
 506                                                      $allVersions, $keepCreator, $keepTime );
 507              if ( $copyResult === 0 )
 508              {   // if copying successful then remove $sourceNode from $sourceNodeList
 509                  array_splice( $sourceNodeList, $i, 1 );
 510              }
 511              else
 512                  $i++;
 513          }
 514          $k++;
 515      }
 516  
 517      array_shift( $syncNodeIDListSrc );
 518      array_shift( $syncNodeIDListNew );
 519  
 520  
 521      $countNewNodes = count( $syncNodeIDListNew );
 522      $countNewObjects = count( $syncObjectIDListNew );
 523  
 524      $key = array_search( $sourceSubTreeMainNodeID, $syncNodeIDListSrc );
 525      if ( $key === false )
 526      {
 527          eZDebug::writeDebug( "Root node of given subtree was not copied.",
 528                               "Subtree copy:" );
 529          $notifications['Notifacations'][] = ezi18n( 'kernel/content/copysubtree',
 530                                                      "Subtree was not copied." );
 531          return $notifications;
 532      }
 533  
 534      $notifications['Notifications'][] = ezi18n( 'kernel/content/copysubtree',
 535                                                  "Number of copied nodes - %1",
 536                                                  null, array( $countNewNodes ) );
 537      $notifications['Notifications'][] = ezi18n( 'kernel/content/copysubtree',
 538                                                  "Number of copied contentobjects - %1",
 539                                                  null, array( $countNewObjects ) );
 540  
 541      eZDebug::writeDebug( count( $syncNodeIDListNew ) ,"Number of copied nodes: " );
 542      eZDebug::writeDebug( count( $syncObjectIDListNew ), "Number of copied contentobjects: " );
 543  
 544      eZDebug::writeDebug( $objectIDBlackList, "Copy subtree: Not copied object IDs list:" );
 545      eZDebug::writeDebug( $nodeIDBlackList, "Copy subtree: Not copied node IDs list:" );
 546  
 547      // 2. fetch all new subtree
 548  
 549      $newSubTreeMainNodeID = $syncNodeIDListSrc[ $key ];
 550      $newSubTreeMainNode   = eZContentObjectTreeNode::fetch( $newSubTreeMainNodeID );
 551  
 552      $newNodeList[] = $newSubTreeMainNode;
 553      $newNodeList = $sourceNodeList = array_merge( $newNodeList,
 554                                                    eZContentObjectTreeNode::subTree( false, $newSubTreeMainNodeID ) );
 555  
 556      // 3. fix local links (in ezcontentobject_link)
 557      eZDebug::writeDebug( "Fixing global and local links...",
 558                           "Subtree copy:" );
 559  
 560      $db =& eZDB::instance();
 561      if ( !$db )
 562      {
 563          eZDebug::writeError( "Cannot create instance of eZDB for fixing local links (related objects).",
 564                               "Subtree Copy Error!" );
 565          $notifications['Errors'][] = ezi18n( 'kernel/content/copysubtree',
 566                                               "Cannot create instance of eZDB to fix local links (related objects)." );
 567          return $notifications;
 568      }
 569  
 570      $idListStr = $db->implodeWithTypeCast( ',', $syncObjectIDListNew, 'int' );
 571      $relatedRecordsList = $db->arrayQuery( "SELECT * FROM ezcontentobject_link WHERE from_contentobject_id IN ($idListStr)" );
 572  
 573      foreach ( array_keys( $relatedRecordsList ) as $key )
 574      {
 575          $relatedEntry =& $relatedRecordsList[ $key ];
 576          $kindex = array_search( $relatedEntry[ 'to_contentobject_id' ], $syncObjectIDListSrc );
 577          if ( $kindex !== false )
 578          {
 579              $newToContentObjectID = (int) $syncObjectIDListNew[ $kindex ];
 580              $linkID = (int) $relatedEntry[ 'id' ];
 581              $db->query( "UPDATE ezcontentobject_link SET  to_contentobject_id=$newToContentObjectID WHERE id=$linkID" );
 582          }
 583      }
 584  
 585      // 4. duplicating of global links for new contentobjects (in ezurl_object_link) are automatic during copy of contentobject.
 586      //    it was fixed as bug patch.
 587  
 588      // 5. fixing node_ids and object_ids in ezxmltext attributes of copied objects
 589      $conditions = array( 'contentobject_id' => '', // 5
 590                           'data_type_string' => 'ezxmltext' );
 591  
 592      foreach ( $syncObjectIDListNew as $contentObjectID )
 593      {
 594          $conditions[ 'contentobject_id' ] = $contentObjectID;
 595          $attributeList = eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(), null, $conditions );
 596          if ( count( $attributeList ) == 0 )
 597          {
 598              continue;
 599          }
 600          foreach ( array_keys( $attributeList ) as $key )
 601          {
 602              $xmlAttribute =& $attributeList[ $key ];
 603              $xmlText = $xmlAttribute->attribute( 'data_text' );
 604              $xmlTextLen = strlen ( $xmlText );
 605              $isTextModified = false;
 606              $curPos = 0;
 607  
 608              while ( $curPos < $xmlTextLen )
 609              {
 610                  $literalTagBeginPos = strpos( $xmlText, "<literal", $curPos );
 611                  if ( $literalTagBeginPos )
 612                  {
 613                      $literalTagEndPos = strpos( $xmlText, "</literal>", $literalTagBeginPos );
 614                      if ( $literalTagEndPos === false )
 615                          break;
 616                      $curPos = $literalTagEndPos + 9;
 617                  }
 618  
 619                  if ( ($tagBeginPos = strpos( $xmlText, "<link", $curPos )) !== false or
 620                       ($tagBeginPos = strpos( $xmlText, "<a"   , $curPos )) !== false or
 621                       ($tagBeginPos = strpos( $xmlText, "<embed",$curPos )) !== false )
 622                  {
 623                      $tagEndPos = strpos( $xmlText, ">", $tagBeginPos + 1 );
 624                      if ( $tagEndPos === false )
 625                          break;
 626  
 627                      $tagText = substr( $xmlText, $tagBeginPos, $tagEndPos - $tagBeginPos );
 628  
 629                      if ( ($nodeIDAttributePos = strpos( $tagText, " node_id=\"" )) !== false )
 630                      {
 631                          $idNumberPos = $nodeIDAttributePos + 10;
 632                          $quoteEndPos = strpos( $tagText, "\"", $idNumberPos );
 633  
 634                          if ( $quoteEndPos !== false )
 635                          {
 636                              $idNumber = substr( $tagText, $idNumberPos, $quoteEndPos - $idNumberPos );
 637                              $key = array_search( (int) $idNumber, $syncNodeIDListSrc );
 638  
 639                              if ( $key !== false )
 640                              {
 641                                  $tagText = substr_replace( $tagText, (string) $syncNodeIDListNew[ $key ], $idNumberPos, $quoteEndPos - $idNumberPos );
 642                                  $xmlText = substr_replace( $xmlText, $tagText, $tagBeginPos, $tagEndPos - $tagBeginPos );
 643                                  $isTextModified = true;
 644                              }
 645                          }
 646                      }
 647                      else if ( ($objectIDAttributePos = strpos( $tagText, " object_id=\"" )) !== false )
 648                      {
 649                          $idNumberPos = $objectIDAttributePos + 12;
 650                          $quoteEndPos = strpos( $tagText, "\"", $idNumberPos );
 651  
 652                          if ( $quoteEndPos !== false )
 653                          {
 654                              $idNumber = substr( $tagText, $idNumberPos, $quoteEndPos - $idNumberPos );
 655                              $key = array_search( (int) $idNumber, $syncObjectIDListSrc );
 656                              if ( $key !== false )
 657                              {
 658                                  $tagText = substr_replace( $tagText, (string) $syncObjectIDListNew[ $key ], $idNumberPos, $quoteEndPos - $idNumberPos );
 659                                  $xmlText = substr_replace( $xmlText, $tagText, $tagBeginPos, $tagEndPos - $tagBeginPos );
 660                                  $isTextModified = true;
 661                              }
 662                          }
 663                      }
 664                      $curPos = $tagEndPos;
 665                  }
 666                  else if ( ($tagBeginPos = strpos( $xmlText, "<object", $curPos )) !== false )
 667                  {
 668                      $tagEndPos = strpos( $xmlText, ">", $tagBeginPos + 1 );
 669                      if ( !$tagEndPos )
 670                          break;
 671  
 672                      $tagText = substr( $xmlText, $tagBeginPos, $tagEndPos - $tagBeginPos );
 673  
 674                      if ( ($idAttributePos = strpos( $tagText, " id=\"" )) !== false )
 675                      {
 676                          $idNumberPos = $idAttributePos + 5;
 677                          $quoteEndPos = strpos( $tagText, "\"", $idNumberPos );
 678  
 679                          if ( $quoteEndPos !== false )
 680                          {
 681                              $idNumber = substr( $tagText, $idNumberPos, $quoteEndPos - $idNumberPos );
 682                              $key = array_search( (int) $idNumber, $syncObjectIDListSrc );
 683                              if ( $key !== false )
 684                              {
 685                                  $tagText = substr_replace( $tagText, (string) $syncObjectIDListNew[ $key ], $idNumberPos, $quoteEndPos - $idNumberPos );
 686                                  $xmlText = substr_replace( $xmlText, $tagText, $tagBeginPos, $tagEndPos - $tagBeginPos );
 687                                  $isTextModified = true;
 688                              }
 689                          }
 690                      }
 691                      $curPos = $tagEndPos;
 692                  }
 693                  else
 694                      break;
 695  
 696              } // while END
 697  
 698              if ( $isTextModified )
 699              {
 700                  $xmlAttribute->setAttribute( 'data_text', $xmlText );
 701                  $xmlAttribute->store();
 702              }
 703          } // foreach END
 704      }
 705  
 706      // 6. fixing datatype ezobjectrelationlist
 707      $conditions = array( 'contentobject_id' => '',
 708                           'data_type_string' => 'ezobjectrelationlist' );
 709      foreach ( $syncObjectIDListNew as $contentObjectID )
 710      {
 711          $conditions[ 'contentobject_id' ] = $contentObjectID;
 712          $attributeList = eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(), null, $conditions );
 713          if ( count( $attributeList ) == 0 )
 714          {
 715              continue;
 716          }
 717          foreach ( array_keys( $attributeList ) as $key )
 718          {
 719              $relationListAttribute =& $attributeList[ $key ];
 720              $relationsXmlText = $relationListAttribute->attribute( 'data_text' );
 721              $relationsDom =& eZObjectRelationListType::parseXML( $relationsXmlText );
 722              $relationItems = $relationsDom->elementsByName( 'relation-item' ) ? $relationsDom->elementsByName( 'relation-item' ) : array();
 723              $isRelationModified = false;
 724              foreach ( $relationItems as $relationItem )
 725              {
 726                  $allAttributes = $relationItem->attributes();
 727                  $relatedNodeID = $relationItem->attributeValue('node-id');
 728                  $relatedNode = eZContentObjectTreeNode::fetch( $relatedNodeID );
 729                  $originalObjectID = $relatedNode->attribute('contentobject_id');
 730                  $srcKey = array_search( (int) $originalObjectID, $syncObjectIDListSrc );
 731                  if ( $srcKey !== false )
 732                  {
 733                      $isRelationModified = true;
 734                      foreach( $allAttributes as $attribute )
 735                      {
 736                          $attrName = $attribute->Name;
 737                          if( $attrName == 'contentobject-id' )
 738                          {
 739                              $attribute->setContent( $syncObjectIDListNew[$srcKey] );
 740                          }
 741                          if( $attrName == 'node-id' )
 742                          {
 743                              $attribute->setContent( $syncNodeIDListNew[$srcKey] );
 744                          }
 745                          if( $attrName == 'parent-node-id' )
 746                          {
 747                              $attrContent = $attribute->Content;
 748                              $newNode = eZContentObjectTreeNode::fetch( $syncNodeIDListNew[$srcKey] );
 749                              $attribute->setContent( $newNode->attribute( 'parent_node_id' ) );
 750                          }
 751                      }
 752                  }
 753              }
 754              if ( $isRelationModified )
 755              {
 756                  $attributeID = $relationListAttribute->attribute( 'id' );
 757                  $changedDomString =$db->escapeString( eZObjectRelationListType::domString( $relationsDom ) );
 758                  $db->query( "UPDATE ezcontentobject_attribute SET data_text='$changedDomString' WHERE id=$attributeID" );
 759              }
 760          }
 761      }
 762  
 763      eZDebug::writeDebug( "Successfuly DONE.",
 764                           "Copy subtree:" );
 765  
 766      $notifications['Notifications'][] = ezi18n( 'kernel/content/copysubtree',
 767                                                  "Successfuly DONE." );
 768      return $notifications;
 769  } // function copySubtree END
 770  
 771  /*!
 772  Browse for node to place the object copy into
 773  */
 774  function browse( &$Module, &$srcNode )
 775  {
 776      if ( $Module->hasActionParameter( 'LanguageCode' ) )
 777          $languageCode = $Module->actionParameter( 'LanguageCode' );
 778      else
 779      {
 780          $languageCode = false;
 781      }
 782  
 783      $nodeID          = $srcNode->attribute( 'node_id' );
 784      $object          = $srcNode->attribute( 'object' );
 785      $objectID        = $object->attribute( 'id' );
 786      $class           = $object->contentClass();
 787      $classID         = $class->attribute( 'id' );
 788      $srcParentNodeID = $srcNode->attribute( 'parent_node_id' );
 789  
 790      $ignoreNodesSelect = array();
 791      $ignoreNodesClick = array();
 792      foreach ( $object->assignedNodes( false ) as $element )
 793      {
 794          $ignoreNodesSelect[] = $element['node_id'];
 795          $ignoreNodesClick[]  = $element['node_id'];
 796      }
 797      $ignoreNodesSelect = array_unique( $ignoreNodesSelect );
 798      $ignoreNodesClick = array_unique( $ignoreNodesClick );
 799  
 800      $viewMode = 'full';
 801      if ( $Module->hasActionParameter( 'ViewMode' ) )
 802          $viewMode = $module->actionParameter( 'ViewMode' );
 803  
 804      include_once ( 'kernel/classes/ezcontentbrowse.php' );
 805      eZContentBrowse::browse(
 806           array( 'action_name'          => 'CopySubtree',
 807                  'description_template' => 'design:content/browse_copy_subtree.tpl',
 808                  'keys'                 => array( 'class'      => $classID,
 809                                                   'class_id'   => $class->attribute( 'identifier' ),
 810                                                   'classgroup' => $class->attribute( 'ingroup_id_list' ),
 811                                                   'section'    => $object->attribute( 'section_id' ) ),
 812                  'ignore_nodes_select'  => $ignoreNodesSelect,
 813                  'ignore_nodes_click'   => $ignoreNodesClick,
 814                  'persistent_data'      => array( 'ObjectID' => $objectID,
 815                                                   'NodeID'   => $nodeID ),
 816                  'permission'           => array( 'access' => 'create', 'contentclass_id' => $classID ),
 817                  'content'              => array( 'node_id' => $nodeID ),
 818                  'start_node'           => $srcParentNodeID,
 819                  'cancel_page'          => $Module->redirectionURIForModule( $Module, 'view',
 820                                                           array( $viewMode, $srcParentNodeID, $languageCode ) ),
 821                  'from_page'            => "/content/copysubtree" ),
 822           $Module );
 823  }
 824  
 825  /*!
 826  Redirect to the page that lets a user to choose which versions to copy:
 827  either all version or the current one.
 828  */
 829  function chooseOptionsToCopy( &$Module, &$Result, &$srcNode, $chooseVersions, $chooseCreator, $chooseTime )
 830  {
 831          include_once ( 'kernel/classes/ezcontentbrowse.php' );
 832          $selectedNodeIDArray = eZContentBrowse::result( $Module->currentAction() );
 833  
 834          include_once ( 'kernel/common/template.php' );
 835          $tpl =& templateInit();
 836  
 837          $tpl->setVariable( 'node', $srcNode );
 838          $tpl->setVariable( 'selected_node_id', $selectedNodeIDArray[0] );
 839          $tpl->setVariable( 'choose_versions', $chooseVersions );
 840          $tpl->setVariable( 'choose_creator', $chooseCreator );
 841          $tpl->setVariable( 'choose_time', $chooseTime );
 842  
 843          $Result['content'] = $tpl->fetch( 'design:content/copy_subtree.tpl' );
 844          $Result['path'] = array( array( 'url' => false,
 845                                          'text' => ezi18n( 'kernel/content', 'Content' ) ),
 846                                   array( 'url' => false,
 847                                          'text' => ezi18n( 'kernel/content', 'Copy Subtree' ) ) );
 848  }
 849  
 850  function showNotificationAfterCopying( &$http, &$Module, &$Result, &$Notifications, &$srcNode )
 851  {
 852      include_once ( 'kernel/common/template.php' );
 853      $tpl =& templateInit();
 854  
 855      if ( $http->hasSessionVariable( "LastAccessesURI" ) )
 856      {
 857          $tpl->setVariable( 'redirect_url', $http->sessionVariable( "LastAccessesURI" ) );
 858      }
 859      else
 860      {
 861          $parentRootNodeID = $srcNode->attribute( 'parent_node_id' );
 862          if ( $Module->hasActionParameter( 'LanguageCode' ) )
 863              $languageCode = $Module->actionParameter( 'LanguageCode' );
 864          else
 865          {
 866              $languageCode = false;
 867          }
 868  
 869          if ( $Module->hasActionParameter( 'ViewMode' ) )
 870              $viewMode = $module->actionParameter( 'ViewMode' );
 871          else
 872              $viewMode = 'full';
 873  
 874          $redirectURI = $Module->redirectionURIForModule( $Module, 'view', array( $viewMode, $parentRootNodeID, $languageCode ) );
 875          $tpl->setVariable( 'redirect_url', $redirectURI );
 876      }
 877  
 878      $tpl->setVariable( 'source_node', $srcNode );
 879      //$tpl->setVariable( 'subtree_nodes_count', $srcSubtreeNodesCount );
 880      $tpl->setVariable( 'notifications', $Notifications );
 881  
 882      $Result['content'] = $tpl->fetch( 'design:content/copy_subtree_notification.tpl' );
 883      $Result['path'] = array( array( 'url' => false,
 884                                      'text' => ezi18n( 'kernel/content', 'Content' ) ),
 885                               array( 'url' => false,
 886                                      'text' => ezi18n( 'kernel/content', 'Copy Subtree' ) ) );
 887  }
 888  /////////// functions END ==================================================================
 889  
 890  $Result = array();
 891  $notifications = array( 'Notifications' => array(),
 892                          'Warnings' => array(),
 893                          'Errors' => array() );
 894  $contentINI =& eZINI::instance( 'content.ini' );
 895  
 896  // check if number of nodes being copied not more then MaxNodesCopySubtree setting
 897  $maxNodesCopySubtree = $contentINI->variable( 'CopySettings', 'MaxNodesCopySubtree' );
 898  $srcSubtreeNodesCount = $srcNode->subTreeCount();
 899  
 900  if ( $srcSubtreeNodesCount > $maxNodesCopySubtree )
 901  {
 902      $notifications['Warnings'][] = ezi18n( 'kernel/content/copysubtree',
 903                                             "You are trying to copy a subtree that contains more than ".
 904                                             "the maximum possible nodes for subtree copying. ".
 905                                             "You can copy this subtree using Subtree Copy script.",
 906                                             null, array( $maxNodesCopySubtree ) );
 907      $notifications['Notifications'][] = ezi18n( 'kernel/content/copysubtree',
 908                                                  "Subtree was not copied." );
 909  
 910      showNotificationAfterCopying( $http, $Module, $Result, $notifications, $srcNode );
 911      return;
 912  }
 913  
 914  $versionHandling = $contentINI->variable( 'CopySettings', 'VersionHandling' );
 915  $creatorHandling = $contentINI->variable( 'CopySettings', 'CreatorHandling' );
 916  $timeHandling    = $contentINI->variable( 'CopySettings', 'TimeHandling' );
 917  $showCopySubtreeNotification = $contentINI->variable( 'CopySettings', 'ShowCopySubtreeNotification' );
 918  
 919  $chooseVersions = ( $versionHandling == 'user-defined' );
 920  $chooseCreator  = ( $creatorHandling == 'user-defined' );
 921  $chooseTime     = ( $timeHandling    == 'user-defined' );
 922  $showNotification = ( $showCopySubtreeNotification == 'enabled' );
 923  
 924  if( $chooseVersions )
 925      $allVersions = ( $Module->hasActionParameter( 'VersionChoice' ) and
 926                       $Module->actionParameter( 'VersionChoice' ) == 1 ) ? true : false;
 927  else
 928      $allVersions = ( $versionHandling == 'last-published' ) ? false : true;
 929  
 930  if ( $chooseCreator )
 931      $keepCreator = ( $Module->hasActionParameter( 'CreatorChoice' ) and
 932                       $Module->actionParameter( 'CreatorChoice' ) == 1 ) ? true : false;
 933  else
 934      $keepCreator = ( $creatorHandling == 'keep-unchanged' );
 935  
 936  if ( $chooseTime )
 937      $keepTime = ( $Module->hasActionParameter( 'TimeChoice' ) and
 938                    $Module->actionParameter( 'TimeChoice' ) == 1 ) ? true : false;
 939  else
 940      $keepTime = ( $timeHandling == 'keep-unchanged' );
 941  
 942  
 943  $keepCreator = false;
 944  $keepTime = false;
 945  
 946  if ( $Module->isCurrentAction( 'Copy' ) )
 947  {
 948      // actually do copying after a user has selected object versions to copy
 949      $newParentNodeID = $http->postVariable( 'SelectedNodeID' );
 950      copySubtree( $NodeID, $newParentNodeID, $notifications, $allVersions, $keepCreator, $keepTime );
 951  
 952      if ( $showNotification )
 953      {
 954          showNotificationAfterCopying( $http, $Module, $Result, $notifications, $srcNode );
 955          return;
 956      }
 957      return $Module->redirectToView( 'view', array( 'full', $newParentNodeID ) );
 958  }
 959  else if ( $Module->isCurrentAction( 'CopySubtree' ) )
 960  {
 961      // we get here after a user selects target node to place the source object under
 962      if( $chooseVersions or $chooseCreator or $chooseTime )
 963      {
 964          // redirect to the page with choice of versions to copy
 965          chooseOptionsToCopy( $Module, $Result, $srcNode, $chooseVersions, $chooseCreator, $chooseTime );
 966      }
 967      else
 968      {
 969          // actually do copying of the pre-configured object version(s)
 970          include_once ( 'kernel/classes/ezcontentbrowse.php' );
 971          $selectedNodeIDArray = eZContentBrowse::result( $Module->currentAction() );
 972          $newParentNodeID =& $selectedNodeIDArray[0];
 973          copySubtree( $NodeID, $newParentNodeID, $notifications, $allVersions, $keepCreator, $keepTime );
 974  
 975          if ( $showNotification )
 976          {
 977              showNotificationAfterCopying( $http, $Module, $Result, $notifications, $srcNode );
 978              return;
 979          }
 980          return $Module->redirectToView( 'view', array( 'full', $newParentNodeID ) );
 981      }
 982  }
 983  else // default, initial action
 984  {   //Browse for target node.
 985      //We get here when a user clicks "copy" button when viewing some node.
 986      browse( $Module, $srcNode );
 987  }
 988  
 989  ?>


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