Exponential 6.0.13 Exponential Enterprise Open Source CMS - PHP Class Reference

ezcontentobjecttreenodeoperations.php
Go to the documentation of this file.
1 <?php
21 class eZContentObjectTreeNodeOperations
22 {
38 static function move( $nodeID, $newParentNodeID )
39 {
40 $result = false;
41
42 if ( !is_numeric( $nodeID ) || !is_numeric( $newParentNodeID ) )
43 return false;
44
45 $node = eZContentObjectTreeNode::fetch( $nodeID );
46 if ( !$node )
47 return false;
48
49 $object = $node->object();
50 if ( !$object )
51 return false;
52
53 $objectID = $object->attribute( 'id' );
54 $oldParentNode = $node->fetchParent();
55 $oldParentObject = $oldParentNode->object();
56
57 // clear user policy cache if this is a user object
58 if ( in_array( $object->attribute( 'contentclass_id' ), eZUser::contentClassIDs() ) )
59 {
60 eZUser::purgeUserCacheByUserId( $object->attribute( 'id' ) );
61 }
62
63 // clear cache for old placement.
64 // If child count exceeds threshold, do nothing here, and instead clear all view cache at the end.
65 $childCountInThresholdRange = eZContentCache::inCleanupThresholdRange( $node->childrenCount( false ) );
66 if ( $childCountInThresholdRange )
67 {
68 eZContentCacheManager::clearContentCacheIfNeeded( $objectID );
69 }
70
71 $db = eZDB::instance();
72 $db->begin();
73
74 $node->move( $newParentNodeID );
75
76 $newNode = eZContentObjectTreeNode::fetchNode( $objectID, $newParentNodeID );
77
78 if ( $newNode )
79 {
80 $newNode->updateSubTreePath( true, true );
81 if ( $newNode->attribute( 'main_node_id' ) == $newNode->attribute( 'node_id' ) )
82 {
83 // If the main node is moved we need to check if the section ID must change
84 $newParentNode = $newNode->fetchParent();
85 $newParentObject = $newParentNode->object();
86 if ( $object->attribute( 'section_id' ) != $newParentObject->attribute( 'section_id' ) )
87 {
88
89 eZContentObjectTreeNode::assignSectionToSubTree( $newNode->attribute( 'main_node_id' ),
90 $newParentObject->attribute( 'section_id' ),
91 $oldParentObject->attribute( 'section_id' ) );
92 }
93 }
94
95 // modify assignment
96 $curVersion = $object->attribute( 'current_version' );
97 $nodeAssignment = eZNodeAssignment::fetch( $objectID, $curVersion, $oldParentNode->attribute( 'node_id' ) );
98
99 if ( $nodeAssignment )
100 {
101 $nodeAssignment->setAttribute( 'parent_node', $newParentNodeID );
102 $nodeAssignment->setAttribute( 'op_code', eZNodeAssignment::OP_CODE_MOVE );
103 $nodeAssignment->store();
104 }
105
106 $result = true;
107 }
108 else
109 {
110 eZDebug::writeError( "Node $nodeID was moved to $newParentNodeID but fetching the new node failed" );
111 }
112
113 $db->commit();
114
115 if ( $newNode && !empty($nodeAssignment) )
116 {
117 // update search index specifying we are doing a move operation
118 $nodeIDList = array( $nodeID );
119 eZSearch::removeNodeAssignment( $node->attribute( 'main_node_id' ), $newNode->attribute( 'main_node_id' ), $object->attribute( 'id' ), $nodeIDList );
120 eZSearch::addNodeAssignment( $newNode->attribute( 'main_node_id' ), $object->attribute( 'id' ), $nodeIDList, true );
121 }
122
123 // clear cache for new placement.
124 // If child count exceeds threshold, clear all view cache instead.
125 if ( $childCountInThresholdRange )
126 {
127 eZContentCacheManager::clearContentCacheIfNeeded( $objectID );
128 }
129 else
130 {
131 eZContentCacheManager::clearAllContentCache();
132 }
133
134 return $result;
135 }
136
151 static function copy( $nodeID, $newParentNodeID )
152 {
153 $result = false;
154
155 if ( !is_numeric( $nodeID ) || !is_numeric( $newParentNodeID ) )
156 return false;
157
158 $node = eZContentObjectTreeNode::fetch( $nodeID );
159 if ( !$node )
160 return false;
161
162 $object = $node->object();
163 if ( !$object )
164 return false;
165
166 $objectID = $object->attribute( 'id' );
167 $oldParentNode = $node->fetchParent();
168 $oldParentObject = $oldParentNode->object();
169
170 $Result = array();
171 $notifications = array( 'Notifications' => array(),
172 'Warnings' => array(),
173 'Errors' => array(),
174 'Result' => false );
175 $contentINI = eZINI::instance( 'content.ini' );
176 $http = eZHTTPTool::instance();
177
178 // check if number of nodes being copied not more then MaxNodesCopySubtree setting
179 $maxNodesCopySubtree = $contentINI->variable( 'CopySettings', 'MaxNodesCopySubtree' );
180 $srcSubtreeNodesCount = $node->subTreeCount();
181
182 if ( $srcSubtreeNodesCount > $maxNodesCopySubtree )
183 {
184 $notifications['Warnings'][] = ezpI18n::tr( 'kernel/content/copysubtree',
185 "You are trying to copy a subtree that contains more than ".
186 "the maximum possible nodes for subtree copying. ".
187 "You can copy this subtree using Subtree Copy script.",
188 null, array( $maxNodesCopySubtree ) );
189 $notifications['Result'] = false;
190 self::showNotificationAfterCopying( $Result, $notifications, $node );
191 return;
192 }
193
194 // actually do copying of the pre-configured object version(s)
195 $notifications = self::copySubtree( $nodeID, $newParentNodeID, $notifications, true, true, true );
196
197 return $notifications;
198 }
199
200 static public function copySubtree( $srcNodeID, $dstNodeID, &$notifications, $allVersions, $keepCreator, $keepTime )
201 {
202 // 1. Copy subtree and form the arrays of accordance of the old and new nodes and content objects.
203
204 $sourceSubTreeMainNode = ( $srcNodeID ) ? eZContentObjectTreeNode::fetch( $srcNodeID ) : false;
205 $destinationNode = ( $dstNodeID ) ? eZContentObjectTreeNode::fetch( $dstNodeID ) : false;
206
207 if ( !$sourceSubTreeMainNode )
208 {
209 eZDebug::writeError( "Cannot get subtree main node (nodeID = $srcNodeID).",
210 "Subtree copy Error!" );
211 $notifications['Errors'][] = ezpI18n::tr( 'kernel/content/copysubtree',
212 "Fatal error: cannot get subtree main node (ID = %1).",
213 null, array( $srcNodeID ) );
214 $notifications['Result'] = false;
215 return $notifications;
216 }
217 if ( !$destinationNode )
218 {
219 eZDebug::writeError( "Cannot get destination node (nodeID = $dstNodeID).",
220 "Subtree copy Error!" );
221 $notifications['Errors'][] = ezpI18n::tr( 'kernel/content/copysubtree',
222 "Fatal error: cannot get destination node (ID = %1).",
223 null, array( $dstNodeID ) );
224 $notifications['Result'] = false;
225 return $notifications;
226 }
227
228 $sourceNodeList = array();
229
230 $syncNodeIDListSrc = array(); // arrays for synchronizing between source and new IDs of nodes
231 $syncNodeIDListNew = array();
232 $syncObjectIDListSrc = array(); // arrays for synchronizing between source and new IDs of contentobjects
233 $syncObjectIDListNew = array();
234
235 $sourceSubTreeMainNodeID = $sourceSubTreeMainNode->attribute( 'node_id' );
236 $sourceNodeList[] = $sourceSubTreeMainNode;
237
238 $syncNodeIDListSrc[] = $sourceSubTreeMainNode->attribute( 'parent_node_id' );
239 $syncNodeIDListNew[] = (int) $dstNodeID;
240
241 $nodeIDBlackList = array(); // array of nodes which are unable to copy
242 $objectIDBlackList = array(); // array of contentobjects which are unable to copy in any location inside new subtree
243
244 $sourceNodeList = array_merge( $sourceNodeList,
245 eZContentObjectTreeNode::subTreeByNodeID( array( 'Limitation' => array() ), $sourceSubTreeMainNodeID ) );
246 $countNodeList = count( $sourceNodeList );
247
248 $notifications['Notifications'][] = ezpI18n::tr( 'kernel/content/copysubtree',
249 "Number of nodes of source subtree - %1",
250 null, array( $countNodeList ) );
251 // Prepare list of source node IDs. We will need it in the future
252 // for checking node is inside or outside of the subtree being copied.
253 $sourceNodeIDList = array();
254 foreach ( $sourceNodeList as $sourceNode )
255 $sourceNodeIDList[] = $sourceNode->attribute( 'node_id' );
256
257 eZDebug::writeDebug( "Source NodeID = $srcNodeID, destination NodeID = $dstNodeID",
258 "Subtree copy: START!" );
259
260 // 1. copying and publishing source subtree
261 $k = 0;
262 while ( count( $sourceNodeList ) > 0 )
263 {
264 if ( $k > $countNodeList )
265 {
266 eZDebug::writeError( "Too many loops while copying nodes.",
267 "Subtree Copy Error!" );
268 break;
269 }
270
271 for ( $i = 0; $i < count( $sourceNodeList ); $i)
272 {
273 $sourceNodeID = $sourceNodeList[ $i ]->attribute( 'node_id' );
274
275 // if node was alreaty copied
276 if ( in_array( $sourceNodeID, $syncNodeIDListSrc ) )
277 {
278 array_splice( $sourceNodeList, $i, 1 );
279 continue;
280 }
281
283 // if node is already in black list, then skip current node:
284 if ( in_array( $sourceNodeID, $nodeIDBlackList ) )
285 {
286 array_splice( $sourceNodeList, $i, 1 );
287 continue;
288 }
289
290 $sourceObject = $sourceNodeList[ $i ]->object();
291
292 $srcSubtreeNodeIDlist = ($sourceNodeID == $sourceSubTreeMainNodeID) ? $syncNodeIDListSrc : $sourceNodeIDList;
293 $copyResult = self::copyPublishContentObject( $sourceObject,
294 $srcSubtreeNodeIDlist,
295 $syncNodeIDListSrc, $syncNodeIDListNew,
296 $syncObjectIDListSrc, $syncObjectIDListNew,
297 $objectIDBlackList, $nodeIDBlackList,
298 $notifications,
299 $allVersions, $keepCreator, $keepTime );
300 if ( $copyResult === 0 )
301 { // if copying successful then remove $sourceNode from $sourceNodeList
302 array_splice( $sourceNodeList, $i, 1 );
303 }
304 else
305 $i++;
306 }
307 $k++;
308 }
309
310 array_shift( $syncNodeIDListSrc );
311 array_shift( $syncNodeIDListNew );
312
313 $countNewNodes = count( $syncNodeIDListNew );
314 $countNewObjects = count( $syncObjectIDListNew );
315
316 $notifications['Notifications'][] = ezpI18n::tr( 'kernel/content/copysubtree',
317 "Number of copied nodes - %1",
318 null, array( $countNewNodes ) );
319 $notifications['Notifications'][] = ezpI18n::tr( 'kernel/content/copysubtree',
320 "Number of copied contentobjects - %1",
321 null, array( $countNewObjects ) );
322
323 eZDebug::writeDebug( count( $syncNodeIDListNew ), "Number of copied nodes: " );
324 eZDebug::writeDebug( count( $syncObjectIDListNew ), "Number of copied contentobjects: " );
325
326 eZDebug::writeDebug( $objectIDBlackList, "Copy subtree: Not copied object IDs list:" );
327 eZDebug::writeDebug( $nodeIDBlackList, "Copy subtree: Not copied node IDs list:" );
328
329 $key = array_search( $sourceSubTreeMainNodeID, $syncNodeIDListSrc );
330 if ( $key === false )
331 {
332 eZDebug::writeDebug( "Root node of given subtree was not copied.",
333 "Subtree copy:" );
334 $notifications['Result'] = false;
335 return $notifications;
336 }
337
338 // 2. fetch all new subtree
339
340 $newSubTreeMainNodeID = $syncNodeIDListSrc[ $key ];
341 $newSubTreeMainNode = eZContentObjectTreeNode::fetch( $newSubTreeMainNodeID );
342
343 $newNodeList[] = $newSubTreeMainNode;
344 $newNodeList = $sourceNodeList = array_merge( $newNodeList,
345 eZContentObjectTreeNode::subTreeByNodeID( false, $newSubTreeMainNodeID ) );
346
347 // 3. fix local links (in ezcontentobject_link)
348 eZDebug::writeDebug( "Fixing global and local links...",
349 "Subtree copy:" );
350
351 $db = eZDB::instance();
352 if ( !$db )
353 {
354 eZDebug::writeError( "Cannot create instance of eZDB for fixing local links (related objects).",
355 "Subtree Copy Error!" );
356 $notifications['Errors'][] = ezpI18n::tr( 'kernel/content/copysubtree',
357 "Cannot create instance of eZDB to fix local links (related objects)." );
358 return $notifications;
359 }
360
361 $idListINString = $db->generateSQLINStatement( $syncObjectIDListNew, 'from_contentobject_id', false, false, 'int' );
362 $relatedRecordsList = $db->arrayQuery( "SELECT * FROM ezcontentobject_link WHERE $idListINString" );
363
364 foreach ( $relatedRecordsList as $relatedEntry )
365 {
366 $kindex = array_search( $relatedEntry[ 'to_contentobject_id' ], $syncObjectIDListSrc );
367 if ( $kindex !== false )
368 {
369 $newToContentObjectID = (int) $syncObjectIDListNew[ $kindex ];
370 $linkID = (int) $relatedEntry[ 'id' ];
371 $db->query( "UPDATE ezcontentobject_link SET to_contentobject_id=$newToContentObjectID WHERE id=$linkID" );
372 }
373 }
374
375 // 4. duplicating of global links for new contentobjects (in ezurl_object_link) are automatic during copy of contentobject.
376 // it was fixed as bug patch.
377
378 // 5. fixing node_ids and object_ids in ezxmltext attributes of copied objects
379 $conditions = array( 'contentobject_id' => '', // 5
380 'data_type_string' => 'ezxmltext' );
381
382 foreach ( $syncObjectIDListNew as $contentObjectID )
383 {
384 $conditions[ 'contentobject_id' ] = $contentObjectID;
385 $attributeList = eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(), null, $conditions );
386 if ( count( $attributeList ) == 0 )
387 {
388 continue;
389 }
390 foreach ( $attributeList as $xmlAttribute )
391 {
392 $xmlText = $xmlAttribute->attribute( 'data_text' );
393 $xmlTextLen = strlen ( $xmlText );
394 $isTextModified = false;
395 $curPos = 0;
396
397 while ( $curPos < $xmlTextLen )
398 {
399 $literalTagBeginPos = strpos( $xmlText, "<literal", $curPos );
400 if ( $literalTagBeginPos )
401 {
402 $literalTagEndPos = strpos( $xmlText, "</literal>", $literalTagBeginPos );
403 if ( $literalTagEndPos === false )
404 break;
405 $curPos = $literalTagEndPos + 9;
406 }
407
408 if ( ($tagBeginPos = strpos( $xmlText, "<link", $curPos )) !== false or
409 ($tagBeginPos = strpos( $xmlText, "<a" , $curPos )) !== false or
410 ($tagBeginPos = strpos( $xmlText, "<embed",$curPos )) !== false )
411 {
412 $tagEndPos = strpos( $xmlText, ">", $tagBeginPos + 1 );
413 if ( $tagEndPos === false )
414 break;
415
416 $tagText = substr( $xmlText, $tagBeginPos, $tagEndPos - $tagBeginPos );
417
418 if ( ($nodeIDAttributePos = strpos( $tagText, " node_id=\"" )) !== false )
419 {
420 $idNumberPos = $nodeIDAttributePos + 10;
421 $quoteEndPos = strpos( $tagText, "\"", $idNumberPos );
422
423 if ( $quoteEndPos !== false )
424 {
425 $idNumber = substr( $tagText, $idNumberPos, $quoteEndPos - $idNumberPos );
426 $key = array_search( (int) $idNumber, $syncNodeIDListSrc );
427
428 if ( $key !== false )
429 {
430 $tagText = substr_replace( $tagText, (string) $syncNodeIDListNew[ $key ], $idNumberPos, $quoteEndPos - $idNumberPos );
431 $xmlText = substr_replace( $xmlText, $tagText, $tagBeginPos, $tagEndPos - $tagBeginPos );
432 $isTextModified = true;
433 }
434 }
435 }
436 else if ( ($objectIDAttributePos = strpos( $tagText, " object_id=\"" )) !== false )
437 {
438 $idNumberPos = $objectIDAttributePos + 12;
439 $quoteEndPos = strpos( $tagText, "\"", $idNumberPos );
440
441 if ( $quoteEndPos !== false )
442 {
443 $idNumber = substr( $tagText, $idNumberPos, $quoteEndPos - $idNumberPos );
444 $key = array_search( (int) $idNumber, $syncObjectIDListSrc );
445 if ( $key !== false )
446 {
447 $tagText = substr_replace( $tagText, (string) $syncObjectIDListNew[ $key ], $idNumberPos, $quoteEndPos - $idNumberPos );
448 $xmlText = substr_replace( $xmlText, $tagText, $tagBeginPos, $tagEndPos - $tagBeginPos );
449 $isTextModified = true;
450 }
451 }
452 }
453 $curPos = $tagEndPos;
454 }
455 else if ( ($tagBeginPos = strpos( $xmlText, "<object", $curPos )) !== false )
456 {
457 $tagEndPos = strpos( $xmlText, ">", $tagBeginPos + 1 );
458 if ( !$tagEndPos )
459 break;
460
461 $tagText = substr( $xmlText, $tagBeginPos, $tagEndPos - $tagBeginPos );
462
463 if ( ($idAttributePos = strpos( $tagText, " id=\"" )) !== false )
464 {
465 $idNumberPos = $idAttributePos + 5;
466 $quoteEndPos = strpos( $tagText, "\"", $idNumberPos );
467
468 if ( $quoteEndPos !== false )
469 {
470 $idNumber = substr( $tagText, $idNumberPos, $quoteEndPos - $idNumberPos );
471 $key = array_search( (int) $idNumber, $syncObjectIDListSrc );
472 if ( $key !== false )
473 {
474 $tagText = substr_replace( $tagText, (string) $syncObjectIDListNew[ $key ], $idNumberPos, $quoteEndPos - $idNumberPos );
475 $xmlText = substr_replace( $xmlText, $tagText, $tagBeginPos, $tagEndPos - $tagBeginPos );
476 $isTextModified = true;
477 }
478 }
479 }
480 $curPos = $tagEndPos;
481 }
482 else
483 break;
484
485 } // while END
486
487 if ( $isTextModified )
488 {
489 $xmlAttribute->setAttribute( 'data_text', $xmlText );
490 $xmlAttribute->store();
491 }
492 } // foreach END
493 }
494
495 // 6. fixing datatype ezobjectrelationlist
496 $conditions = array( 'contentobject_id' => '',
497 'data_type_string' => 'ezobjectrelationlist' );
498 foreach ( $syncObjectIDListNew as $contentObjectID )
499 {
500 $conditions[ 'contentobject_id' ] = $contentObjectID;
501 $attributeList = eZPersistentObject::fetchObjectList( eZContentObjectAttribute::definition(), null, $conditions );
502 if ( count( $attributeList ) == 0 )
503 {
504 continue;
505 }
506 foreach ( $attributeList as $relationListAttribute )
507 {
508 $relationsXmlText = $relationListAttribute->attribute( 'data_text' );
509 $relationsDom = eZObjectRelationListType::parseXML( $relationsXmlText );
510 $relationItems = $relationsDom->getElementsByTagName( 'relation-item' );
511 $isRelationModified = false;
512
513 foreach ( $relationItems as $relationItem )
514 {
515 $originalObjectID = $relationItem->getAttribute( 'contentobject-id' );
516
517 $key = array_search( $originalObjectID, $syncObjectIDListSrc );
518 if ( $key !== false )
519 {
520 $newObjectID = $syncObjectIDListNew[ $key ];
521 $relationItem->setAttribute( 'contentobject-id', $newObjectID );
522 $isRelationModified = true;
523 }
524
525 $originalNodeID = $relationItem->getAttribute( 'node-id' );
526 if ( $originalNodeID )
527 {
528 $key = array_search( $originalNodeID, $syncNodeIDListSrc );
529 if ( $key !== false )
530 {
531 $newNodeID = $syncNodeIDListNew[ $key ];
532 $relationItem->setAttribute( 'node-id', $newNodeID );
533
534 $newNode = eZContentObjectTreeNode::fetch( $newNodeID );
535 $newParentNodeID = $newNode->attribute( 'parent_node_id' );
536 $relationItem->setAttribute( 'parent-node-id', $newParentNodeID );
537 $isRelationModified = true;
538 }
539 }
540 }
541 if ( $isRelationModified )
542 {
543 $attributeID = $relationListAttribute->attribute( 'id' );
544 $attributeVersion = $relationListAttribute->attribute( 'version' );
545 $changedDomString =$db->escapeString( eZObjectRelationListType::domString( $relationsDom ) );
546 $db->query( "UPDATE ezcontentobject_attribute SET data_text='$changedDomString'
547 WHERE id=$attributeID AND version=$attributeVersion" );
548 }
549 }
550 }
551
552 eZDebug::writeDebug( "Successfuly DONE.",
553 "Copy subtree:" );
554
555 $notifications['Result'] = true;
556 return $notifications;
557 } // function copySubtree END
558
559 static public function showNotificationAfterCopying( &$Result, &$Notifications, $srcNode )
560 {
561 $tpl = eZTemplate::factory();
562
563 $tpl->setVariable( 'current_user', eZUser::currentUser() );
564 $tpl->setVariable( 'ui_context', false );
565
566 $navigationPartString = 'ezmynavigationpart';
567 $navigationPart = eZNavigationPart::fetchPartByIdentifier( $navigationPartString );
568
569 $tpl->setVariable( 'navigation_part', $navigationPart );
570
571 $tpl->setVariable( 'source_node', $srcNode );
572 $tpl->setVariable( 'notifications', $Notifications );
573
574 $Result['content'] = $tpl->fetch( 'design:content/copy_subtrees_notification.tpl' );
575
576 $Result['path'] = array( array( 'url' => false,
577 'text' => ezpI18n::tr( 'kernel/content', 'Content' ) ),
578 array( 'url' => false,
579 'text' => ezpI18n::tr( 'kernel/content', 'Copy subtrees' ) ) );
580
581 $tpl->setVariable( 'module_result', array( 'content' => $Result['content'], 'path' => $Result['path'] ) );
582
583 $Result['pagelayout'] = $tpl->fetch( 'design:pagelayout.tpl', false, true );
584
585 require_once 'kernel/private/classes/global_functions.php';
586
587 ob_start();
588 eZDisplayResult( $Result['pagelayout']['result_text'] );
589 $content .= ob_get_clean();
590
591 $kernelResult = new ezpKernelResult( $content, array( 'module_result' => $Result['pagelayout']['result_text'] ) );
592
593 echo $kernelResult->getContent();
594 eZExecution::cleanExit();
595 }
596
597 static public function copyPublishContentObject( $sourceObject,
598 $sourceSubtreeNodeIDList,
599 &$syncNodeIDListSrc, &$syncNodeIDListNew,
600 &$syncObjectIDListSrc, &$syncObjectIDListNew,
601 $objectIDBlackList, &$nodeIDBlackList,
602 &$notifications,
603 $allVersions = false, $keepCreator = false, $keepTime = false )
604 {
605 $sourceObjectID = $sourceObject->attribute( 'id' );
606
607 $key = array_search( $sourceObjectID, $syncObjectIDListSrc );
608 if ( $key !== false )
609 {
610 eZDebug::writeDebug( "Object (ID = $sourceObjectID) has been already copied.",
611 "Subtree copy: copyPublishContentObject()" );
612 return 1; // object already copied
613 }
614
615 $srcNodeList = $sourceObject->attribute( 'assigned_nodes' );
616
617 // if we already failed to copy that contentobject, then just skip it:
618 if ( in_array( $sourceObjectID, $objectIDBlackList ) )
619 return 0;
620 // if we already failed to copy that node, then just skip it:
621 //if ( in_array( $sourceNodeID, $nodeIDBlackList ) )
622 // return 0;
623
624 // if cannot read contentobject then remember it and all its nodes (nodes
625 // which are inside subtree being copied) in black list, and skip current node:
626 if ( !$sourceObject->attribute( 'can_read' ) )
627 {
628 $objectIDBlackList[] = $sourceObjectID;
629 $notifications['Warnings'][] = ezpI18n::tr( 'kernel/content/copysubtree',
630 "Object (ID = %1) was not copied: you do not have permission to read the object.",
631 null, array( $sourceObjectID ) );
632
633 $srcNodeList = $sourceObject->attribute( 'assigned_nodes' );
634 foreach( $srcNodeList as $srcNode )
635 {
636 $srcNodeID = $srcNode->attribute( 'node_id' );
637 $sourceParentNodeID = $srcNode->attribute( 'parent_node_id' );
638
639 $key = array_search( $sourceParentNodeID, $sourceSubtreeNodeIDList );
640 if ( $key !== false )
641 {
642 $nodeIDBlackList[] = $srcNodeID;
643 $notifications['Warnings'][] = ezpI18n::tr( 'kernel/content/copysubtree',
644 "Node (ID = %1) was not copied: you do not have permission to read object (ID = %2).",
645 null, array( $srcNodeID, $sourceObjectID ) );
646 }
647 }
648 return 0;
649 }
650
651 // check if all possible parent nodes for given contentobject are already published:
652 $isReadyToPublish = false;
653 foreach ( $srcNodeList as $srcNode )
654 {
655 $srcNodeID = $srcNode->attribute( 'node_id' );
656
657 if ( in_array( $srcNodeID, $nodeIDBlackList ) )
658 continue;
659
660 $srcParentNodeID = $srcNode->attribute( 'parent_node_id' );
661
662 // if parent node for this node is outside
663 // of subtree being copied, then skip this node:
664 $key = array_search( $srcParentNodeID, $sourceSubtreeNodeIDList );
665 if ( $key === false )
666 continue;
667
668 // if parent node for this node wasn't copied yet and is in black list
669 // then add that node in black list and just skip it:
670 $key = array_search( $srcParentNodeID, $nodeIDBlackList );
671 if ( $key !== false )
672 {
673 $nodeIDBlackList[] = $srcNodeID;
674 $notifications['Warnings'][] = ezpI18n::tr( 'kernel/content/copysubtree',
675 "Node (ID = %1) was not copied: parent node (ID = %2) was not copied.",
676 null, array( $srcNodeID, $srcParentNodeID ) );
677 continue;
678 }
679
680 $key = array_search( $srcParentNodeID, $syncNodeIDListSrc );
681 if ( $key === false )
682 {
683 // if parent node is not copied yet and not in black list,
684 // then just skip sourceObject from copying for next time
685 eZDebug::writeDebug( "Parent node (ID = $srcParentNodeID) for contentobject (ID = $sourceObjectID) is not published yet.",
686 "Subtree copy: copyPublishContentObject()" );
687 return 2;
688 }
689 else
690 {
691 $newParentNodeID = $syncNodeIDListNew[ $key ];
692 $newParentNode = eZContentObjectTreeNode::fetch( $newParentNodeID );
693 if ( $newParentNode === null )
694 {
695 eZDebug::writeError( "Cannot fetch one of parent nodes. Error are somewhere above",
696 "Subtree copy error: copyPublishContentObject()" );
697 return 3;
698 }
699
700 if ( $newParentNode->checkAccess( 'create', $sourceObject->attribute( 'contentclass_id' ) ) != 1 )
701 {
702 $nodeIDBlackList[] = $srcNodeID;
703 $notifications['Warnings'][] = ezpI18n::tr( 'kernel/content/copysubtree',
704 "Node (ID = %1) was not copied: you do not have permission to create.",
705 null, array( $srcNodeID ) );
706
707 continue;
708 }
709 else
710 $isReadyToPublish = true;
711 }
712 }
713
714 // if all nodes of sourceObject were skiped as black list entry or
715 // as outside of subtree being copied, then sourceObject cannot be
716 // copied and published in any new location. So insert sourceObject
717 // in a black list and skip it.
718 if ( $isReadyToPublish == false )
719 {
720 $objectIDBlackList[] = $sourceObjectID;
721 $notifications['Warnings'][] = ezpI18n::tr( 'kernel/content/copysubtree',
722 "Object (ID = %1) was not copied: no one nodes of object was not copied.",
723 null, array( $sourceObjectID) );
724 return 0;
725 }
726
727 $db = eZDB::instance();
728 $db->begin();
729
730 // make copy of source object
731 $newObject = $sourceObject->copy( $allVersions ); // insert source and new object's ids in $syncObjectIDList
732 // We should reset section that will be updated in updateSectionID().
733 // If sectionID is 0 than the object has been newly created
734 $newObject->setAttribute( 'section_id', 0 );
735 $newObject->store();
736
737 $syncObjectIDListSrc[] = $sourceObjectID;
738
739 $curVersion = $newObject->attribute( 'current_version' );
740 $curVersionObject = $newObject->attribute( 'current' );
741
742 $newObjAssignments = $curVersionObject->attribute( 'node_assignments' );
743
744 // copy nodeassigments:
745 $assignmentsForRemoving = array();
746 $foundMainAssignment = false;
747 foreach ( $newObjAssignments as $assignment )
748 {
749 $parentNodeID = $assignment->attribute( 'parent_node' );
750
751 // if assigment is outside of subtree being copied then do not copy this assigment
752 $key1 = array_search( $parentNodeID, $sourceSubtreeNodeIDList );
753 $key2 = array_search( $parentNodeID, $nodeIDBlackList );
754 if ( $key1 === false or $key2 !== false )
755 {
756 $assignmentsForRemoving[] = $assignment->attribute( 'id' );
757 continue;
758 }
759
760 $key = array_search( $parentNodeID, $syncNodeIDListSrc );
761 if ( $key === false )
762 {
763 eZDebug::writeError( "Cannot publish contentobject (ID=$sourceObjectID). Parent is not published yet.",
764 "Subtree Copy error: copyPublishContentObject()" );
765 return 4;
766 }
767
768 if ( $assignment->attribute( 'is_main' ) )
769 $foundMainAssignment = true;
770
771 $newParentNodeID = $syncNodeIDListNew[ $key ];
772 $assignment->setAttribute( 'parent_node', $newParentNodeID );
773 $assignment->store();
774 }
775 // remove assigments which are outside of subtree being copied:
776 eZNodeAssignment::purgeByID( $assignmentsForRemoving );
777
778 // if main nodeassigment was not copied then set as main first nodeassigment
779 if ( $foundMainAssignment == false )
780 {
781 $newObjAssignments = $curVersionObject->attribute( 'node_assignments' );
782 // We need to check if it has any assignments before changing the data.
783 if ( isset( $newObjAssignments[0] ) )
784 {
785 $newObjAssignments[0]->setAttribute( 'is_main', 1 );
786 $newObjAssignments[0]->store();
787 }
788 }
789
790 $db->commit();
791
792 // publish the newly created object
793 $result = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $newObject->attribute( 'id' ),
794 'version' => $curVersion ) );
795 // Refetch the object data since it might change in the database.
796 $newObjectID = $newObject->attribute( 'id' );
797 $newObject = eZContentObject::fetch( $newObjectID );
798 $newNodeList = $newObject->attribute( 'assigned_nodes' );
799 if ( count($newNodeList) == 0 )
800 {
801 $newObject->purge();
802 eZDebug::writeError( "Cannot publish contentobject.",
803 "Subtree Copy Error!" );
804 $sourceObjectName = $srcNode->getName();
805 $notifications['Warnings'][] = ezpI18n::tr( 'kernel/content/copysubtree',
806 "Cannot publish object (Name: %1, ID: %2).",
807 null, array( $sourceObjectName, $sourceObjectID ) );
808 return -1;
809 }
810 else
811 {
812 $sourceObjectName = $srcNode->getName();
813 $notifications['Notifications'][] = ezpI18n::tr( 'kernel/content/copysubtree',
814 "Published object (Name: %1, ID: %2).",
815 null, array( $sourceObjectName, $sourceObjectID ) );
816 }
817 // Only if the object has been published successfully, the object id can be added into $syncObjectIDListNew
818 $syncObjectIDListNew[] = $newObject->attribute( 'id' );
819
820 $objAssignments = $curVersionObject->attribute( 'node_assignments' );
821 foreach ( $newNodeList as $newNode )
822 {
823 $newParentNode = $newNode->fetchParent();
824 $newParentNodeID = $newParentNode->attribute( 'node_id' );
825
826 $keyA = array_search( $newParentNodeID, $syncNodeIDListNew );
827 if ( $keyA === false )
828 {
829 eZDebug::writeError( "Algoritm ERROR! Cannot find new parent node ID in new ID's list",
830 "Subtree Copy Error!" );
831 return -2;
832 }
833
834 $srcParentNodeID = $syncNodeIDListSrc[ $keyA ];
835
836 // Update attributes of node
837 $bSrcParentFound = false;
838 foreach ( $srcNodeList as $srcNode )
839 {
840 if ( $srcNode->attribute( 'parent_node_id' ) == $srcParentNodeID )
841 {
842 $newNode->setAttribute( 'priority', $srcNode->attribute( 'priority' ) );
843 $newNode->setAttribute( 'is_hidden', $srcNode->attribute( 'is_hidden' ) );
844 // Update node visibility
845 if ( $newParentNode->attribute( 'is_invisible' ) or $newParentNode->attribute( 'is_hidden' ) )
846 $newNode->setAttribute( 'is_invisible', 1 );
847 else
848 $newNode->setAttribute( 'is_invisible', $srcNode->attribute( 'is_invisible' ) );
849
850 $newNode->store();
851 $syncNodeIDListSrc[] = $srcNode->attribute( 'node_id' );
852 $syncNodeIDListNew[] = $newNode->attribute( 'node_id' );
853 $bSrcParentFound = true;
854 break;
855 }
856 }
857 if ( $bSrcParentFound == false )
858 {
859 eZDebug::writeError( "Cannot find source parent node in list of nodes already copied.",
860 "Subtree Copy Error!" );
861 }
862 }
863
864 // if $keepCreator == true then keep owner of contentobject being
865 // copied and creator of its published version Unchaged
866 $isModified = false;
867 if ( $keepTime )
868 {
869 $srcPublished = $sourceObject->attribute( 'published' );
870 $newObject->setAttribute( 'published', $srcPublished );
871 $srcModified = $sourceObject->attribute( 'modified' );
872 $newObject->setAttribute( 'modified', $srcModified );
873 $isModified = true;
874 }
875 if ( $keepCreator )
876 {
877 $srcOwnerID = $sourceObject->attribute( 'owner_id' );
878 $newObject->setAttribute( 'owner_id', $srcOwnerID );
879 $isModified = true;
880 }
881 if ( $isModified )
882 $newObject->store();
883
884 if ( $allVersions )
885 { // copy time of creation and midification and creator id for
886 // all versions of content object being copied.
887 $srcVersionsList = $sourceObject->versions();
888
889 foreach ( $srcVersionsList as $srcVersionObject )
890 {
891 $newVersionObject = $newObject->version( $srcVersionObject->attribute( 'version' ) );
892 if ( !is_object( $newVersionObject ) )
893 continue;
894
895 $isModified = false;
896 if ( $keepTime )
897 {
898 $srcVersionCreated = $srcVersionObject->attribute( 'created' );
899 $newVersionObject->setAttribute( 'created', $srcVersionCreated );
900 $srcVersionModified = $srcVersionObject->attribute( 'modified' );
901 $newVersionObject->setAttribute( 'modified', $srcVersionModified );
902 $isModified = true;
903 }
904 if ( $keepCreator )
905 {
906 $srcVersionCreatorID = $srcVersionObject->attribute( 'creator_id' );
907 $newVersionObject->setAttribute( 'creator_id', $srcVersionCreatorID );
908
909 $isModified = true;
910 }
911 if ( $isModified )
912 $newVersionObject->store();
913 }
914 }
915 else // if not all versions copied
916 {
917 $srcVersionObject = $sourceObject->attribute( 'current' );
918 $newVersionObject = $newObject->attribute( 'current' );
919
920 $isModified = false;
921 if ( $keepTime )
922 {
923 $srcVersionCreated = $srcVersionObject->attribute( 'created' );
924 $newVersionObject->setAttribute( 'created', $srcVersionCreated );
925 $srcVersionModified = $srcVersionObject->attribute( 'modified' );
926 $newVersionObject->setAttribute( 'modified', $srcVersionModified );
927 $isModified = true;
928 }
929 if ( $keepCreator )
930 {
931 $srcVersionCreatorID = $srcVersionObject->attribute( 'creator_id' );
932 $newVersionObject->setAttribute( 'creator_id', $srcVersionCreatorID );
933 $isModified = true;
934 }
935 if ( $isModified )
936 $newVersionObject->store();
937 }
938
939 return 0; // source object was copied successfully.
940
941 } // function copyPublishContentObject END
942
943 }
944
945
946 ?>
eZContentCacheManager\clearAllContentCache
static clearAllContentCache( $ignoreINISettings=false)
Definition: ezcontentcachemanager.php:1116
eZContentCacheManager\clearContentCacheIfNeeded
static clearContentCacheIfNeeded( $objectID, $versionNum=true, $additionalNodeList=false)
Definition: ezcontentcachemanager.php:1062
eZContentCache\inCleanupThresholdRange
static inCleanupThresholdRange( $value)
Definition: ezcontentcache.php:248
eZContentObjectAttribute\definition
static definition()
Definition: ezcontentobjectattribute.php:38
eZContentObjectTreeNodeOperations
The class eZContentObjectTreeNodeOperations is a wrapper for node's core-operations....
Definition: ezcontentobjecttreenodeoperations.php:22
eZContentObjectTreeNodeOperations\move
static move( $nodeID, $newParentNodeID)
Definition: ezcontentobjecttreenodeoperations.php:38
eZContentObjectTreeNodeOperations\showNotificationAfterCopying
static showNotificationAfterCopying(&$Result, &$Notifications, $srcNode)
Definition: ezcontentobjecttreenodeoperations.php:559
eZContentObjectTreeNodeOperations\copyPublishContentObject
static copyPublishContentObject( $sourceObject, $sourceSubtreeNodeIDList, &$syncNodeIDListSrc, &$syncNodeIDListNew, &$syncObjectIDListSrc, &$syncObjectIDListNew, $objectIDBlackList, &$nodeIDBlackList, &$notifications, $allVersions=false, $keepCreator=false, $keepTime=false)
Definition: ezcontentobjecttreenodeoperations.php:597
eZContentObjectTreeNodeOperations\copySubtree
static copySubtree( $srcNodeID, $dstNodeID, &$notifications, $allVersions, $keepCreator, $keepTime)
Definition: ezcontentobjecttreenodeoperations.php:200
eZContentObjectTreeNodeOperations\copy
static copy( $nodeID, $newParentNodeID)
Definition: ezcontentobjecttreenodeoperations.php:151
eZContentObjectTreeNode\assignSectionToSubTree
static assignSectionToSubTree( $nodeID, $sectionID, $oldSectionID=false, $updateSearchIndexes=true)
Definition: ezcontentobjecttreenode.php:2828
eZContentObjectTreeNode\fetch
static fetch( $nodeID=false, $lang=false, $asObject=true, $conditions=false)
Definition: ezcontentobjecttreenode.php:3058
eZContentObjectTreeNode\fetchNode
static fetchNode( $contentObjectID, $parentNodeID)
Definition: ezcontentobjecttreenode.php:3172
eZContentObjectTreeNode\subTreeByNodeID
static subTreeByNodeID( $params=false, $nodeID=0)
Definition: ezcontentobjecttreenode.php:1940
eZContentObject\fetch
static fetch( $id, $asObject=true)
Definition: ezcontentobject.php:885
eZDB\instance
static instance( $databaseImplementation=false, $databaseParameters=false, $forceNewInstance=false)
Definition: ezdb.php:117
eZDebug\writeError
static writeError( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:545
eZDebug\writeDebug
static writeDebug( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:588
eZExecution\cleanExit
static cleanExit()
Definition: ezexecution.php:100
eZHTTPTool\instance
static instance()
Definition: ezhttptool.php:189
eZNavigationPart\fetchPartByIdentifier
static fetchPartByIdentifier( $identifier)
Definition: eznavigationpart.php:41
eZNodeAssignment\fetch
static fetch( $contentObjectID, $version=1, $parentNode=0, $asObject=true)
Definition: eznodeassignment.php:409
eZNodeAssignment\OP_CODE_MOVE
const OP_CODE_MOVE
Definition: eznodeassignment.php:29
eZNodeAssignment\purgeByID
static purgeByID( $assignmentID)
Definition: eznodeassignment.php:364
eZObjectRelationListType\parseXML
static parseXML( $xmlText)
Definition: ezobjectrelationlisttype.php:1469
eZObjectRelationListType\domString
static domString( $domDocument)
Definition: ezobjectrelationlisttype.php:768
eZOperationHandler\execute
static execute( $moduleName, $operationName, $operationParameters, $lastTriggerName=null, $useTriggers=true)
Definition: ezoperationhandler.php:42
eZPersistentObject\fetchObjectList
static fetchObjectList( $def, $field_filters=null, $conds=null, $sorts=null, $limit=null, $asObject=true, $grouping=false, $custom_fields=null, $custom_tables=null, $custom_conds=null)
Definition: ezpersistentobject.php:806
eZSearch\removeNodeAssignment
static removeNodeAssignment( $mainNodeID, $newMainNodeID, $objectID, $nodeAssigmentIDList)
Definition: ezsearch.php:586
eZSearch\addNodeAssignment
static addNodeAssignment( $mainNodeID, $objectID, $nodeAssignmentIDList, $isMoved=false)
Definition: ezsearch.php:564
eZTemplate\factory
static factory()
Definition: eztemplate.php:2380
eZUser\purgeUserCacheByUserId
static purgeUserCacheByUserId( $userId)
Definition: ezuser.php:1345
eZUser\contentClassIDs
static contentClassIDs()
Definition: ezuser.php:2912
eZUser\currentUser
static currentUser()
Definition: ezuser.php:1716
ezpI18n\tr
static tr( $context, $source, $comment=null, $arguments=null)
Definition: ezpi18n.php:86
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.