private function trash_list() { $params = false; $asCount = false; $trashObjects = eZContentObjectTrashNode::trashList($params, $asCount); eep::displayNodeList($trashObjects, "Garbage Nodes"); }
/** * Regression test for issue #16737 * 1) Test executing the sql and verify that it doesn't have database error. * 2) Test the sorting in class_name, class_name with contentobject_id * The test should pass in mysql, postgresql and oracle */ public function testIssue16737() { //test generated result of createSortingSQLStrings $sortList = array( array( 'class_name', true ) ); $result = eZContentObjectTreeNode::createSortingSQLStrings( $sortList ); $this->assertEquals( ', ezcontentclass_name.name as contentclass_name', strtolower( $result['attributeTargetSQL'] ) ); $this->assertEquals( 'contentclass_name asc', strtolower( $result['sortingFields'] ) ); $sortListTwo = array( array( 'class_name', false ), array( 'class_identifier', true ) ); $result = eZContentObjectTreeNode::createSortingSQLStrings( $sortListTwo ); $this->assertEquals( ', ezcontentclass_name.name as contentclass_name', strtolower( $result['attributeTargetSQL'] )); $this->assertEquals( 'contentclass_name desc, ezcontentclass.identifier asc', strtolower( $result['sortingFields'] ) ); //test trash node with classname $sortBy = array( array( 'class_name', true ), array( 'contentobject_id', true ) ); $params = array( 'SortBy', $sortBy ); $result = eZContentObjectTrashNode::trashList( $params ); $this->assertEquals( array(), $result ); $result = eZContentObjectTrashNode::trashList( $params, true ); $this->assertEquals( 0, $result ); //if there is an error, there will be fatal error message //test subtreenode with classname $parent = new ezpObject( 'folder', 1 ); $parent->publish(); $parentNodeID = $parent->mainNode->node_id; $article = new ezpObject( 'article', $parentNodeID ); $article->publish(); $link = new ezpObject( 'link', $parentNodeID ); $link->publish(); $folder = new ezpObject( 'folder', $parentNodeID ); $folder->publish(); $folder2 = new ezpObject( 'folder', $parentNodeID ); $folder2->publish(); $sortBy = array( array( 'class_name', false ) ); $params = array( 'SortBy' => $sortBy ); $result = eZContentObjectTreeNode::subTreeByNodeID( $params, $parentNodeID ); $this->assertEquals( $article->mainNode->node_id, $result[count( $result )-1]->attribute( 'node_id' ) ); $sortBy = array( array( 'class_name', false ), array( 'contentobject_id', false ) ); $params = array( 'SortBy' => $sortBy ); $result = eZContentObjectTreeNode::subTreeByNodeID( $params, $parentNodeID ); $this->assertEquals( $folder2->mainNode->node_id, $result[1]->attribute( 'node_id' ) ); }
/** * Unit test for eZContentObject::relatedObjectCount() * * Outline: * 1) Create a content class with ezobjectrelation and ezobjectrelationlist * attributes * 2) Create objects and relate them to each of these attributes and to the * object itself (common) * 3) Check that attribute count is correct on each attribute and globally */ public function testRelatedObjectCount() { // Create a test content class $class = new ezpClass(__FUNCTION__, __FUNCTION__, 'name'); $class->add('Name', 'name', 'ezstring'); $attributes['single_relation_1'] = $class->add('Single relation #1', 'single_relation_1', 'ezobjectrelation')->attribute('id'); $attributes['single_relation_2'] = $class->add('Single relation #2', 'single_relation_2', 'ezobjectrelation')->attribute('id'); $attributes['multiple_relations_1'] = $class->add('Multiple relations #1', 'multiple_relations_1', 'ezobjectrelationlist')->attribute('id'); $attributes['multiple_relations_2'] = $class->add('Multiple relations #2', 'multiple_relations_2', 'ezobjectrelationlist')->attribute('id'); $class->store(); // create a few articles we will relate our object to $relatedObjects = array(); for ($i = 0; $i < 10; $i++) { $article = new ezpObject('article', 2); $article->title = "Related object #'{$i} for " . __FUNCTION__; $article->publish(); $relatedObjects[] = $article->attribute('id'); } // Create a test object with various relations (some objects are related // to multiple attributes in order to test reverse relations): // - 1 relation (IDX 0) on single_relation_1 // - 1 relation (IDX 1) on single_relation_2 // - 2 relations (IDX 2, 3) on multiple_relations_1 // - 2 relations (IDX 4, 5) on multiple_relations_2 // - 6 object level relations ((IDX 6, 7, 8, 9) $object = new ezpObject(__FUNCTION__, 2); $object->name = __FUNCTION__; $object->single_relation_1 = $relatedObjects[0]; $object->single_relation_2 = $relatedObjects[1]; $object->multiple_relations_1 = array($relatedObjects[0], $relatedObjects[2], $relatedObjects[3]); $object->multiple_relations_2 = array($relatedObjects[1], $relatedObjects[4], $relatedObjects[5]); $object->addContentObjectRelation($relatedObjects[0]); $object->addContentObjectRelation($relatedObjects[1]); $object->addContentObjectRelation($relatedObjects[6]); $object->addContentObjectRelation($relatedObjects[7]); $object->addContentObjectRelation($relatedObjects[8]); $object->addContentObjectRelation($relatedObjects[9]); $object->publish(); // Create 2 more objects with relations to $relatedObjects[9] // in order to test reverse related objects $otherObject1 = new ezpObject(__FUNCTION__, 2); $otherObject1->name = "Reverse test object #1 for " . __FUNCTION__; $otherObject1->single_relation_1 = $relatedObjects[9]; $otherObject1->publish(); $otherObject2 = new ezpObject(__FUNCTION__, 2); $otherObject2->name = "Reverse test object #2 for " . __FUNCTION__; $otherObject2->single_relation_2 = $relatedObjects[9]; $otherObject2->publish(); $contentObject = eZContentObject::fetch($object->attribute('id')); $paramAllRelations = array('AllRelations' => true); $paramAttributeRelations = array('AllRelations' => eZContentObject::RELATION_ATTRIBUTE); $paramCommonRelations = array('AllRelations' => eZContentObject::RELATION_COMMON); // Test overall relation count $this->assertEquals(14, $contentObject->relatedObjectCount(false, false, false, $paramAllRelations), "Overall relation count should be 14"); // Test relation count for each attribute $this->assertEquals(1, $contentObject->relatedObjectCount(false, $attributes['single_relation_1'], false, $paramAttributeRelations), "Relation count on attribute single_relation_1 should be 1"); $this->assertEquals(1, $contentObject->relatedObjectCount(false, $attributes['single_relation_2'], false, $paramAttributeRelations), "Relation count on attribute single_relation_2 should be 1"); $this->assertEquals(3, $contentObject->relatedObjectCount(false, $attributes['multiple_relations_1'], false, $paramAttributeRelations), "Relation count on attribute multiple_relations_1 should be 3"); $this->assertEquals(3, $contentObject->relatedObjectCount(false, $attributes['multiple_relations_2'], false, $paramAttributeRelations), "Relation count on attribute multiple_relations_2 should be 3"); // Test common level relation count $this->assertEquals(6, $contentObject->relatedObjectCount(false, false, false, $paramCommonRelations), "Common relations count should be 6"); // Test reverse relation count on $relatedObject[9] // This object is related to: // - the main $object on common level // - one object on single_relation_1 // - another object on single_relation_2 $relatedContentObject = eZContentObject::fetch($relatedObjects[9]); $this->assertEquals(3, $relatedContentObject->relatedObjectCount(false, false, true, $paramAllRelations), "Overall reverse relation count should be 3"); $this->assertEquals(1, $relatedContentObject->relatedObjectCount(false, false, true, $paramCommonRelations), "Common reverse relation count should be 1"); $this->assertEquals(1, $relatedContentObject->relatedObjectCount(false, $attributes['single_relation_1'], true, $paramAttributeRelations), "Attribute reverse relation count on single_relation_1 should be 1"); $this->assertEquals(1, $relatedContentObject->relatedObjectCount(false, $attributes['single_relation_2'], true, $paramAttributeRelations), "Attribute reverse relation count on single_relation_2 should be 1"); // Test that trashed objects are not counted as related (issue #15142) $trashObject = eZContentObject::fetch($relatedObjects[9]); $trashObject->removeThis(); $this->assertEquals(13, $contentObject->relatedObjectCount(false, false, false, $paramAllRelations), "Relation count after move to trash should be 13"); // Empty the trash foreach (eZContentObjectTrashNode::trashList() as $node) { eZContentObjectTrashNode::purgeForObject($node->attribute('contentobject_id')); } }
public static function fetchTrashObjectList($offset, $limit, $objectNameFilter, $attributeFilter = false, $sortBy = false, $asObject = true) { $params = array(); if ($objectNameFilter !== false) { $params['ObjectNameFilter'] = $objectNameFilter; } $params['Limit'] = $limit; $params['Offset'] = $offset; $params['AttributeFilter'] = $attributeFilter; $params['SortBy'] = $sortBy; $params['AsObject'] = $asObject; $trashNodesList = eZContentObjectTrashNode::trashList($params, false); return array('result' => $trashNodesList); }
$object->store(); $version->setAttribute('status', eZContentObjectVersion::STATUS_DRAFT); $version->store(); $user = eZUser::currentUser(); $operationResult = eZOperationHandler::execute('content', 'publish', array('object_id' => $objectID, 'version' => $version->attribute('version'))); if (array_key_exists('status', $operationResult) && $operationResult['status'] != eZModuleOperationInfo::STATUS_CONTINUE) { switch ($operationResult['status']) { case eZModuleOperationInfo::STATUS_HALTED: case eZModuleOperationInfo::STATUS_CANCELLED: $module->redirectToView('trash'); } } $objectID = $object->attribute('id'); $object = eZContentObject::fetch($objectID); $mainNodeID = $object->attribute('main_node_id'); eZContentObjectTrashNode::purgeForObject($objectID); if ($locationAdded) { if ($object->attribute('contentclass_id') == $userClassID) { eZUser::purgeUserCacheByUserId($object->attribute('id')); } } eZContentObject::fixReverseRelations($objectID, 'restore'); $db->commit(); $module->redirectToView('view', array('full', $mainNodeID)); return; } $tpl = eZTemplate::factory(); $res = eZTemplateDesignResource::instance(); $designKeys = array(array('object', $object->attribute('id')), array('remote_id', $object->attribute('remote_id')), array('class', $class->attribute('id')), array('class_identifier', $class->attribute('identifier'))); // Class identifier $res->setKeys($designKeys);
/** * Returns the number of nodes in the trash * * @param array|bool $params * @return int */ static function trashListCount($params = false) { return eZContentObjectTrashNode::trashList($params, true); }
static function removeRelationObject($contentObjectAttribute, $deletionItem) { if (self::isItemPublished($deletionItem)) { return; } $hostObject = $contentObjectAttribute->attribute('object'); $hostObjectID = $hostObject->attribute('id'); // Do not try removing the object if present in trash // Only objects being really orphaned (not even being in trash) should be removed by this method. // See issue #019457 if ((int) eZPersistentObject::count(eZContentObjectTrashNode::definition(), array("contentobject_id" => $hostObjectID)) > 0) { return; } $hostObjectVersions = $hostObject->versions(); $isDeletionAllowed = true; // check if the relation item to be deleted is unique in the domain of all host-object versions foreach ($hostObjectVersions as $version) { if ($isDeletionAllowed and $version->attribute('version') != $contentObjectAttribute->attribute('version')) { $relationAttribute = eZPersistentObject::fetchObjectList(eZContentObjectAttribute::definition(), null, array('version' => $version->attribute('version'), 'contentobject_id' => $hostObjectID, 'contentclassattribute_id' => $contentObjectAttribute->attribute('contentclassattribute_id'))); if (count($relationAttribute) > 0) { $relationContent = $relationAttribute[0]->content(); if (is_array($relationContent) and is_array($relationContent['relation_list'])) { foreach ($relationContent['relation_list'] as $relationItem) { if ($deletionItem['contentobject_id'] == $relationItem['contentobject_id'] && $deletionItem['contentobject_version'] == $relationItem['contentobject_version']) { $isDeletionAllowed = false; break 2; } } } } } } if ($isDeletionAllowed) { $subObjectVersion = eZContentObjectVersion::fetchVersion($deletionItem['contentobject_version'], $deletionItem['contentobject_id']); if ($subObjectVersion instanceof eZContentObjectVersion) { $subObjectVersion->removeThis(); } else { eZDebug::writeError('Cleanup of subobject-version failed. Could not fetch object from relation list.\\n' . 'Requested subobject id: ' . $deletionItem['contentobject_id'] . '\\n' . 'Requested Subobject version: ' . $deletionItem['contentobject_version'], __METHOD__); } } }
/** * Executes the purge operation * * @param int|null $iterationLimit Number of trashed objects to treat per iteration, use null to use a default value. * @param int|null $sleep Number of seconds to sleep between two iterations, use null to use a default value. * * @return bool True if the operation succeeded. */ public function run($iterationLimit = 100, $sleep = 1) { if ($iterationLimit === null) { $iterationLimit = 100; } if ($sleep === null) { $sleep = 1; } if ($this->memoryMonitoring) { eZLog::rotateLog($this->logFile); $this->cli->output("Logging memory usage to {$this->logFile}"); } $this->cli->output("Purging trash items:"); $this->monitor("start"); $db = eZDB::instance(); // Get user's ID who can remove subtrees. (Admin by default with userID = 14) $userCreatorID = eZINI::instance()->variable("UserSettings", "UserCreatorID"); $user = eZUser::fetch($userCreatorID); if (!$user) { $this->cli->error("Cannot get user object with userID = '{$userCreatorID}'.\n(See site.ini[UserSettings].UserCreatorID)"); return false; } eZUser::setCurrentlyLoggedInUser($user, $userCreatorID); $trashCount = eZContentObjectTrashNode::trashListCount(false); if (!$this->quiet) { $this->cli->output("Found {$trashCount} object(s) in trash."); } if ($trashCount == 0) { return true; } if ($this->script !== null) { $this->script->resetIteration($trashCount); } while ($trashCount > 0) { $this->monitor("iteration start"); $trashList = eZContentObjectTrashNode::trashList(array('Limit' => $iterationLimit), false); $db->begin(); foreach ($trashList as $trashNode) { $object = $trashNode->attribute('object'); $this->monitor("purge"); $object->purge(); if ($this->script !== null) { $this->script->iterate($this->cli, true); } } if (!$db->commit()) { $this->cli->output(); $this->cli->error('Trash has not been emptied, impossible to commit the whole transaction'); return false; } $trashCount = eZContentObjectTrashNode::trashListCount(false); if ($trashCount > 0) { eZContentObject::clearCache(); if ($sleep > 0) { sleep($sleep); } } $this->monitor("iteration end"); } if (!$this->quiet) { $this->cli->output('Trash successfully emptied'); } $this->monitor("end"); return true; }
function removeNodeFromTree($moveToTrash = true) { $nodeID = $this->attribute('node_id'); $object = $this->object(); $assignedNodes = $object->attribute('assigned_nodes'); if ($nodeID == $this->attribute('main_node_id')) { if (count($assignedNodes) > 1) { $newMainNode = false; foreach ($assignedNodes as $assignedNode) { $assignedNodeID = $assignedNode->attribute('node_id'); if ($assignedNodeID == $nodeID) { continue; } $newMainNode = $assignedNode; break; } // We need to change the main node ID before we remove the current node $db = eZDB::instance(); $db->begin(); eZContentObjectTreeNode::updateMainNodeID($newMainNode->attribute('node_id'), $object->attribute('id'), $object->attribute('current_version'), $newMainNode->attribute('parent_node_id')); $this->removeThis(); eZSearch::addObject($object); $db->commit(); } else { // This is the last assignment so we remove the object too $db = eZDB::instance(); $db->begin(); $this->removeThis(); if ($moveToTrash) { // saving information about this node in ..trash_node table $trashNode = eZContentObjectTrashNode::createFromNode($this); $db = eZDB::instance(); $db->begin(); $trashNode->storeToTrash(); $db->commit(); $object->removeThis(); } else { $object->purge(); } $db->commit(); } } else { $this->removeThis(); if (count($assignedNodes) > 1) { eZSearch::addObject($object); } } }
/** * Deletes the current object, all versions and translations, and corresponding tree nodes from the database * * Transaction unsafe. If you call several transaction unsafe methods you must enclose * the calls within a db transaction; thus within db->begin and db->commit. */ function purge() { $delID = $this->ID; // Who deletes which content should be logged. eZAudit::writeAudit( 'content-delete', array( 'Object ID' => $delID, 'Content Name' => $this->attribute( 'name' ), 'Comment' => 'Purged the current object: eZContentObject::purge()' ) ); $db = eZDB::instance(); $db->begin(); $attrOffset = 0; $attrLimit = 20; while ( $contentobjectAttributes = $this->allContentObjectAttributes( $delID, true, array( 'limit' => $attrLimit, 'offset' => $attrOffset ) ) ) { foreach ( $contentobjectAttributes as $contentobjectAttribute ) { $dataType = $contentobjectAttribute->dataType(); if ( !$dataType ) continue; $dataType->deleteStoredObjectAttribute( $contentobjectAttribute ); } $attrOffset += $attrLimit; } eZInformationCollection::removeContentObject( $delID ); eZContentObjectTrashNode::purgeForObject( $delID ); $db->query( "DELETE FROM ezcontentobject_tree WHERE contentobject_id='$delID'" ); $db->query( "DELETE FROM ezcontentobject_attribute WHERE contentobject_id='$delID'" ); $db->query( "DELETE FROM ezcontentobject_version WHERE contentobject_id='$delID'" ); $db->query( "DELETE FROM ezcontentobject_name WHERE contentobject_id='$delID'" ); $db->query( "DELETE FROM ezcobj_state_link WHERE contentobject_id=$delID" ); $db->query( "DELETE FROM ezcontentobject WHERE id='$delID'" ); $db->query( "DELETE FROM eznode_assignment WHERE contentobject_id = '$delID'" ); $db->query( "DELETE FROM ezuser_role WHERE contentobject_id = '$delID'" ); $db->query( "DELETE FROM ezuser_discountrule WHERE contentobject_id = '$delID'" ); eZContentObject::fixReverseRelations( $delID, 'remove' ); eZSearch::removeObjectById( $delID ); // Check if deleted object is in basket/wishlist $sql = 'SELECT DISTINCT ezproductcollection_item.productcollection_id FROM ezbasket, ezwishlist, ezproductcollection_item WHERE ( ezproductcollection_item.productcollection_id=ezbasket.productcollection_id OR ezproductcollection_item.productcollection_id=ezwishlist.productcollection_id ) AND ezproductcollection_item.contentobject_id=' . $delID; $rows = $db->arrayQuery( $sql ); if ( count( $rows ) > 0 ) { $countElements = 50; $deletedArray = array(); // Create array of productCollectionID will be removed from ezwishlist and ezproductcollection_item foreach ( $rows as $row ) { $deletedArray[] = $row['productcollection_id']; } // Split $deletedArray into several arrays with $countElements values $splitted = array_chunk( $deletedArray, $countElements ); // Remove eZProductCollectionItem and eZWishList foreach ( $splitted as $value ) { eZPersistentObject::removeObject( eZProductCollectionItem::definition(), array( 'productcollection_id' => array( $value, '' ) ) ); eZPersistentObject::removeObject( eZWishList::definition(), array( 'productcollection_id' => array( $value, '' ) ) ); } } $db->query( 'UPDATE ezproductcollection_item SET contentobject_id = 0 WHERE contentobject_id = ' . $delID ); // Cleanup relations in two steps to avoid locking table for to long $db->query( "DELETE FROM ezcontentobject_link WHERE from_contentobject_id = '$delID'" ); $db->query( "DELETE FROM ezcontentobject_link WHERE to_contentobject_id = '$delID'" ); // Cleanup properties: LastVisit, Creator, Owner $db->query( "DELETE FROM ezuservisit WHERE user_id = '$delID'" ); $db->query( "UPDATE ezcontentobject_version SET creator_id = 0 WHERE creator_id = '$delID'" ); $db->query( "UPDATE ezcontentobject SET owner_id = 0 WHERE owner_id = '$delID'" ); if ( isset( $GLOBALS["eZWorkflowTypeObjects"] ) and is_array( $GLOBALS["eZWorkflowTypeObjects"] ) ) { $registeredTypes =& $GLOBALS["eZWorkflowTypeObjects"]; } else { $registeredTypes = eZWorkflowType::fetchRegisteredTypes(); } // Cleanup ezworkflow_event etc... foreach ( array_keys( $registeredTypes ) as $registeredTypeKey ) { $registeredType = $registeredTypes[$registeredTypeKey]; $registeredType->cleanupAfterRemoving( array( 'DeleteContentObject' => $delID ) ); } $db->commit(); }