diff --git a/ktapi/KTAPIBulkActions.inc.php b/ktapi/KTAPIBulkActions.inc.php
new file mode 100644
index 0000000..e6b98bf
--- /dev/null
+++ b/ktapi/KTAPIBulkActions.inc.php
@@ -0,0 +1,575 @@
+.
+ *
+ * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
+ * California 94120-7775, or email info@knowledgetree.com.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "Powered by
+ * KnowledgeTree" logo and retain the original copyright notice. If the display of the
+ * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+ * must display the words "Powered by KnowledgeTree" and retain the original
+ * copyright notice.
+ *
+ * @copyright 2008-2009, KnowledgeTree Inc.
+ * @license GNU General Public License version 3
+ * @author KnowledgeTree Team
+ * @package KnowledgeTree API
+ * @version Version 0.9
+ */
+
+/**
+ * API for the handling bulk actions on documents and folders within KnowledgeTree
+ *
+ * @author KnowledgeTree Team
+ * @package KnowledgeTree API
+ * @version 0.9
+ */
+class KTAPI_BulkActions
+{
+ /**
+ * Instance of the KTAPI object
+ *
+ * @access private
+ */
+ private $ktapi;
+
+ /**
+ * Constructs the bulk actions object
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param KTAPI $ktapi Instance of the KTAPI object
+ */
+ function __construct(&$ktapi)
+ {
+ $this->ktapi = $ktapi;
+ }
+
+ /**
+ * Bulk copies a list of folders and/or documents into the target folder.
+ * If any documents or folders fail to copy, an array is returned containing the document/folder object and the failure message.
+ *
+ *
+ * $ktapi = new KTAPI();
+ * $session = $ktapi->start_system_session();
+ * $document = $ktapi->get_document_by_id($documentid);
+ *
+ * $root = $ktapi->get_root_folder();
+ * $newFolder = $root->add_folder("New target folder");
+ * if(PEAR::isError($newFolder)) return;
+ *
+ * $aItems = array($document);
+ * $bulk = new KTAPI_BulkActions($ktapi);
+ * $res = $bulk->copy($aItems, $newFolder, 'Bulk copy');
+ *
+ * // if documents / folders failed
+ * if(!empty($res)) {
+ * // display reason for documents failure
+ * foreach($res['docs'] as $failedDoc){
+ * echo '
' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
+ * }
+ * // display reason for folders failure
+ * foreach($res['folders'] as $failedDoc){
+ * echo '
' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
+ * }
+ * }
+ *
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param array $items The folders and/or documents
+ * @param KTAPI_Folder $target_folder The target folder object
+ * @param string $reason The reason for performing the copy
+ * @return array|PEAR_Error Returns an array of documents and folders that couldn't be copied | PEAR_Error on failure
+ */
+ function copy($items, &$target_folder, $reason)
+ {
+ if(empty($items)) return;
+ assert(!is_null($target_folder));
+ assert($target_folder instanceof KTAPI_FOLDER);
+
+ if(!is_array($items)){
+ $items = array($items);
+ }
+
+ // Check user has write permission on target folder
+ $result = $this->ktapi->can_user_access_object_requiring_permission($target_folder->get_folder(), KTAPI_PERMISSION_WRITE);
+
+ if (PEAR::isError($result))
+ {
+ return $result;
+ }
+
+ // Copy the document or folder
+ // Items that fail are returned in an array with the reason for failure.
+
+ $failed = array();
+ foreach ($items as $item){
+ assert($item instanceof KTAPI_Document || $item instanceof KTAPI_Folder);
+
+ $docOrFolder = ($item instanceof KTAPI_Document) ? 'docs' : 'folders';
+
+ $res = $item->copy($target_folder, $reason);
+
+ if(PEAR::isError($res)){
+ $failed[$docOrFolder][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * Bulk moves a list of folders and/or documents into the target folder
+ *
+ *
+ * $ktapi = new KTAPI();
+ * $session = $ktapi->start_system_session();
+ * $document = $ktapi->get_document_by_id($documentid);
+ *
+ * $root = $ktapi->get_root_folder();
+ * $newFolder = $root->add_folder("New target folder");
+ * if(PEAR::isError($newFolder)) return;
+ *
+ * $aItems = array($document);
+ * $bulk = new KTAPI_BulkActions($ktapi)
+ * $res = $bulk->move($aItems, $newFolder, 'Bulk move');
+ *
+ * // if documents / folders failed
+ * if(!empty($res)) {
+ * // display reason for documents failure
+ * foreach($res['docs'] as $failedDoc){
+ * echo '
' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
+ * }
+ * // display reason for folders failure
+ * foreach($res['folders'] as $failedDoc){
+ * echo '
' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
+ * }
+ * }
+ *
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param array $items The folders and/or documents
+ * @param KTAPI_Folder $target_folder The target folder object
+ * @param string $reason The reason for performing the move
+ * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
+ */
+ function move($items, &$target_folder, $reason)
+ {
+ if(empty($items)) return;
+ assert(!is_null($target_folder));
+ assert($target_folder instanceof KTAPI_FOLDER);
+
+ if(!is_array($items)){
+ $items = array($items);
+ }
+
+ // Check user has write permission on target folder
+ $result = $this->ktapi->can_user_access_object_requiring_permission($target_folder->get_folder(), KTAPI_PERMISSION_WRITE);
+
+ if (PEAR::isError($result))
+ {
+ return $result;
+ }
+
+ // Move the document or folder
+ // Items that fail are returned in an array with the reason for failure.
+
+ $failed = array();
+ foreach ($items as $item){
+ assert($item instanceof KTAPI_Document || $item instanceof KTAPI_Folder);
+
+ $docOrFolder = ($item instanceof KTAPI_Document) ? 'docs' : 'folders';
+
+ $res = $item->move($target_folder, $reason);
+
+ if(PEAR::isError($res)){
+ $failed[$docOrFolder][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * Performs a bulk checkout on a list of folders and/or documents
+ *
+ *
+ * $ktapi = new KTAPI();
+ * $session = $ktapi->start_system_session();
+ * $document = $ktapi->get_document_by_id($documentid);
+ * $folder = $ktapi->get_folder_by_name('New test folder');
+ *
+ * $aItems = array($document, $folder);
+ * $bulk = new KTAPI_BulkActions($ktapi)
+ * $res = $bulk->checkout($aItems, 'Bulk archive');
+ *
+ * // if documents / folders failed
+ * if(!empty($res)) {
+ * // display reason for documents failure
+ * foreach($res['docs'] as $failedDoc){
+ * echo '
' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
+ * }
+ * // display reason for folders failure
+ * foreach($res['folders'] as $failedDoc){
+ * echo '
' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
+ * }
+ * }
+ *
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param array $items The folders and/or documents
+ * @param string $reason The reason for performing the checkout
+ * @return void|PEAR_Error Nothing with download set to false | PEAR_Error on failure
+ */
+ function checkout($items, $reason)
+ {
+ if(empty($items)) return;
+
+ if(!is_array($items)){
+ $items = array($items);
+ }
+
+ // Checkout the document or folder
+ // Items that fail are returned in an array with the reason for failure.
+
+ $failed = array();
+ foreach ($items as $item){
+ // Documents
+ if($item instanceof KTAPI_Document){
+ $res = $item->checkout($reason);
+
+ if(PEAR::isError($res)){
+ $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ }else if($item instanceof KTAPI_Folder){
+ // Folders - need to recurse in
+ DBUtil::startTransaction();
+ $res = $this->recurseFolder($item, $reason, 'checkout');
+
+ if(PEAR::isError($res)){
+ DBUtil::rollback();
+ $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ DBUtil::commit();
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * Performs a bulk cancel checkout on a list of folders and/or documents
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param array $items The folders and/or documents
+ * @param string $reason The reason for cancelling the checkout
+ * @return void|PEAR_Error Nothing with download set to false | PEAR_Error on failure
+ */
+ function undo_checkout($items, $reason)
+ {
+ if(empty($items)) return;
+
+ if(!is_array($items)){
+ $items = array($items);
+ }
+
+ // Cancel checkout on the document or folder contents
+ // Items that fail are returned in an array with the reason for failure.
+
+ $failed = array();
+ foreach ($items as $item){
+ // Documents
+ if($item instanceof KTAPI_Document){
+ $res = $item->undo_checkout($reason);
+
+ if(PEAR::isError($res)){
+ $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ }else if($item instanceof KTAPI_Folder){
+ // Folders - need to recurse in
+ DBUtil::startTransaction();
+ $res = $this->recurseFolder($item, $reason, 'undo_checkout');
+
+ if(PEAR::isError($res)){
+ DBUtil::rollback();
+ $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ DBUtil::commit();
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * Bulk immutes a list of documents
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param array $items The folders and/or documents
+ * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
+ */
+ function immute($items)
+ {
+ if(empty($items)) return;
+
+ if(!is_array($items)){
+ $items = array($items);
+ }
+
+ // Immute the documents
+ // Items that fail are returned in an array with the reason for failure.
+
+ $failed = array();
+ foreach ($items as $item){
+ // Documents
+ if($item instanceof KTAPI_Document){
+ $res = $item->immute();
+
+ if(PEAR::isError($res)){
+ $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ }else if($item instanceof KTAPI_Folder){
+ // Folders - need to recurse in
+ DBUtil::startTransaction();
+ $res = $this->recurseFolder($item, null, 'immute');
+
+ if(PEAR::isError($res)){
+ DBUtil::rollback();
+ $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ DBUtil::commit();
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * Bulk deletes a list of folders and/or documents
+ *
+ *
+ * $ktapi = new KTAPI();
+ * $session = $ktapi->start_system_session();
+ * $document = $ktapi->get_document_by_id($documentid);
+ * $folder = $ktapi->get_folder_by_name('New test folder');
+ *
+ * $aItems = array($document, $folder);
+ * $bulk = new KTAPI_BulkActions($ktapi)
+ * $res = $bulk->delete($aItems, 'Bulk delete');
+ *
+ * // if documents / folders failed
+ * if(!empty($res)) {
+ * // display reason for documents failure
+ * foreach($res['docs'] as $failedDoc){
+ * echo '
' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
+ * }
+ * // display reason for folders failure
+ * foreach($res['folders'] as $failedDoc){
+ * echo '
' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
+ * }
+ * }
+ *
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param array $items The folders and/or documents
+ * @param string $reason The reason for performing the deletion
+ * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
+ */
+ function delete($items, $reason)
+ {
+ if(empty($items)) return;
+
+ if(!is_array($items)){
+ $items = array($items);
+ }
+
+ // Delete the document or folder
+ // Items that fail are returned in an array with the reason for failure.
+
+ $failed = array();
+ foreach ($items as $item){
+ assert($item instanceof KTAPI_Document || $item instanceof KTAPI_Folder);
+
+ $docOrFolder = ($item instanceof KTAPI_Document) ? 'docs' : 'folders';
+
+ $res = $item->delete($reason);
+
+ if(PEAR::isError($res)){
+ $failed[$docOrFolder][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * Bulk archives a list of folders and/or documents
+ *
+ *
+ * $ktapi = new KTAPI();
+ * $session = $ktapi->start_system_session();
+ * $document = $ktapi->get_document_by_id($documentid);
+ * $folder = $ktapi->get_folder_by_name('New test folder');
+ *
+ * $aItems = array($document, $folder);
+ * $bulk = new KTAPI_BulkActions($ktapi)
+ * $res = $bulk->archive($aItems, 'Bulk archive');
+ *
+ * // if documents / folders failed
+ * if(!empty($res)) {
+ * // display reason for documents failure
+ * foreach($res['docs'] as $failedDoc){
+ * echo '
' . $failedDoc['object']->get_title() . ' - reason: '.$failedDoc['reason'];
+ * }
+ * // display reason for folders failure
+ * foreach($res['folders'] as $failedDoc){
+ * echo '
' . $failedFolder['object']->get_folder_name() . ' - reason: '.$failedFolder['reason'];
+ * }
+ * }
+ *
+ *
+ * @author KnowledgeTree Team
+ * @access public
+ * @param array $items The folders and/or documents
+ * @param string $reason The reason for performing the archival
+ * @return void|PEAR_Error Nothing on success | PEAR_Error on failure
+ */
+ function archive($items, $reason)
+ {
+ if(empty($items)) return;
+
+ if(!is_array($items)){
+ $items = array($items);
+ }
+
+ // Archive the document or folder
+ // Items that fail are returned in an array with the reason for failure.
+
+ $failed = array();
+ foreach ($items as $item){
+ // Documents
+ if($item instanceof KTAPI_Document){
+ $res = $item->archive($reason);
+
+ if(PEAR::isError($res)){
+ $failed['docs'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ }else if($item instanceof KTAPI_Folder){
+ // Folders - need to recurse in
+ DBUtil::startTransaction();
+ $res = $this->recurseFolder($item, $reason, 'archive');
+
+ if(PEAR::isError($res)){
+ DBUtil::rollback();
+ $failed['folders'][] = array('object' => $item, 'reason' => $res->getMessage());
+ continue;
+ }
+ DBUtil::commit();
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * Recursive function to perform a given action on a folder and contained documents.
+ *
+ * @author KnowledgeTree Team
+ * @access private
+ * @param KTAPI_Folder $folder The instance of the folder object being archived
+ * @param string $reason The reason for archiving
+ * @param string $action The action to be performed on the documents
+ * @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
+ */
+ private function recurseFolder($folder, $reason = '', $action = 'archive')
+ {
+ if(!$folder instanceof KTAPI_Folder){
+ return PEAR::raiseError('Object is not an instance of KTAPI_Folder');
+ }
+
+ // Archive contained documents
+ $listDocs = $folder->get_listing(1, 'D');
+ if(!empty($listDocs)) {
+
+ foreach ($listDocs as $docInfo){
+ $doc = $this->ktapi->get_document_by_id($docInfo['id']);
+
+ switch ($action){
+ case 'archive':
+ $res = $doc->archive($reason);
+ break;
+
+ case 'checkout':
+ $res = $doc->checkout($reason);
+ break;
+
+ case 'undo_checkout':
+ $res = $doc->undo_checkout($reason);
+ break;
+
+ case 'immute':
+ $res = $doc->immute();
+ break;
+ }
+
+
+ if(PEAR::isError($res)){
+ return $res;
+ }
+ }
+ }
+
+ // Archive contained folders
+ $listFolders = $folder->get_listing(1, 'F');
+ if(!empty($listFolders)) {
+ foreach ($listFolders as $folderItem){
+ $res = $this->archiveFolder($folderItem, $reason);
+
+ if(PEAR::isError($res)){
+ return $res;
+ }
+ }
+ }
+ return;
+ }
+}
+?>
\ No newline at end of file
diff --git a/ktapi/KTAPIDocument.inc.php b/ktapi/KTAPIDocument.inc.php
index 9bff361..21a84a6 100644
--- a/ktapi/KTAPIDocument.inc.php
+++ b/ktapi/KTAPIDocument.inc.php
@@ -711,6 +711,7 @@ class KTAPI_Document extends KTAPI_FolderItem
DBUtil::commit();
+ /*
// FIXME do we need to refactor all trigger usage into the util function?
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('copyDocument', 'postValidate');
@@ -725,6 +726,7 @@ class KTAPI_Document extends KTAPI_FolderItem
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
}
+ */
return KTAPI_Document::get($this->ktapi, $new_document->getId());
}
@@ -1021,6 +1023,16 @@ class KTAPI_Document extends KTAPI_FolderItem
return $user;
}
+ DBUtil::startTransaction();
+ $res = KTDocumentUtil::archive($this->document, $reason);
+
+ if(PEAR::isError($res)){
+ DBUtil::rollback();
+ return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $res);
+ }
+ DBUtil::commit();
+
+ /*
list($permission, $user) = $perm_and_user;
DBUtil::startTransaction();
@@ -1048,6 +1060,7 @@ class KTAPI_Document extends KTAPI_FolderItem
$oTrigger->setInfo($aInfo);
$ret = $oTrigger->postValidate();
}
+ */
}
/**
@@ -2321,6 +2334,9 @@ class KTAPI_Document extends KTAPI_FolderItem
*/
public function immute()
{
+ if($this->is_checked_out()){
+ return new PEAR_Error('Document is checked out and can\'t be set to immutable.');
+ }
$this->document->setImmutable(true);
$this->document->update();
}
diff --git a/ktapi/ktapi.inc.php b/ktapi/ktapi.inc.php
index 3505cc2..22a4af8 100644
--- a/ktapi/ktapi.inc.php
+++ b/ktapi/ktapi.inc.php
@@ -58,6 +58,7 @@ require_once(KTAPI_DIR .'/KTAPIFolder.inc.php');
require_once(KTAPI_DIR .'/KTAPIDocument.inc.php');
require_once(KTAPI_DIR .'/KTAPIAcl.inc.php');
require_once(KTAPI_DIR .'/KTAPICollection.inc.php');
+require_once(KTAPI_DIR .'/KTAPIBulkActions.inc.php');
/**
* This class defines functions that MUST exist in the inheriting class
diff --git a/lib/documentmanagement/documentutil.inc.php b/lib/documentmanagement/documentutil.inc.php
index 00461fe..2556283 100644
--- a/lib/documentmanagement/documentutil.inc.php
+++ b/lib/documentmanagement/documentutil.inc.php
@@ -152,6 +152,15 @@ class KTDocumentUtil {
return PEAR::raiseError(_kt('Already checked out.'));
}
+ if($oDocument->getImmutable()){
+ return PEAR::raiseError(_kt('Document cannot be checked out as it is immutable'));
+ }
+
+ // Check if the action is restricted by workflow on the document
+ if(!KTWorkflowUtil::actionEnabledForDocument($oDocument, 'ktcore.actions.document.checkout')){
+ return PEAR::raiseError(_kt('Checkout is restricted by the workflow state.'));
+ }
+
// FIXME at the moment errors this _does not_ rollback.
$oDocument->setIsCheckedOut(true);
@@ -186,12 +195,8 @@ class KTDocumentUtil {
function archive($oDocument, $sReason) {
- $this->startTransaction();
- $oDocument->setStatusID(ARCHIVED);
- $res = $oDocument->update();
-
- if (PEAR::isError($res) || ($res === false)) {
- return PEAR::raiseError(_kt('There was a database error while trying to archive this file'));
+ if($oDocument->isSymbolicLink()){
+ return PEAR::raiseError(_kt("It is not possible to archive a shortcut. Please archive the target document."));
}
// Ensure the action is not blocked
@@ -199,6 +204,13 @@ class KTDocumentUtil {
return PEAR::raiseError(_kt('Document cannot be archived as it is restricted by the workflow.'));
}
+ $oDocument->setStatusID(ARCHIVED);
+ $res = $oDocument->update();
+
+ if (PEAR::isError($res) || ($res === false)) {
+ return PEAR::raiseError(_kt('There was a database error while trying to archive this file'));
+ }
+
//delete all shortcuts linking to this document
$aSymlinks = $oDocument->getSymbolicLinks();
foreach($aSymlinks as $aSymlink){
@@ -220,8 +232,6 @@ class KTDocumentUtil {
$oDocumentTransaction = & new DocumentTransaction($oDocument, sprintf(_kt('Document archived: %s'), $sReason), 'ktcore.transactions.update');
$oDocumentTransaction->create();
- $this->commitTransaction();
-
$oKTTriggerRegistry = KTTriggerRegistry::getSingleton();
$aTriggers = $oKTTriggerRegistry->getTriggers('archive', 'postValidate');
foreach ($aTriggers as $aTrigger) {
@@ -1213,11 +1223,11 @@ $sourceDocument->getName(),
}
function rename($oDocument, $sNewFilename, $oUser) {
- $oStorage =& KTStorageManagerUtil::getSingleton();
-
+ $oStorage =& KTStorageManagerUtil::getSingleton();
+
$oKTConfig = KTConfig::getSingleton();
- $updateVersion = $oKTConfig->get('tweaks/incrementVersionOnRename', true);
-
+ $updateVersion = $oKTConfig->get('tweaks/incrementVersionOnRename', true);
+
$iPreviousMetadataVersion = $oDocument->getMetadataVersionId();
$oOldContentVersion = $oDocument->_oDocumentContentVersion;
@@ -1231,22 +1241,22 @@ $sourceDocument->getName(),
KTDocumentUtil::copyMetadata($oDocument, $iPreviousMetadataVersion);
}
-
+
$res = $oStorage->renameDocument($oDocument, $oOldContentVersion, $sNewFilename);
if (!$res) {
return PEAR::raiseError(_kt('An error occurred while storing the new file'));
}
-
-
+
+
$oDocument->setLastModifiedDate(getCurrentDateTime());
$oDocument->setModifiedUserId($oUser->getId());
-
+
if($updateVersion) { // Update version number
$oDocument->setMinorVersionNumber($oDocument->getMinorVersionNumber()+1);
}
-
+
$oDocument->_oDocumentContentVersion->setFilename($sNewFilename);
$sType = KTMime::getMimeTypeFromFile($sNewFilename);
diff --git a/tests/api/testBulkActions.php b/tests/api/testBulkActions.php
new file mode 100644
index 0000000..3eb7297
--- /dev/null
+++ b/tests/api/testBulkActions.php
@@ -0,0 +1,368 @@
+ktapi = new KTAPI();
+ $this->session = $this->ktapi->start_system_session();
+ $this->root = $this->ktapi->get_root_folder();
+ $this->bulk = new KTAPI_BulkActions($this->ktapi);
+ }
+
+ /**
+ * End the ktapi session
+ */
+ function tearDown() {
+ $this->session->logout();
+ }
+
+ /**
+ * Test the bulk copy functionality
+ */
+ function testCopy()
+ {
+ // Create documents
+ $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
+ $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
+ $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
+ $folder1 = $this->root->add_folder("New copy folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
+
+ // Add a folder
+ $targetFolder = $this->root->add_folder("New target folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $aItems = array($doc1, $doc2, $doc3, $folder1);
+
+ // Copy documents and folder into target folder
+ $res = $this->bulk->copy($aItems, $targetFolder, 'Testing bulk copy');
+
+ $this->assertTrue(empty($res));
+
+ // Check the documents copied
+ $listDocs = $targetFolder->get_listing(1, 'D');
+ $this->assertTrue(count($listDocs) == 3);
+
+ // Check the folder copied
+ $listFolders = $targetFolder->get_listing(1, 'F');
+ $this->assertTrue(count($listFolders) == 1);
+
+ // Check the document contained in the folder copied
+ $newFolderId = $listFolders[0]['id'];
+ $newFolder = $this->ktapi->get_folder_by_id($newFolderId);
+ $listSubDocs = $newFolder->get_listing(1, 'D');
+ $this->assertTrue(count($listSubDocs) == 1);
+
+ // Delete and expunge documents and folder
+ $this->deleteDocument($doc1);
+ $this->deleteDocument($doc2);
+ $this->deleteDocument($doc3);
+ $this->deleteDocument($doc4);
+ $targetFolder->delete('Testing bulk copy');
+ $folder1->delete('Testing bulk copy');
+ }
+
+ /**
+ * Test the bulk move functionality
+ */
+ function testMove()
+ {
+ // Create documents
+ $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
+ $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
+ $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
+ $folder1 = $this->root->add_folder("New move folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
+
+ // Add a folder
+ $targetFolder = $this->root->add_folder("New target folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $aItems = array($doc1, $doc2, $doc3, $folder1);
+
+ // Copy documents and folder into target folder
+ $res = $this->bulk->move($aItems, $targetFolder, 'Testing bulk move');
+
+ $this->assertTrue(empty($res));
+
+ // Check document has been moved not copied
+ $detail = $doc1->get_detail();
+ $this->assertFalse($detail['folder_id'] == $this->root->get_folderid());
+ $this->assertTrue($detail['folder_id'] == $targetFolder->get_folderid());
+
+ // Check folder has been moved not copied
+ $this->assertFalse($folder1->get_parent_folder_id() == $this->root->get_folderid());
+ $this->assertTrue($folder1->get_parent_folder_id() == $targetFolder->get_folderid());
+
+ // Check the documents copied
+ $listDocs = $targetFolder->get_listing(1, 'D');
+ $this->assertTrue(count($listDocs) == 3);
+
+ // Check the folder copied
+ $listFolders = $targetFolder->get_listing(1, 'F');
+ $this->assertTrue(count($listFolders) == 1);
+
+ // Check the document contained in the folder copied
+ $newFolderId = $listFolders[0]['id'];
+ $newFolder = $this->ktapi->get_folder_by_id($newFolderId);
+ $listSubDocs = $newFolder->get_listing(1, 'D');
+ $this->assertTrue(count($listSubDocs) == 1);
+
+ // Delete and expunge documents and folder
+ $this->deleteDocument($doc1);
+ $this->deleteDocument($doc2);
+ $this->deleteDocument($doc3);
+ $this->deleteDocument($doc4);
+ $targetFolder->delete('Testing bulk copy');
+ $folder1->delete('Testing bulk copy');
+ }
+
+ /**
+ * Test the bulk checkout and cancel checkout functionality
+ */
+ function testCheckout()
+ {
+ // Create documents
+ $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
+ $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
+ $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
+ $folder1 = $this->root->add_folder("New test folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
+
+ $aItems = array($doc1, $doc2, $doc3, $folder1);
+
+ // Checkout documents and folder
+ $res = $this->bulk->checkout($aItems, 'Testing bulk checkout');
+
+ $this->assertTrue(empty($res));
+
+ $this->assertTrue($doc1->is_checked_out());
+ $this->assertTrue($doc2->is_checked_out());
+ $this->assertTrue($doc3->is_checked_out());
+ $this->assertTrue($doc4->is_checked_out());
+
+ $res = $this->bulk->undo_checkout($aItems, 'Testing bulk undo / cancel checkout');
+
+ $this->assertTrue(empty($res));
+
+ $this->assertFalse($doc1->is_checked_out());
+ $this->assertFalse($doc2->is_checked_out());
+ $this->assertFalse($doc3->is_checked_out());
+ $this->assertFalse($doc4->is_checked_out());
+
+ // Delete and expunge documents and folder
+ $this->deleteDocument($doc1);
+ $this->deleteDocument($doc2);
+ $this->deleteDocument($doc3);
+ $this->deleteDocument($doc4);
+ $folder1->delete('Testing bulk checkout');
+ }
+
+ /**
+ * Test the bulk immute functionality
+ */
+ function testImmute()
+ {
+ // Create documents
+ $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
+ $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
+ $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
+ $folder1 = $this->root->add_folder("New test folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
+
+ $aItems = array($doc1, $doc2, $doc3, $folder1);
+
+ // Immute documents
+ $res = $this->bulk->immute($aItems);
+
+ $this->assertTrue(empty($res));
+
+ $this->assertTrue($doc1->isImmutable());
+ $this->assertTrue($doc2->isImmutable());
+ $this->assertTrue($doc3->isImmutable());
+ $this->assertTrue($doc4->isImmutable());
+
+ // remove immutability for deletion
+ $doc1->unimmute();
+ $doc2->unimmute();
+ $doc3->unimmute();
+ $doc4->unimmute();
+
+ // Delete and expunge documents and folder
+ $this->deleteDocument($doc1);
+ $this->deleteDocument($doc2);
+ $this->deleteDocument($doc3);
+ $this->deleteDocument($doc4);
+ $folder1->delete('Testing bulk checkout');
+ }
+
+ /**
+ * Test the bulk delete functionality
+ */
+ function testDelete()
+ {
+ // Create documents
+ $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
+ $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
+ $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
+ $folder1 = $this->root->add_folder("New test folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
+
+ $aItems = array($doc1, $doc2, $doc3, $folder1);
+
+ // Delete documents and folder
+ $res = $this->bulk->delete($aItems, 'Testing bulk delete');
+
+ $this->assertTrue(empty($res));
+
+ // Check documents have been deleted
+ $this->assertTrue($doc1->is_deleted());
+ $this->assertTrue($doc2->is_deleted());
+ $this->assertTrue($doc3->is_deleted());
+ $this->assertTrue($doc4->is_deleted());
+
+ // Check folder has been deleted
+ $folder = $this->ktapi->get_folder_by_name('New test folder');
+ $this->assertError($folder);
+
+ // Expunge documents
+ $doc1->expunge();
+ $doc2->expunge();
+ $doc3->expunge();
+ $doc4->expunge();
+ }
+
+ /**
+ * Test the bulk archive functionality
+ */
+ function testArchive()
+ {
+ // Create documents
+ $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt');
+ $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.txt');
+ $doc3 = $this->createDocument('Test Doc Three', 'testdoc3.txt');
+ $folder1 = $this->root->add_folder("New test folder");
+ $this->assertNotError($newFolder);
+ if(PEAR::isError($newFolder)) return;
+
+ $doc4 = $this->createDocument('Test Doc Four', 'testdoc4.txt', $folder1);
+
+ $aItems = array($doc1, $doc2, $doc3, $folder1);
+
+ // Archive documents and folder
+ $res = $this->bulk->archive($aItems, 'Testing bulk archive');
+
+ $this->assertTrue(empty($res));
+
+ $document1 = $doc1->getObject();
+ $this->assertTrue($document1->getStatusID() == 4);
+ $document4 = $doc4->getObject();
+ $this->assertTrue($document4->getStatusID() == 4);
+
+ // Restore for deletion
+ $doc1->restore();
+ $doc2->restore();
+ $doc3->restore();
+ $doc4->restore();
+
+ // Delete and expunge documents and folder
+ $this->deleteDocument($doc1);
+ $this->deleteDocument($doc2);
+ $this->deleteDocument($doc3);
+ $this->deleteDocument($doc4);
+ $folder1->delete('Testing bulk archive');
+ }
+
+ /**
+ * Helper function to delete docs
+ */
+ function deleteDocument($document)
+ {
+ $document->delete('Testing bulk actions');
+ $document->expunge();
+ }
+
+ /**
+ * Helper function to create a document
+ */
+ function createDocument($title, $filename, $folder = null)
+ {
+ if(is_null($folder)){
+ $folder = $this->root;
+ }
+
+ // Create a new document
+ $randomFile = $this->createRandomFile();
+ $this->assertTrue(is_file($randomFile));
+
+ $document = $folder->add_document($title, $filename, 'Default', $randomFile);
+ $this->assertNotError($document);
+
+ @unlink($randomFile);
+ if(PEAR::isError($document)) return false;
+
+ return $document;
+ }
+
+ /**
+ * Helper function to create a file
+ *
+ * @param unknown_type $content
+ * @return unknown
+ */
+ function createRandomFile($content = 'this is some text') {
+ $temp = tempnam(dirname(__FILE__), 'myfile');
+ file_put_contents($temp, $content);
+ return $temp;
+ }
+}
+?>
\ No newline at end of file
diff --git a/tests/runtests.php b/tests/runtests.php
index 8946675..aae0685 100644
--- a/tests/runtests.php
+++ b/tests/runtests.php
@@ -6,18 +6,24 @@ class UnitTests extends TestSuite {
function UnitTests() {
$this->TestSuite('Unit tests');
+
+ // KTAPI
$this->addFile('api/testAuthentication.php');
$this->addFile('api/testDocument.php');
$this->addFile('api/testFolder.php');
- $this->addFile('SQLFile/test_sqlfile.php');
- $this->addFile('cache/testCache.php');
- $this->addFile('config/testConfig.php');
- $this->addFile('document/testDocument.php');
- $this->addFile('document/testDocumentUtil.php');
+ $this->addFile('api/testBulkActions.php');
+ $this->addFile('api/testCollection.php');
+
+// $this->addFile('SQLFile/test_sqlfile.php');
+// $this->addFile('cache/testCache.php');
+// $this->addFile('config/testConfig.php');
+// $this->addFile('document/testDocument.php');
+// $this->addFile('document/testDocumentUtil.php');
// $this->addFile('folder/testFolder.php');
// $this->addFile('browseutil/testBrowseUtil.php');
// $this->addFile('filelike/testStringFileLike.php');
+ // Search (2) and indexing
$this->addFile('documentProcessor/testExtracters.php');
// $this->addFile('documentProcessor/testIndexer.php');
$this->addFile('documentProcessor/testGuidInserter.php');