static function remove($objectID, $removeSubtrees = true) { eZContentCacheManager::clearContentCacheIfNeeded($objectID); $object = eZContentObject::fetch($objectID); if (!is_object($object)) { return false; } // TODO: Is content cache cleared for all objects in subtree ?? if ($removeSubtrees) { $assignedNodes = $object->attribute('assigned_nodes'); if (count($assignedNodes) == 0) { $object->purge(); eZContentObject::expireAllViewCache(); return true; } $assignedNodeIDArray = array(); foreach ($assignedNodes as $node) { $assignedNodeIDArray[] = $node->attribute('node_id'); } eZContentObjectTreeNode::removeSubtrees($assignedNodeIDArray, false); } else { $object->purge(); } return true; }
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" ); }
/** * Deletes a content object, or a list of content objects * * @param array $deleteIDArray * @param bool $moveToTrash * * @return array An array with operation status, always true */ public static function deleteObject($deleteIDArray, $moveToTrash = false) { $ini = eZINI::instance(); $delayedIndexingValue = $ini->variable('SearchSettings', 'DelayedIndexing'); if ($delayedIndexingValue === 'enabled' || $delayedIndexingValue === 'classbased') { $pendingActionsToDelete = array(); $classList = $ini->variable('SearchSettings', 'DelayedIndexingClassList'); // Will be used below if DelayedIndexing is classbased $assignedNodesByObject = array(); $nodesToDeleteByObject = array(); $aNodes = eZContentObjectTreeNode::fetch($deleteIDArray); if (!is_array($aNodes)) { $aNodes = array($aNodes); } foreach ($aNodes as $node) { $object = $node->object(); $objectID = $object->attribute('id'); $assignedNodes = $object->attribute('assigned_nodes'); // Only delete pending action if this is the last object's node that is requested for deletion // But $deleteIDArray can also contain all the object's node (mainly if this method is called programmatically) // So if this is not the last node, then store its id in a temp array // This temp array will then be compared to the whole object's assigned nodes array if (count($assignedNodes) > 1) { // $assignedNodesByObject will be used as a referent to check if we want to delete all lasting nodes if (!isset($assignedNodesByObject[$objectID])) { $assignedNodesByObject[$objectID] = array(); foreach ($assignedNodes as $assignedNode) { $assignedNodesByObject[$objectID][] = $assignedNode->attribute('node_id'); } } // Store the node assignment we want to delete // Then compare the array to the referent node assignment array $nodesToDeleteByObject[$objectID][] = $node->attribute('node_id'); $diff = array_diff($assignedNodesByObject[$objectID], $nodesToDeleteByObject[$objectID]); if (!empty($diff)) { continue; } } if ($delayedIndexingValue !== 'classbased' || is_array($classList) && in_array($object->attribute('class_identifier'), $classList)) { $pendingActionsToDelete[] = $objectID; } } if (!empty($pendingActionsToDelete)) { $filterConds = array('param' => array($pendingActionsToDelete)); eZPendingActions::removeByAction('index_object', $filterConds); } } eZContentObjectTreeNode::removeSubtrees($deleteIDArray, $moveToTrash); return array('status' => true); }
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; }
static function subtreeRemovalInformation($deleteIDArray) { return eZContentObjectTreeNode::removeSubtrees($deleteIDArray, true, true); }
'$te' => $te, '$tm' => $tm, '$r' => $r, '$tr' => $tr, '$tf' => $tf, '$df' => $df, ), true)); */ $i_out = str_pad($i, strlen("{$count}")); $cli->output("[{$i_out}/{$count}] Remove node id : {$child_node_id}. estimated end : {$df} " . $child->url()); } else { $cli->output('-', false); } // Remove subtrees if (!$dryRun) { eZContentObjectTreeNode::removeSubtrees(array($child_node_id), $moveToTrash); } //TODO // // 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" ); } if ($dryRun) { // Si il n'y a pas de dry-run alors la liste des résultats se décale d'elle même. $params['Offset'] += $size;
continue; } $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 {
$nodeName = $deleteItem['node_name']; if ($node === null) { $cli->error("\nSubtree remove Error!\nCannot find subtree '{$nodeName}'."); continue; } $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), $moveToTrash); // 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"); } } $cli->output("Done."); $script->shutdown();
foreach ( $articles as $article ) { $nodeDeletionArray = array(); $assignedNodesAsArray = $article->object()->assignedNodes(false); foreach ( $assignedNodesAsArray as $assignedNodeAsArray ) { if ( $assignedNodeAsArray['node_id'] != $article->attribute('node_id') ) { $nodeDeletionArray[] = $assignedNodeAsArray['node_id']; } } if ( count($nodeDeletionArray) > 0 ) { $i+= count($nodeDeletionArray); eZContentObjectTreeNode::removeSubtrees( $nodeDeletionArray, false ); } $j++; if ( $j%5 == 0 && $j != 0 ) $cli->notice( date('Ymd h:i') . " : $j Articles have been cleaned (with a total of $i node deleted)."); } eZContentObject::clearCache(); $offset+= $limit; } $cli->notice("Purge of publisher folder $publisherFolderPath has finished."); }
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); } }
/** * Deletes a content object, or a list of content objects * * @param array $deleteIDArray * @param bool $moveToTrash * * @return array An array with operation status, always true */ public static function deleteObject($deleteIDArray, $moveToTrash = false) { eZContentObjectTreeNode::removeSubtrees($deleteIDArray, $moveToTrash); return array('status' => true); }
private function deleteSubtree($subtreeNodeId, $additional) { $effectiveLimit = eepSetting::DeleteNodesSanityCheck; if (isset($additional["limit"])) { $effectiveLimit = $additional["limit"]; } if (!eepValidate::validateContentNodeId($subtreeNodeId)) { throw new Exception("This is not a node id: [" . $subtreeNodeId . "]"); } // need to operate in a privileged account $adminUserObject = eZUser::fetch(eepSetting::PrivilegedAccountId); $adminUserObject->loginCurrent(); // get the name, just for display purposes $subtreeNode = eZContentObjectTreeNode::fetch($subtreeNodeId); $subtreeName = $subtreeNode->getName(); $subtreeCount = eZContentObjectTreeNode::subTreeCountByNodeID(array(), $subtreeNodeId); if ($subtreeCount > $effectiveLimit && 0 != $effectiveLimit) { echo "The number of subitems [" . $subtreeCount . "] exceeds the sanity check: [" . $effectiveLimit . "]\n"; return false; } /* // test that we can delete the subtree $info = eZContentObjectTreeNode::subtreeRemovalInformation( array($subtreeNodeId) ); if( !$info[ "can_remove_all" ] ) { //var_dump($info); echo "Permission is denied for the '" . $subtreeName . "' subtree [nodeid=". $subtreeNodeId . "]\n"; return false; // not that anyone is checking the return value ... } //*/ // do the removal $removeResult = eZContentObjectTreeNode::removeSubtrees(array($subtreeNodeId), false, false); if (true === $removeResult) { echo "Subtree '" . $subtreeName . "' removed ok\n"; } else { echo "Failed to remove subtree\n"; } $adminUserObject->logoutCurrent(); }
if (!$object->attribute('can_remove')) { $response[] = ezi18n('extension/contactivity/akismet/submit', "You are not allowed to remove this content object."); continue; } $assignedNodes = $object->attribute('assigned_nodes'); $nodeIdArray = array(); foreach (array_keys($assignedNodes) as $assignedNodeKey) { if ($assignedNodes[$assignedNodeKey]->attribute('can_remove')) { $nodeIdArray[] = $assignedNodes[$assignedNodeKey]->attribute('node_id'); } else { $nodeIdArray = false; break; } } if ($nodeIdArray) { eZContentObjectTreeNode::removeSubtrees($nodeIdArray, false); } else { $object->remove(); $object->purge(); } } } } $akismet = new eZContentObjectAkismet(); $extractableNodes = $akismet->getExtractableNodes($limit, $Offset); $extractableNodesCount = $akismet->getExtractableNodesCount(); include_once 'kernel/common/template.php'; $tpl = templateInit(); $tpl->setVariable('object_id_list', $objectIDList); $tpl->setVariable('view_parameters', $viewParameters); $tpl->setVariable('nodes', $extractableNodes);
/** * Deletes a content object, or a list of content objects * * @param array $deleteIDArray * @param bool $moveToTrash * * @return array An array with operation status, always true */ static public function deleteObject( $deleteIDArray, $moveToTrash = false ) { $ini = eZINI::instance(); $aNodes = eZContentObjectTreeNode::fetch( $deleteIDArray ); if( !is_array( $aNodes ) ) { $aNodes = array( $aNodes ); } $delayedIndexingValue = $ini->variable( 'SearchSettings', 'DelayedIndexing' ); if ( $delayedIndexingValue === 'enabled' || $delayedIndexingValue === 'classbased' ) { $pendingActionsToDelete = array(); $classList = $ini->variable( 'SearchSettings', 'DelayedIndexingClassList' ); // Will be used below if DelayedIndexing is classbased $assignedNodesByObject = array(); $nodesToDeleteByObject = array(); foreach ( $aNodes as $node ) { $object = $node->object(); $objectID = $object->attribute( 'id' ); $assignedNodes = $object->attribute( 'assigned_nodes' ); // Only delete pending action if this is the last object's node that is requested for deletion // But $deleteIDArray can also contain all the object's node (mainly if this method is called programmatically) // So if this is not the last node, then store its id in a temp array // This temp array will then be compared to the whole object's assigned nodes array if ( count( $assignedNodes ) > 1 ) { // $assignedNodesByObject will be used as a referent to check if we want to delete all lasting nodes if ( !isset( $assignedNodesByObject[$objectID] ) ) { $assignedNodesByObject[$objectID] = array(); foreach ( $assignedNodes as $assignedNode ) { $assignedNodesByObject[$objectID][] = $assignedNode->attribute( 'node_id' ); } } // Store the node assignment we want to delete // Then compare the array to the referent node assignment array $nodesToDeleteByObject[$objectID][] = $node->attribute( 'node_id' ); $diff = array_diff( $assignedNodesByObject[$objectID], $nodesToDeleteByObject[$objectID] ); if ( !empty( $diff ) ) // We still have more node assignments for object, pending action is not to be deleted considering this iteration { continue; } } if ( $delayedIndexingValue !== 'classbased' || ( is_array( $classList ) && in_array( $object->attribute( 'class_identifier' ), $classList ) ) ) { $pendingActionsToDelete[] = $objectID; } } if ( !empty( $pendingActionsToDelete ) ) { $filterConds = array( 'param' => array ( $pendingActionsToDelete ) ); eZPendingActions::removeByAction( 'index_object', $filterConds ); } } // Add assigned nodes to the clear cache list // This allows to clear assigned nodes separately (e.g. in reverse proxies) // as once content is removed, there is no more assigned nodes, and http cache clear is not possible any more. // See https://jira.ez.no/browse/EZP-22447 foreach ( $aNodes as $node ) { eZContentCacheManager::addAdditionalNodeIDPerObject( $node->attribute( 'contentobject_id' ), $node->attribute( 'node_id' ) ); } eZContentObjectTreeNode::removeSubtrees( $deleteIDArray, $moveToTrash ); return array( 'status' => true ); }
/** * 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; }