function removeSubtree( $nodeIDs, $moveToTrash ) { global $cli; $cli->output( "Attempting to remove the following subtrees: " . join( ", ", $nodeIDs ) ); eZContentObjectTreeNode::removeSubtrees( $nodeIDs, $moveToTrash ); // We should make sure that all subitems have been removed. $itemInfo = eZContentObjectTreeNode::subtreeRemovalInformation( array( $nodeIDs ) ); $itemTotalChildCount = $itemInfo['total_child_count']; $itemDeleteList = $itemInfo['delete_list']; if ( count( $itemDeleteList ) != 0 or ( $childCount != 0 and $itemTotalChildCount != 0 ) ) $cli->error( "WARNING!\nSome subitems have not been removed.\n" ); else $cli->output( "Successfully removed batch of children.\n" ); }
/** * Regression test for issue #16949 * 1) Test there is no pending object in sub objects * 2) Test there is one pending object in sub objects */ public function testIssue16949() { //create object $top = new ezpObject( 'article', 2 ); $top->title = 'TOP ARTICLE'; $top->publish(); $child = new ezpObject( 'article', $top->mainNode->node_id ); $child->title = 'THIS IS AN ARTICLE'; $child->publish(); $adminUser = eZUser::fetchByName( 'admin' ); $adminUserID = $adminUser->attribute( 'contentobject_id' ); $currentUser = eZUser::currentUser(); $currentUserID = eZUser::currentUserID(); eZUser::setCurrentlyLoggedInUser( $adminUser, $adminUserID ); $result = eZContentObjectTreeNode::subtreeRemovalInformation( array( $top->mainNode->node_id ) ); $this->assertFalse( $result['has_pending_object'] ); $workflowArticle = new ezpObject( 'article', $top->mainNode->node_id ); $workflowArticle->title = 'THIS IS AN ARTICLE WITH WORKFLOW'; $workflowArticle->publish(); $version = $workflowArticle->currentVersion(); $version->setAttribute( 'status', eZContentObjectVersion::STATUS_PENDING ); $version->store(); $result = eZContentObjectTreeNode::subtreeRemovalInformation( array( $top->mainNode->node_id ) ); $this->assertTrue( $result['has_pending_object'] ); eZUser::setCurrentlyLoggedInUser( $currentUser, $currentUserID ); }
function uninstall( $package, $installType, $parameters, $name, $os, $filename, $subdirectory, $content, &$installParameters, &$installData ) { $this->Package = $package; if ( isset( $installParameters['error']['error_code'] ) ) $errorCode = $installParameters['error']['error_code']; else $errorCode = false; // Error codes reserverd for content object uninstallation if ( !$errorCode || ( $errorCode >= self::UNINSTALL_OBJECTS_ERROR_RANGE_FROM && $errorCode <= self::UNINSTALL_OBJECTS_ERROR_RANGE_TO ) ) { $objectListNode = $content->getElementsByTagName( 'object-list' )->item( 0 ); if ( $objectListNode ) { $objectNodes = $objectListNode->getElementsByTagName( 'object' ); } else { $objectListNode = $content->getElementsByTagName( 'object-files-list' )->item( 0 ); $objectNodes = $objectListNode->getElementsByTagName( 'object-file' ); } // loop intentionally from the last until the first // objects need to be uninstalled in reverse order of installation for ( $i = $objectNodes->length - 1; $i >=0; $i-- ) { $objectNode = $objectNodes->item( $i ); $realObjectNode = $this->getRealObjectNode( $objectNode ); $objectRemoteID = $realObjectNode->getAttribute( 'remote_id' ); $name = $realObjectNode->getAttribute( 'name' ); if ( isset( $installParameters['error']['error_code'] ) && !$this->isErrorElement( $objectRemoteID, $installParameters ) ) continue; if ( isset( $object ) ) { eZContentObject::clearCache( $object->attribute( 'id' ) ); unset( $object ); } $object = eZContentObject::fetchByRemoteID( $objectRemoteID ); if ( $object !== null ) { $modified = $object->attribute( 'modified' ); $published = $object->attribute( 'published' ); if ( $modified > $published ) { $choosenAction = $this->errorChoosenAction( eZContentObject::PACKAGE_ERROR_MODIFIED, $installParameters, false, $this->HandlerType ); if ( $choosenAction == eZContentObject::PACKAGE_KEEP ) { continue; } if ( $choosenAction != eZContentObject::PACKAGE_DELETE ) { $installParameters['error'] = array( 'error_code' => eZContentObject::PACKAGE_ERROR_MODIFIED, 'element_id' => $objectRemoteID, 'description' => ezpI18n::tr( 'kernel/package', "Object '%objectname' has been modified since installation. Are you sure you want to remove it?", false, array( '%objectname' => $name ) ), 'actions' => array( eZContentObject::PACKAGE_DELETE => ezpI18n::tr( 'kernel/package', 'Remove' ), eZContentObject::PACKAGE_KEEP => ezpI18n::tr( 'kernel/package', 'Keep object' ) ) ); return false; } } $assignedNodes = $object->attribute( 'assigned_nodes' ); $assignedNodeIDArray = array(); foreach( $assignedNodes as $node ) { $assignedNodeIDArray[] = $node->attribute( 'node_id' ); } if ( count( $assignedNodeIDArray ) == 0 ) continue; $info = eZContentObjectTreeNode::subtreeRemovalInformation( $assignedNodeIDArray ); $childrenCount = $info['total_child_count']; if ( $childrenCount > 0 ) { $choosenAction = $this->errorChoosenAction( eZContentObject::PACKAGE_ERROR_HAS_CHILDREN, $installParameters, false, $this->HandlerType ); if ( $choosenAction == eZContentObject::PACKAGE_KEEP ) { continue; } if ( $choosenAction != eZContentObject::PACKAGE_DELETE ) { $installParameters['error'] = array( 'error_code' => eZContentObject::PACKAGE_ERROR_HAS_CHILDREN, 'element_id' => $objectRemoteID, 'description' => ezpI18n::tr( 'kernel/package', "Object '%objectname' has %childrencount sub-item(s) that will be removed.", false, array( '%objectname' => $name, '%childrencount' => $childrenCount ) ), 'actions' => array( eZContentObject::PACKAGE_DELETE => ezpI18n::tr( 'kernel/package', "Remove object and its sub-item(s)" ), eZContentObject::PACKAGE_KEEP => ezpI18n::tr( 'kernel/package', 'Keep object' ) ) ); return false; } } eZContentObjectTreeNode::removeSubtrees( $assignedNodeIDArray, false ); //eZContentObjectOperations::remove( $object->attribute( 'id' ) ); } else { eZDebug::writeNotice( "Can't uninstall object '$name': object not found", __METHOD__ ); } unset( $realObjectNode ); } } return true; }
if ($http->hasPostVariable("ConfirmButton") or $hideRemoveConfirm) { if (eZOperationHandler::operationIsAvailable('content_delete')) { $operationResult = eZOperationHandler::execute('content', 'delete', array('node_id_list' => $deleteIDArray, 'move_to_trash' => $moveToTrash), null, true); } else { eZContentOperationCollection::deleteObject($deleteIDArray, $moveToTrash); } if ($http->hasSessionVariable('RedirectURIAfterRemove') && $http->sessionVariable('RedirectURIAfterRemove')) { $Module->redirectTo($http->sessionVariable('RedirectURIAfterRemove')); $http->removeSessionVariable('RedirectURIAfterRemove'); return $http->removeSessionVariable('RedirectIfCancel'); } else { return $Module->redirectToView('view', array($viewMode, $contentNodeID, $contentLanguage)); } } $showCheck = $contentINI->hasVariable('RemoveSettings', 'ShowRemoveToTrashCheck') ? $contentINI->variable('RemoveSettings', 'ShowRemoveToTrashCheck') == 'false' ? false : true : true; $info = eZContentObjectTreeNode::subtreeRemovalInformation($deleteIDArray); $deleteResult = $info['delete_list']; $moveToTrashAllowed = $info['move_to_trash']; $totalChildCount = $info['total_child_count']; $hasPendingObject = $info['has_pending_object']; $exceededLimit = false; $deleteNodeIdArray = array(); // Check if number of nodes being removed not more then MaxNodesRemoveSubtree setting. $maxNodesRemoveSubtree = $contentINI->hasVariable('RemoveSettings', 'MaxNodesRemoveSubtree') ? $contentINI->variable('RemoveSettings', 'MaxNodesRemoveSubtree') : 100; $deleteItemsExist = true; // If false, we should disable 'OK' button if count of each deletion items more then MaxNodesRemoveSubtree setting. foreach (array_keys($deleteResult) as $removeItemKey) { $removeItem =& $deleteResult[$removeItemKey]; $deleteNodeIdArray[$removeItem['node']->attribute('node_id')] = 1; if ($removeItem['child_count'] > $maxNodesRemoveSubtree) { $removeItem['exceeded_limit_of_subitems'] = true;
$nodeID = $node->attribute('node_id'); $childCount = $deleteItem['child_count']; $objectNodeCount = $deleteItem['object_node_count']; $cli->output("Node id: {$nodeID}"); $cli->output("Node name: {$nodeName}"); $canRemove = $deleteItem['can_remove']; if (!$canRemove) { $cli->error("\nSubtree remove Error!\nInsufficient permissions. You do not have permissions to remove the subtree with nodeID: {$nodeID}\n"); continue; } $cli->output("Child count: {$childCount}"); $cli->output("Object node count: {$objectNodeCount}"); // Remove subtrees eZContentObjectTreeNode::removeSubtrees(array($nodeID), $argumentsTrash); // We should make sure that all subitems have been removed. $itemInfo = eZContentObjectTreeNode::subtreeRemovalInformation(array($nodeID)); $itemTotalChildCount = $itemInfo['total_child_count']; $itemDeleteList = $itemInfo['delete_list']; /* if ( count( $itemDeleteList ) != 0 or ( $childCount != 0 and $itemTotalChildCount != 0 ) ) $cli->error( "\nWARNING!\nSome subitems have not been removed.\n" ); else $cli->output( "Successfuly DONE.\n" ); */ } // Prepare exit message to user if (count($itemDeleteList) != 0 or $childCount != 0 and $itemTotalChildCount != 0) { $cli->error("\nWARNING!\n The script has completed normally but some nodes have not been removed successfully.\n"); } else { // Alert user to script completion result summary $cli->output("\n" . 'The script has exited normally. Assume nodes removed successfully.' . "\n");
private function deleteClass($classIdentifier) { $chunkSize = 1000; $classId = eZContentClass::classIDByIdentifier($classIdentifier); $contentClass = eZContentClass::fetch($classId); if (!$contentClass) { throw new Exception("Failed to instantiate content class. [" . $classIdentifier . "]"); } $totalObjectCount = eZContentObject::fetchSameClassListCount($classId); echo "Deleting " . $totalObjectCount . " objects.\n"; $moreToDelete = 0 < $totalObjectCount; $totalDeleted = 0; // need to operate in a privileged account - use doug@mugo.ca $adminUserObject = eZUser::fetch(eepSetting::PrivilegedAccountId); $adminUserObject->loginCurrent(); while ($moreToDelete) { $params["IgnoreVisibility"] = true; $params['Limitation'] = array(); $params['Limit'] = $chunkSize; $params['ClassFilterType'] = "include"; $params['ClassFilterArray'] = array($classIdentifier); $children = eZContentObjectTreeNode::subTreeByNodeID($params, 2); foreach ($children as $child) { $info = eZContentObjectTreeNode::subtreeRemovalInformation(array($child->NodeID)); if (!$info["can_remove_all"]) { $msg = " permission is denied for nodeid=" . $child->NodeID; // todo, this can yield an infinite loop if some objects are // not deleteable, but you don't take that number into account // at the bottom of the loop - where there will always be // some >0 number of undeleteable objects left echo $msg . "\n"; continue; } $removeResult = eZContentObjectTreeNode::removeSubtrees(array($child->NodeID), false, false); if (true === $removeResult) { $totalDeleted += 1; } else { $msg = " failed to delete nodeid=" . $child->NodeID; echo $msg . "\n"; } echo "Percent complete: " . sprintf("% 3.3f", $totalDeleted / $totalObjectCount * 100.0) . "%\r"; unset($GLOBALS['eZContentObjectContentObjectCache']); unset($GLOBALS['eZContentObjectDataMapCache']); unset($GLOBALS['eZContentObjectVersionCache']); } $moreToDelete = 0 < eZContentObject::fetchSameClassListCount($classId); } echo "\nDone deleting objects.\n"; $adminUserObject->logoutCurrent(); eZContentClassClassGroup::removeClassMembers($classId, 0); eZContentClassClassGroup::removeClassMembers($classId, 1); // Fetch real version and remove it $contentClass->remove(true); // this seems to mainly cause an exception, might be an idea to simply skip it // Fetch temp version and remove it $tempDeleteClass = eZContentClass::fetch($classId, true, 1); if ($tempDeleteClass != null) { $tempDeleteClass->remove(true, 1); } }
/** * Removes content object * * @param eZContentObject $object * @return bool true if object was removed, otherwise false */ public function removeObject(eZContentObject $object) { $objectName = $object->attribute('name'); $this->debug('Removing "' . $objectName . '" object (class: ' . $object->attribute('class_name') . ') with remote ID ' . $object->attribute('remote_id')); $this->db->begin(); $object->resetDataMap(); eZContentObject::clearCache($object->attribute('id')); if (is_null($object->attribute('main_node'))) { $object->purge(); $this->db->commit(); $this->debug('[Removed] "' . $objectName . '"'); return true; } else { $removeNodeIDs = array($object->attribute('main_node')->attribute('node_id')); $nodeAssigments = eZNodeAssignment::fetchForObject($object->attribute('id')); foreach ($nodeAssigments as $assigment) { $node = $assigment->attribute('node'); if ($node instanceof eZContentObjectTreeNode) { $removeNodeIDs[] = $node->attribute('node_id'); } } $removeNodeIDs = array_unique($removeNodeIDs); $info = eZContentObjectTreeNode::subtreeRemovalInformation($removeNodeIDs); foreach ($info['delete_list'] as $deleteItem) { $node = $deleteItem['node']; if ($node === null) { continue; } if ($deleteItem['can_remove']) { eZContentObjectTreeNode::removeSubtrees(array($node->attribute('node_id')), false); $this->debug('[Removed] "' . $objectName . '", Node ID: ' . $node->attribute('node_id'), array('red')); } } $this->db->commit(); } return false; }