diff --git a/lib/documentmanagement/documentutil.inc.php b/lib/documentmanagement/documentutil.inc.php index 1a94f8d..68076d6 100644 --- a/lib/documentmanagement/documentutil.inc.php +++ b/lib/documentmanagement/documentutil.inc.php @@ -1076,20 +1076,62 @@ $sourceDocument->getName(), Indexer::index($oDocument); } + function canBeCopied($oDocument, &$sError) { + if ($oDocument->getIsCheckedOut()) { + $sError = PEAR::raiseError(_kt('Document cannot be copied as it is checked out.')); + return false; + } + if (!KTWorkflowUtil::actionEnabledForDocument($oDocument, 'ktcore.actions.document.copy')) { + $sError = PEAR::raiseError(_kt('Document cannot be copied as it is restricted by the workflow.')); + return false; + } + return true; + } - function canBeMoved($oDocument) { + function canBeMoved($oDocument, &$sError) { + if ($oDocument->getImmutable()) { + $sError = PEAR::raiseError(_kt('Document cannot be moved as it is immutable.')); + return false; + } if ($oDocument->getIsCheckedOut()) { + $sError = PEAR::raiseError(_kt('Document cannot be moved as it is checked out.')); return false; } if (!KTWorkflowUtil::actionEnabledForDocument($oDocument, 'ktcore.actions.document.move')) { + $sError = PEAR::raiseError(_kt('Document cannot be moved as it is restricted by the workflow.')); return false; } - if ($oDocument->getImmutable()) { + return true; + } + + function canBeDeleted($oDocument, &$sError) { + if($oDocument->getImmutable()) + { + $sError = PEAR::raiseError(_kt('Document cannot be deleted as it is immutable.')); + return false; + } + if ($oDocument->getIsCheckedOut()) { + $sError = PEAR::raiseError(_kt('Document cannot be deleted as it is checked out.')); + return false; + } + if(!KTWorkflowUtil::actionEnabledForDocument($oDocument, 'ktcore.actions.document.delete')){ + $sError = PEAR::raiseError(_kt('Document cannot be deleted as it is restricted by the workflow.')); return false; } return true; } + function canBeArchived($oDocument, &$sError) { + if ($oDocument->getIsCheckedOut()) { + $sError = PEAR::raiseError(_kt('Document cannot be archived as it is checked out.')); + return false; + } + if(!KTWorkflowUtil::actionEnabledForDocument($oDocument, 'ktcore.actions.document.archive')){ + $sError = PEAR::raiseError(_kt('Document cannot be archived as it is restricted by the workflow.')); + return false; + } + return true; + } function copy($oDocument, $oDestinationFolder, $sReason = null, $sDestinationDocName = null) { // 1. generate a new triad of content, metadata and core objects. diff --git a/plugins/ktcore/KTBulkActions.php b/plugins/ktcore/KTBulkActions.php index 553feaf..bd6c5cf 100644 --- a/plugins/ktcore/KTBulkActions.php +++ b/plugins/ktcore/KTBulkActions.php @@ -53,14 +53,64 @@ class KTBulkDeleteAction extends KTBulkAction { function check_entity($oEntity) { if(is_a($oEntity, 'Document')) { - if($oEntity->getImmutable()) - { - return PEAR::raiseError(_kt('Document cannot be deleted as it is immutable')); + if(!KTDocumentUtil::canBeDeleted($oEntity, $sError)) { + if (PEAR::isError($sError)) + { + return $sError; + } + return PEAR::raiseError(_kt('Document cannot be deleted')); } - if(!KTWorkflowUtil::actionEnabledForDocument($oEntity, 'ktcore.actions.document.delete')){ - return PEAR::raiseError(_kt('Document cannot be deleted as it is restricted by the workflow.')); + } + + if(is_a($oEntity, 'Folder')) { + $aDocuments = array(); + $aChildFolders = array(); + + $oFolder = $oEntity; + + // Get folder id + $sFolderId = $oFolder->getID(); + + // Get documents in folder + $sDocuments = $oFolder->getDocumentIDs($sFolderId); + $aDocuments = (!empty($sDocuments)) ? explode(',', $sDocuments) : array(); + + // Loop through documents and send to this function for checking + if(!empty($aDocuments)){ + foreach($aDocuments as $sDocID){ + $oDocument = Document::get($sDocID); + $res = $this->check_entity($oDocument); + if (PEAR::isError($res)) + { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be deleted + return PEAR::raiseError(_kt('Folder cannot be deleted')); + } + } + } + + // If all documents at the current level may be deleted, we can continue + // Get any existing subfolders + $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR + parent_folder_ids LIKE '{$sFolderId},%' OR + parent_folder_ids LIKE '%,{$sFolderId},%' OR + parent_folder_ids LIKE '%,{$sFolderId}'"; + $aChildFolders = $this->oFolder->getList($sWhereClause); + + // Loop through subfolders and check each in the same way as the parent + if(!empty($aChildFolders)){ + foreach($aChildFolders as $oChild){ + $res = $this->check_entity($oChild); + if (PEAR::isError($res)) + { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be deleted + return PEAR::raiseError(_kt('Folder cannot be deleted')); + } + } } } + return parent::check_entity($oEntity); } @@ -348,7 +398,11 @@ class KTBulkMoveAction extends KTBulkAction { function check_entity($oEntity) { if(is_a($oEntity, 'Document')) { - if(!KTDocumentUtil::canBeMoved($oEntity)) { + if(!KTDocumentUtil::canBeMoved($oEntity, $sError)) { + if (PEAR::isError($sError)) + { + return $sError; + } return PEAR::raiseError(_kt('Document cannot be moved')); } } @@ -373,6 +427,8 @@ class KTBulkMoveAction extends KTBulkAction { $res = $this->check_entity($oDocument); if (PEAR::isError($res)) { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be moved return PEAR::raiseError(_kt('Folder cannot be moved')); } } @@ -392,6 +448,8 @@ class KTBulkMoveAction extends KTBulkAction { $res = $this->check_entity($oChild); if (PEAR::isError($res)) { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be moved return PEAR::raiseError(_kt('Folder cannot be moved')); } } @@ -579,10 +637,64 @@ class KTBulkCopyAction extends KTBulkAction { function check_entity($oEntity) { if(is_a($oEntity, 'Document')) { - if(!KTDocumentUtil::canBeMoved($oEntity)) { + if(!KTDocumentUtil::canBeCopied($oEntity, $sError)) { + if (PEAR::isError($sError)) + { + return $sError; + } return PEAR::raiseError(_kt('Document cannot be copied')); } } + + if(is_a($oEntity, 'Folder')) { + $aDocuments = array(); + $aChildFolders = array(); + + $oFolder = $oEntity; + + // Get folder id + $sFolderId = $oFolder->getID(); + + // Get documents in folder + $sDocuments = $oFolder->getDocumentIDs($sFolderId); + $aDocuments = (!empty($sDocuments)) ? explode(',', $sDocuments) : array(); + + // Loop through documents and send to this function for checking + if(!empty($aDocuments)){ + foreach($aDocuments as $sDocID){ + $oDocument = Document::get($sDocID); + $res = $this->check_entity($oDocument); + if (PEAR::isError($res)) + { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be copied + return PEAR::raiseError(_kt('Folder cannot be copied')); + } + } + } + + // If all documents at the current level may be copied, we can continue + // Get any existing subfolders + $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR + parent_folder_ids LIKE '{$sFolderId},%' OR + parent_folder_ids LIKE '%,{$sFolderId},%' OR + parent_folder_ids LIKE '%,{$sFolderId}'"; + $aChildFolders = $this->oFolder->getList($sWhereClause); + + // Loop through subfolders and check each in the same way as the parent + if(!empty($aChildFolders)){ + foreach($aChildFolders as $oChild){ + $res = $this->check_entity($oChild); + if (PEAR::isError($res)) + { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be copied + return PEAR::raiseError(_kt('Folder cannot be copied')); + } + } + } + } + return parent::check_entity($oEntity); } @@ -709,17 +821,76 @@ class KTBulkArchiveAction extends KTBulkAction { } function check_entity($oEntity) { + // NOTE: these checks don't have an equivalent in the delete and move functions. + // possibly they are no longer needed but I am leaving them here + // to avoid any potential problems I may not be aware of if((!is_a($oEntity, 'Document')) && (!is_a($oEntity, 'Folder'))) { - return PEAR::raiseError(_kt('Document cannot be archived')); + return PEAR::raiseError(_kt('Document cannot be archived')); } + if($oEntity->isSymbolicLink()){ return PEAR::raiseError(_kt("It is not possible to archive a shortcut. Please archive the target document or folder instead.")); } - if(is_a($oEntity, 'Document')){ - if(!KTWorkflowUtil::actionEnabledForDocument($oEntity, 'ktcore.actions.document.archive')){ - return PEAR::raiseError(_kt('Document cannot be archived as it is restricted by the workflow.')); + + if(is_a($oEntity, 'Document')) { + if(!KTDocumentUtil::canBeArchived($oEntity, $sError)) { + if (PEAR::isError($sError)) + { + return $sError; + } + return PEAR::raiseError(_kt('Document cannot be archived')); + } + } + + if(is_a($oEntity, 'Folder')) { + $aDocuments = array(); + $aChildFolders = array(); + + $oFolder = $oEntity; + + // Get folder id + $sFolderId = $oFolder->getID(); + + // Get documents in folder + $sDocuments = $oFolder->getDocumentIDs($sFolderId); + $aDocuments = (!empty($sDocuments)) ? explode(',', $sDocuments) : array(); + + // Loop through documents and send to this function for checking + if(!empty($aDocuments)){ + foreach($aDocuments as $sDocID){ + $oDocument = Document::get($sDocID); + $res = $this->check_entity($oDocument); + if (PEAR::isError($res)) + { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be archived + return PEAR::raiseError(_kt('Folder cannot be archived')); + } + } + } + + // If all documents at the current level may be archived, we can continue + // Get any existing subfolders + $sWhereClause = "parent_folder_ids = '{$sFolderId}' OR + parent_folder_ids LIKE '{$sFolderId},%' OR + parent_folder_ids LIKE '%,{$sFolderId},%' OR + parent_folder_ids LIKE '%,{$sFolderId}'"; + $aChildFolders = $this->oFolder->getList($sWhereClause); + + // Loop through subfolders and check each in the same way as the parent + if(!empty($aChildFolders)){ + foreach($aChildFolders as $oChild){ + $res = $this->check_entity($oChild); + if (PEAR::isError($res)) + { + // NOTE: we may want to append the document reason to this + // in order for the user to have some idea WHY the folder cannot be archived + return PEAR::raiseError(_kt('Folder cannot be archived')); + } + } } } + return parent::check_entity($oEntity); } @@ -871,6 +1042,7 @@ class KTBulkArchiveAction extends KTBulkAction { } } +// NOTE: None of the new code for folder recursion is implemented for this action. class KTBrowseBulkExportAction extends KTBulkAction { var $sName = 'ktcore.actions.bulk.export'; var $_sPermission = 'ktcore.permissions.read'; @@ -881,8 +1053,6 @@ class KTBrowseBulkExportAction extends KTBulkAction { return _kt('Download All'); } - - function check_entity($oEntity) { if((!is_a($oEntity, 'Document')) && (!is_a($oEntity, 'Folder'))) { return PEAR::raiseError(_kt('Document cannot be exported')); @@ -1081,6 +1251,7 @@ class KTBrowseBulkExportAction extends KTBulkAction { } } +// NOTE: None of the new code for folder recursion is implemented for this action. class KTBrowseBulkCheckoutAction extends KTBulkAction { var $sName = 'ktcore.actions.bulk.checkout'; var $_sPermission = 'ktcore.permissions.write';