diff --git a/ktapi/KTAPIAcl.inc.php b/ktapi/KTAPIAcl.inc.php index cc776bd..fe80661 100644 --- a/ktapi/KTAPIAcl.inc.php +++ b/ktapi/KTAPIAcl.inc.php @@ -1719,7 +1719,7 @@ final class KTAPI_RoleAllocation extends KTAPI_AllocationBase $roleAllocation = RoleAllocation::getAllocationsForFolderAndRole($objectId, $roleId); - $res = $oRoleAllocation->delete(); + $res = $roleAllocation->delete(); if (PEAR::isError($res)) { return $res; diff --git a/ktapi/KTAPIBulkActions.inc.php b/ktapi/KTAPIBulkActions.inc.php index 65c2bee..349f469 100644 --- a/ktapi/KTAPIBulkActions.inc.php +++ b/ktapi/KTAPIBulkActions.inc.php @@ -63,7 +63,7 @@ class KTAPI_BulkActions * @access public * @param KTAPI $ktapi Instance of the KTAPI object */ - function __construct(&$ktapi) + public function __construct(&$ktapi) { $this->ktapi = $ktapi; } diff --git a/ktapi/KTAPIDocument.inc.php b/ktapi/KTAPIDocument.inc.php index ca42950..7b7d7da 100644 --- a/ktapi/KTAPIDocument.inc.php +++ b/ktapi/KTAPIDocument.inc.php @@ -2438,7 +2438,7 @@ class KTAPI_Document extends KTAPI_FolderItem $config = KTConfig::getSingleton(); $allowAttachment = $config->get('email/allowAttachment', false); - $allowEmailAddresses = $oConfig->get('email/allowEmailAddresses', false); + $allowEmailAddresses = $config->get('email/allowEmailAddresses', false); $emailErrors = array(); $userEmails = array(); diff --git a/ktapi/KTAPIFolder.inc.php b/ktapi/KTAPIFolder.inc.php index 1daf537..4cb3415 100644 --- a/ktapi/KTAPIFolder.inc.php +++ b/ktapi/KTAPIFolder.inc.php @@ -1031,6 +1031,15 @@ class KTAPI_Folder extends KTAPI_FolderItem DBUtil::rollback(); return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $result); } + + // regenerate internal folder object + $res = $this->updateObject(); + + if (PEAR::isError($res)) + { + DBUtil::rollback(); + return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $result); + } DBUtil::commit(); } @@ -1132,6 +1141,20 @@ class KTAPI_Folder extends KTAPI_FolderItem return $this->folder; } + /** + * Updates the Folder object + */ + private function updateObject() + { + $folder = &Folder::get($this->folderid); + if (is_null($folder) || PEAR::isError($folder)) + { + return new KTAPI_Error(KTAPI_ERROR_FOLDER_INVALID, $folder); + } + + $this->folder = $folder; + } + /** * Get the role allocation for the folder * diff --git a/ktapi/ktapi.inc.php b/ktapi/ktapi.inc.php index 34d6050..9346042 100644 --- a/ktapi/ktapi.inc.php +++ b/ktapi/ktapi.inc.php @@ -288,6 +288,39 @@ class KTAPI ); } + + /** + * Returns folder permissions + * + * @access public + * @param string + * @param int + * + */ + public function get_document_permissions($username, $document_id) { + if (is_null($this->session)) + { + return array( + "status_code" => 1, + "message" => "Your session is not active" + ); + } + /* We need to create a new instance of KTAPI to get another user */ + $user_ktapi = new KTAPI(); + $user_ktapi->start_system_session($username); + + $document = KTAPI_Document::get($user_ktapi, $document_id); + + $permissions = $document->getPermissionAllocation(); + + $user_ktapi->session_logout(); + + return array( + "status_code" => 0, + "results" => $permissions->permissions + ); + + } /** * Add folder permission @@ -1137,8 +1170,646 @@ class KTAPI return $subscriptions; } + /** + * Perform a bulk action on a list of folders and documents + * Available actions are copy, move, delete, archive, checkout, undo_checkout and immute. + * + * + * $ktapi = new KTAPI(); + * $session = $ktapi->start_system_session(); + * + * $items = array(); + * $items['documents'][] = $document_id; + * $items['folders'][] = $folder_id; + * + * $response = $ktapi->performBulkAction('move', $items, 'Reason for moving', $target_folder_id); + * if($response['status_code'] != 0) return 'ERROR'; + * + * + * + * @author KnowledgeTree Team + * @access public + * @param string $action The action to be performed + * @param array $items A list of id's and item type in the format array('documents' => array(1,6), 'folders' => array(3,4)) + * @param string $reason The reason for performing the action - only immute does not require a reason. + * @param integer $target_folder_id The id of the target folder if required - copy and move require this. + * @return array The response array. On success response['results'] will be empty | contain an array of failed items. + */ + public function performBulkAction($action, $items, $reason = '', $target_folder_id = null) + { + $response['status_code'] = 1; + + if(!is_array($items)){ + $response['message'] = _kt("The list of id's must be an array of format array('documents' => array(1,2), 'folders' => array(2,3)). Received: {$items}"); + return $response; + } + + if(empty($items)){ + $response['message'] = _kt('No items found to perform the action on.'); + return $response; + } + + if(!is_string($action)){ + $response['message'] = _kt("The bulk action to perform must be a string. Received: {$action}"); + return $response; + } + + // Check that the action exists in the bulk actions class + $bulkActions = new ReflectionClass('KTAPI_BulkActions'); + $methods = $bulkActions->getMethods(); + + $exists = false; + foreach ($methods as $method){ + if($method->getName() == $action){ + $actionMethod = $method; + $exists = true; + break; + } + } + + if(!$exists) { + $response['message'] = _kt("The requested action has not been implemented: {$action}"); + return $response; + } + + // Create the document and folder objects + $objects = array(); + if(isset($items['folders'])){ + foreach($items['folders'] as $item) { + $folder = $this->get_folder_by_id($item); + $objects[] = $folder; + } + } + + if(isset($items['documents'])){ + foreach($items['documents'] as $item) { + $document = $this->get_document_by_id($item); + $objects[] = $document; + } + } + + if(empty($objects)){ + $response['message'] = _kt('No folder or document items found to perform the action on.'); + return $response; + } + + // perform the action + $ktapi_bulkactions = new KTAPI_BulkActions($this); + + // Get target folder object if required + if(in_array($action, array('move', 'copy'))){ + if(!is_int($target_folder_id) || empty($target_folder_id)){ + $response['message'] = _kt('No target folder has been specified.'); + return $response; + } + $target = $this->get_folder_by_id($target_folder_id); + + // call the action + $result = $ktapi_bulkactions->$action($objects, $target, $reason); + }else if($action == 'immute'){ + // call the action + $result = $ktapi_bulkactions->$action($objects); + }else { + // call the action + $result = $ktapi_bulkactions->$action($objects, $reason); + } + + if(PEAR::isError($result)) { + $response['message'] = _kt("The bulk action failed: {$result->getMessage()}"); + return $response; + } + + // if failed items are returned - flatten the objects + if(is_array($result)){ + if(isset($result['docs'])){ + foreach ($result['docs'] as $key => $item){ + $result['docs'][$key]['object'] = $item['object']->get_detail(); + } + } + if(isset($result['folders'])){ + foreach ($result['folders'] as $key => $item){ + $result['folders'][$key]['object'] = $item['object']->get_detail(); + } + } + } + + // For a successful action + $response['status_code'] = 0; + $response['results'] = $result; + return $response; + } + + /* *** ACL Roles and Role_Allocation *** */ + + /** + * Get a list of available roles + * + * @author KnowledgeTree Team + * @access public + * @param string $filter The beginning letter(s) of the role being searched for + * @return array Response. + */ + public function get_roles($filter = null) + { + $response['status_code'] = 1; + + // check the filter + if(!empty($filter)) { + if(!is_string($filter)){ + $response['message'] = _kt('Filter should be a string.'); + return $response; + } + + // escape filter string - prevent sql injection + $filter = addslashes($filter); + $filter = "name like '{$filter}%'"; + } + + $listing = KTAPI_Role::getList($filter); + + if(PEAR::isError($listing)){ + $response['message'] = $listing->getMessage(); + return $response; + } + + // flatten role objects + $roles = array(); + foreach ($listing as $ktapi_roll) { + $roles[] = array( + 'id' => $ktapi_roll->getId(), + 'name' => $ktapi_roll->getName(), + ); + } + + $response['status_code'] = 0; + $response['results'] = $roles; + return $response; + } + + /** + * Get a role using its id + * + * @author KnowledgeTree Team + * @access public + * @param integer $role_id The id of the role + * @return array Response + */ + public function get_role_by_id($role_id) + { + $response['status_code'] = 1; + if(!is_numeric($role_id)){ + $response['message'] = _kt('Role id must be numeric.'); + return $response; + + } + + $role = KTAPI_Role::getById($role_id); + + if(PEAR::isError($role)) { + $response['message'] = $role->getMessage(); + return $response; + } + + $response['status_code'] = 0; + $response['results'] = array( + 'id' => $role->getId(), + 'name' => $role->getName() + ); + + return $response; + } + + /** + * Get a role based on its name + * + * @author KnowledgeTree Team + * @access public + * @param string $role_name The name of the role + * @return array Response + */ + public function get_role_by_name($role_name) + { + $response['status_code'] = 1; + if(!is_string($role_name)){ + $response['message'] = _kt('Role name must be a string.'); + return $response; + + } + + $role = KTAPI_Role::getByName($role_name); + + if(PEAR::isError($role)) { + $response['message'] = $role->getMessage(); + return $response; + } + + $response['status_code'] = 0; + $response['results'] = array( + 'id' => $role->getId(), + 'name' => $role->getName() + ); + + return $response; + } + + /** + * Get the list of role allocations on a folder + * + * @author KnowledgeTree Team + * @access public + * @param integar $folder_id The id of the folder + * @return array Response + */ + public function get_role_allocation_for_folder($folder_id) + { + $response['status_code'] = 1; + if(!is_numeric($folder_id)){ + $response['message'] = _kt('Folder id must be numeric.'); + return $response; + + } + + $folder = $this->get_folder_by_id($folder_id); + + if(PEAR::isError($folder)) { + $response['message'] = $folder->getMessage(); + return $response; + } + + $role_allocation = $folder->getRoleAllocation(); + + // flatten object + $membership = $role_allocation->getMembership(); + + $response['status_code'] = 0; + $response['results'] = $membership; + return $response; + } + + /** + * Add a user to a role on a folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being modified + * @param integer $user_id The id of the user to be added + * @return array Response + */ + public function add_user_to_role_on_folder($folder_id, $role_id, $user_id) + { + $response['status_code'] = 1; + if(!is_numeric($user_id)){ + $response['message'] = _kt('User id must be numeric.'); + return $response; + } + $member['users'][] = $user_id; + + return $this->add_members_to_role_on_folder($folder_id, $role_id, $member); + } + + /** + * Add a group to a role on a folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being modified + * @param integer $group_id The id of the group to be added + * @return array Response + */ + public function add_group_to_role_on_folder($folder_id, $role_id, $group_id) + { + $response['status_code'] = 1; + if(!is_numeric($group_id)){ + $response['message'] = _kt('Group id must be numeric.'); + return $response; + } + $member['groups'][] = $group_id; + + return $this->add_members_to_role_on_folder($folder_id, $role_id, $member); + } + + /** + * Remove a user from a role on a folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being modified + * @param integer $user_id The id of the user to be removed + * @return array Response + */ + public function remove_user_from_role_on_folder($folder_id, $role_id, $user_id) + { + $response['status_code'] = 1; + if(!is_numeric($user_id)){ + $response['message'] = _kt('User id must be numeric.'); + return $response; + } + $member['users'][] = $user_id; + + return $this->remove_members_from_role_on_folder($folder_id, $role_id, $member); + } + + /** + * Remove a group from a role on a folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being modified + * @param integer $group_id The id of the group to be removied + * @return array Response + */ + public function remove_group_from_role_on_folder($folder_id, $role_id, $group_id) + { + $response['status_code'] = 1; + if(!is_numeric($group_id)){ + $response['message'] = _kt('Group id must be numeric.'); + return $response; + } + $member['groups'][] = $group_id; + + return $this->remove_members_from_role_on_folder($folder_id, $role_id, $member); + } + + /** + * Remove members (user, group) from a role on a folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being modified + * @param array $members The list of id's of members to be removed - array('users' => array(1,2), 'groups' => array(2,4)) + * @return array Response + */ + public function remove_members_from_role_on_folder($folder_id, $role_id, $members) + { + return $this->update_members_on_role_on_folder($folder_id, $role_id, $members, 'remove'); + } + + /** + * Add members (user, group) to a role on a folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being modified + * @param array $members The list of id's of members to be added - array('users' => array(1,2), 'groups' => array(2,4)) + * @return array Response + */ + public function add_members_to_role_on_folder($folder_id, $role_id, $members) + { + return $this->update_members_on_role_on_folder($folder_id, $role_id, $members, 'add'); + } + + /** + * Add / remove members (user, group) to / from a role on a folder + * + * @author KnowledgeTree Team + * @access private + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being modified + * @param array $members The list of id's of members to be updated - array('users' => array(1,2), 'groups' => array(2,4)) + * @param string $update The type of modification - add | remove + * @return array Response + */ + private function update_members_on_role_on_folder($folder_id, $role_id, $members, $update = 'add') + { + // Check input information + $response['status_code'] = 1; + if(!is_numeric($folder_id)){ + $response['message'] = _kt('Folder id must be numeric.'); + return $response; + } + + if(!is_numeric($role_id)){ + $response['message'] = _kt('Role id must be numeric.'); + return $response; + } + + if(!is_array($members)){ + $response['message'] = _kt("The list of members must be in the format: array('users' => array(1,2), 'groups' => array(2,4)).')"); + return $response; + } + + if(!isset($members['users']) && !isset($members['groups'])){ + $response['message'] = _kt("The list of members must be in the format: array('users' => array(1,2), 'groups' => array(2,4)).')"); + return $response; + } + + // Get folder and role objects + $folder = $this->get_folder_by_id($folder_id); + if(PEAR::isError($folder)) { + $response['message'] = $folder->getMessage(); + return $response; + } + + $role = KTAPI_Role::getById($role_id); + if(PEAR::isError($role)) { + $response['message'] = $role->getMessage(); + return $response; + } + + // Get the role allocation for the folder + $role_allocation = $folder->getRoleAllocation(); + + // Get member objects and add them to the role + // Users + if(isset($members['users'])){ + + foreach($members['users'] as $user_id){ + // Get the user object + $member = KTAPI_User::getById($user_id); + + if(PEAR::isError($member)) { + $response['message'] = $member->getMessage(); + return $response; + } + + // Add to / remove from the role + $role_allocation->$update($role, $member); + } + } + + // Groups + if(isset($members['groups'])){ + + foreach($members['groups'] as $group_id){ + // Get the group object + $member = KTAPI_Group::getById($group_id); + + if(PEAR::isError($member)) { + $response['message'] = $member->getMessage(); + return $response; + } + + // Add to / remove from the role + $role_allocation->$update($role, $member); + } + } + + // Save the new allocations + $role_allocation->save(); + + $response['status_code'] = 0; + return $response; + } + + /** + * Check if a user or group is allocated to a role on the folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id The id of the role being checked + * @param integer $member_id The id of the user or group + * @param string $member_type user | group + * @return array Response + */ + public function is_member_in_role_on_folder($folder_id, $role_id, $member_id, $member_type = 'user') + { + $response['status_code'] = 1; + + // Get folder and role objects + $folder = $this->get_folder_by_id($folder_id); + if(PEAR::isError($folder)) { + $response['message'] = $folder->getMessage(); + return $response; + } + + $role = KTAPI_Role::getById($role_id); + if(PEAR::isError($role)) { + $response['message'] = $role->getMessage(); + return $response; + } + + // get the member object + switch($member_type){ + case 'user': + $member = KTAPI_User::getById($member_id); + break; + case 'group': + $member = KTAPI_Group::getById($member_id); + break; + default: + $response['message'] = _kt('Unrecognised member type. Must be group or user.'); + return $response; + } + + if(PEAR::isError($member)) { + $response['message'] = $member->getMessage(); + return $response; + } + + // Get the role allocation for the folder + $role_allocation = $folder->getRoleAllocation(); + $check = $role_allocation->doesRoleHaveMember($role, $member); + $result = ($check) ? 'YES' : 'NO'; + + $response['status_code'] = 0; + $response['results'] = $result; + return $response; + } + + /** + * Removes all members (users, groups) from all roles or from the specified role on the folder + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @param integer $role_id Optional. The id of the role being reset. + * @return array Response + */ + public function remove_all_role_allocation_from_folder($folder_id, $role_id = null) + { + $response['status_code'] = 1; + + // Get folder and role objects + $folder = $this->get_folder_by_id($folder_id); + if(PEAR::isError($folder)) { + $response['message'] = $folder->getMessage(); + return $response; + } + + $role = null; + if(!empty($role_id)){ + $role = KTAPI_Role::getById($role_id); + if(PEAR::isError($role)) { + $response['message'] = $role->getMessage(); + return $response; + } + } + + // Get the role allocation for the folder + $role_allocation = $folder->getRoleAllocation(); + $role_allocation->removeAll($role); + $role_allocation->save(); + + $response['status_code'] = 0; + $response['results'] = $result; + return $response; + } + + /** + * Overrides the parents role allocation + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @return array Response + */ + public function override_role_allocation_on_folder($folder_id) + { + $response['status_code'] = 1; + + // Get folder object + $folder = $this->get_folder_by_id($folder_id); + if(PEAR::isError($folder)) { + $response['message'] = $folder->getMessage(); + return $response; + } + + // Get the role allocation for the folder + $role_allocation = $folder->getRoleAllocation(); + $result = $role_allocation->overrideAllocation(); + + $response['status_code'] = 0; + $response['results'] = $result; + return $response; + } + + /** + * Inherits the role allocation from the parent + * + * @author KnowledgeTree Team + * @access public + * @param integer $folder_id The folder id + * @return array Response + */ + public function inherit_role_allocation_on_folder($folder_id) + { + $response['status_code'] = 1; + + // Get folder object + $folder = $this->get_folder_by_id($folder_id); + if(PEAR::isError($folder)) { + $response['message'] = $folder->getMessage(); + return $response; + } + + // Get the role allocation for the folder + $role_allocation = $folder->getRoleAllocation(); + $result = $role_allocation->inheritAllocation(); + + $response['status_code'] = 0; + $response['results'] = $result; + return $response; + } + - /* *** Refactored web services functions *** */ + /* *** Refactored web services functions *** */ /** diff --git a/ktwebservice/KTWebService.php b/ktwebservice/KTWebService.php index 7d1df33..d65a19a 100644 --- a/ktwebservice/KTWebService.php +++ b/ktwebservice/KTWebService.php @@ -118,6 +118,7 @@ class JsonEncoder extends EncoderBase */ public function encode($input) { + $input = array('response' => $input); return json_encode($input); } } @@ -150,11 +151,12 @@ class XmlEncoder extends EncoderBase return false; } - $xml = ''."\n"; - $xml .= ''."\n"; + $xml = ''."\n"; + $xml .= ''."\n"; +// $xml .= ''."\n"; $xml .= XmlEncoder::createXmlFromArray($input); - + $xml .= ''."\n"; return $xml; } @@ -171,6 +173,10 @@ class XmlEncoder extends EncoderBase $xml = ''; foreach ($input as $key => $value) { + if(is_numeric($key)){ + $key = 'item'; + } + if(is_array($value)){ $value = XmlEncoder::createXmlFromArray($value); } @@ -383,6 +389,13 @@ class Response extends ResponseBase // instantiate KTAPI and invoke method $ktapi = $this->get_ktapi($session_id); + + if(PEAR::isError($ktapi)){ + $this->error = 'API could not be authenticated: '.$ktapi->getMessage(); + $this->error_code = 404; + return false; + } + $result = $reflectMethod->invokeArgs($ktapi, $orderedParams); return $result; @@ -409,10 +422,10 @@ class Response extends ResponseBase if(!empty($session_id)){ $session = $kt->get_active_session($session_id, null); - if ( PEAR::isError($session)) + if (PEAR::isError($session)) { // return error / exception - return false; + return $session; } } $this->ktapi = $kt; @@ -477,6 +490,18 @@ class Response extends ResponseBase */ protected function _post($args) { + $result = $this->callMethod($args); + + // if an error occurred, initiate the error response + if($result === false){ + return false; + } + + $result = $this->flattenInput($result); + + $encoder = EncoderBase::getEncoder($this->responseType); + $this->output = $encoder->encode($result); + $this->headers = $encoder->getHeaders(); } /** @@ -489,6 +514,18 @@ class Response extends ResponseBase */ protected function _put($args) { + $result = $this->callMethod($args); + + // if an error occurred, initiate the error response + if($result === false){ + return false; + } + + $result = $this->flattenInput($result); + + $encoder = EncoderBase::getEncoder($this->responseType); + $this->output = $encoder->encode($result); + $this->headers = $encoder->getHeaders(); } /** @@ -501,6 +538,18 @@ class Response extends ResponseBase */ protected function _delete($args) { + $result = $this->callMethod($args); + + // if an error occurred, initiate the error response + if($result === false){ + return false; + } + + $result = $this->flattenInput($result); + + $encoder = EncoderBase::getEncoder($this->responseType); + $this->output = $encoder->encode($result); + $this->headers = $encoder->getHeaders(); } /** @@ -512,9 +561,12 @@ class Response extends ResponseBase public function output() { if(!empty($this->error)){ + $response = array('message' => $this->error, 'status_code' => 1); + $encoder = EncoderBase::getEncoder($this->responseType); + $this->output = $encoder->encode($response); + $this->headers = $encoder->getHeaders(); + $this->_respondError($this->error_code); - echo $this->error; - exit; } $this->_respond($this->output, $this->headers); diff --git a/ktwebservice/webservice.php b/ktwebservice/webservice.php index 585145c..bc70e67 100644 --- a/ktwebservice/webservice.php +++ b/ktwebservice/webservice.php @@ -1455,7 +1455,7 @@ class KTWebService } $folder = $kt->get_folder_by_id($folder_id); - if(PEAR::isError($document)){ + if(PEAR::isError($folder)){ $response=array( 'status_code'=>KTWS_ERR_INVALID_FOLDER, 'message'=>$folder->getMessage() @@ -1699,7 +1699,7 @@ class KTWebService } $source_document = &$kt->get_document_by_id($source_document_id); - if (PEAR::isError($source_folder)) + if (PEAR::isError($source_document)) { $response = KTWebService::_status(KTWS_ERR_INVALID_DOCUMENT,$source_document); @@ -2454,7 +2454,7 @@ class KTWebService if (PEAR::isError($tempfilename)) { $reason = $tempfilename->getMessage(); - $response = KTWebService::_status(KTWS_ERR_INVALID_DOCUMENT,'Cannot write to temp file: ' + $tempfilename . ". Reason: $reason"); + $response = KTWebService::_status(KTWS_ERR_INVALID_DOCUMENT,'Cannot write to temp file: ' . $tempfilename . ". Reason: $reason"); $this->debug("add_small_document - cannot write $tempfilename. Reason: $reason", $session_id); return new SOAP_Value('return',"{urn:$this->namespace}kt_document_detail", $response); @@ -2639,7 +2639,7 @@ class KTWebService if (PEAR::isError($tempfilename)) { $reason = $tempfilename->getMessage(); - $response = KTWebService::_status(KTWS_ERR_INVALID_DOCUMENT,'Cannot write to temp file: ' + $tempfilename . ". Reason: $reason"); + $response = KTWebService::_status(KTWS_ERR_INVALID_DOCUMENT,'Cannot write to temp file: ' . $tempfilename . ". Reason: $reason"); $this->debug("checkin_small_document - cannot write $tempfilename. Reason: $reason", $session_id); return new SOAP_Value('return',"{urn:$this->namespace}kt_document_detail", $response); diff --git a/lib/documentmanagement/documentutil.inc.php b/lib/documentmanagement/documentutil.inc.php index 2556283..834379a 100644 --- a/lib/documentmanagement/documentutil.inc.php +++ b/lib/documentmanagement/documentutil.inc.php @@ -995,6 +995,9 @@ $sourceDocument->getName(), return PEAR::raiseError(_kt('There was a problem deleting the document from storage.')); } + // get the user object + $oUser = User::get($_SESSION['userID']); + //delete all shortcuts linking to this document $aSymlinks = $oDocument->getSymbolicLinks(); foreach($aSymlinks as $aSymlink){ @@ -1005,7 +1008,7 @@ $sourceDocument->getName(), //send an email to the owner of the shortcut if($oOwnerUser->getEmail()!=null && $oOwnerUser->getEmailNotification() == true){ - $emailTemplate = new EmailTemplate("kt3/notifications/notification.SymbolicLinkDeleted",array('user_name'=>$this->oUser->getName(), + $emailTemplate = new EmailTemplate("kt3/notifications/notification.SymbolicLinkDeleted",array('user_name'=>$oUser->getName(), 'url'=>KTUtil::ktLink(KTBrowseUtil::getUrlForDocument($oShortcutDocument)), 'title' =>$oShortcutDocument->getName())); $email = new EmailAlert($oOwnerUser->getEmail(),_kt("KnowledgeTree Notification"),$emailTemplate->getBody()); diff --git a/lib/foldermanagement/Folder.inc b/lib/foldermanagement/Folder.inc index c92740b..6fffd95 100644 --- a/lib/foldermanagement/Folder.inc +++ b/lib/foldermanagement/Folder.inc @@ -130,6 +130,11 @@ class Folder extends KTEntity { //now load fields from the folder this folder is linking to, if any. if($this->isSymbolicLink()){ $oLinkedFolder = $this->getLinkedFolder(); + + if(PEAR::isError($oLinkedFolder)){ + return PEAR::raiseError(_kt("Linked folder can't be found: ") . $oLinkedFolder->getMessage()); + } + $this->sName = $oLinkedFolder->getName(); $this->sDescription = $oLinkedFolder->getDescription(); } diff --git a/lib/foldermanagement/folderutil.inc.php b/lib/foldermanagement/folderutil.inc.php index ac24b33..91c961f 100644 --- a/lib/foldermanagement/folderutil.inc.php +++ b/lib/foldermanagement/folderutil.inc.php @@ -241,12 +241,13 @@ class KTFolderUtil { // First, deal with SQL, as it, at least, is guaranteed to be atomic $table = "folders"; - if ($oFolder->getId() == 1) { + if ($oFolder->getId() == 1 || $oFolder->getParentID() == 1) { $sOldPath = $oFolder->getName(); $sNewPath = $sNewName; } else { $sOldPath = $oFolder->getFullPath(); - $sNewPath = dirname($oFolder->getFullPath()) . '/' . $sNewName; + $sNewPathDir = !empty($sOldPath) ? dirname($sOldPath) . '/' : ''; + $sNewPath = $sNewPathDir . $sNewName; } $sQuery = "UPDATE $table SET full_path = CONCAT(?, SUBSTRING(full_path FROM ?)) WHERE full_path LIKE ? OR full_path = ?"; @@ -400,7 +401,7 @@ class KTFolderUtil { foreach($aFolderIds as $iFolder){ $oFolder = Folder::get($iFolder); $aLinks = $oFolder->getSymbolicLinks(); - array_merge($aSymlinks, $aLinks); + $aSymlinks = array_merge($aSymlinks, $aLinks); } // documents all cleared. @@ -423,11 +424,14 @@ class KTFolderUtil { $linkIds = implode(',', $links); $query = "DELETE FROM folders WHERE id IN ($linkIds)"; + DBUtil::runQuery($query); } + /* foreach($aSymlinks as $aSymlink){ KTFolderUtil::deleteSymbolicLink($aSymlink['id']); } + */ // purge caches KTEntityUtil::clearAllCaches('Folder'); diff --git a/tests/api/testAcl.php b/tests/api/testAcl.php index 273aeb0..f2298fd 100644 --- a/tests/api/testAcl.php +++ b/tests/api/testAcl.php @@ -9,6 +9,7 @@ class APIAclTestCase extends KTUnitTestCase { */ var $ktapi; var $session; + var $root; /** * Setup the session @@ -17,6 +18,7 @@ class APIAclTestCase extends KTUnitTestCase { function setUp() { $this->ktapi = new KTAPI(); $this->session = $this->ktapi->start_system_session(); + $this->root = $this->ktapi->get_root_folder(); } /** @@ -27,6 +29,140 @@ class APIAclTestCase extends KTUnitTestCase { $this->session->logout(); } + + /* *** Testing KTAPI ACL functions *** */ + + /** + * Testing get list of roles + */ + function testGetRoles() + { + $list = $this->ktapi->get_roles(); + + $this->assertEqual($list['status_code'], 0); + $this->assertTrue(!empty($list['results'])); + + // filter roles - should return the "Everyone" role + $list = $this->ktapi->get_roles('Ever'); + + $this->assertEqual($list['status_code'], 0); + $this->assertTrue(!empty($list['results'])); + $this->assertEqual(count($list['results']), 1); + $this->assertEqual($list['results'][0]['name'], 'Everyone'); + } + + /** + * Testing get role by id and name + */ + function testGetRole() + { + // get by id -2 - should return system role Owner + $role = $this->ktapi->get_role_by_id(-2); + + $this->assertEqual($role['status_code'], 0); + $this->assertTrue(!empty($role['results'])); + $this->assertEqual($role['results']['name'], 'Owner'); + + // get by name Authenticated + $role = $this->ktapi->get_role_by_name('Authenticated Users'); + + $this->assertEqual($role['status_code'], 0); + $this->assertTrue(!empty($role['results'])); + $this->assertEqual($role['results']['name'], 'Authenticated Users'); + $this->assertEqual($role['results']['id'], -4); + } + + /** + * Test role allocation on folders + */ + function testAllocatingMembersToRoles() + { + $folder = $this->ktapi->get_folder_by_name('test123'); + if(!$folder instanceof KTAPI_Folder){ + $folder = $this->root->add_folder('test123'); + } + $folder_id = $folder->get_folderid(); + + $allocation = $this->ktapi->get_role_allocation_for_folder($folder_id); + $this->assertEqual($allocation['status_code'], 0); + $this->assertTrue(empty($allocation['results'])); + + // add a user to a role + $role_id = 2; // Publisher + $user_id = 1; // Admin + $result = $this->ktapi->add_user_to_role_on_folder($folder_id, $role_id, $user_id); + $this->assertEqual($result['status_code'], 0); + + $allocation = $this->ktapi->get_role_allocation_for_folder($folder_id); + $this->assertEqual($allocation['status_code'], 0); + $this->assertTrue(isset($allocation['results']['Publisher'])); + $this->assertEqual($allocation['results']['Publisher']['user'][1], 'Administrator'); + + // test check on members in the role + $check = $this->ktapi->is_member_in_role_on_folder($folder_id, $role_id, $user_id, 'user'); + $this->assertEqual($check['status_code'], 0); + $this->assertEqual($check['results'], 'YES'); + + // remove user from a role + $result = $this->ktapi->remove_user_from_role_on_folder($folder_id, $role_id, $user_id); + $this->assertEqual($result['status_code'], 0); + + $allocation = $this->ktapi->get_role_allocation_for_folder($folder_id); + $this->assertEqual($allocation['status_code'], 0); + $this->assertFalse(isset($allocation['results']['Publisher'])); + + // clean up + $folder->delete('Testing API'); + } + + /** + * Test inherit and override role allocation and remove all allocations + */ + function testRoleAllocationInheritance() + { + $folder = $this->ktapi->get_folder_by_name('test123'); + if(!$folder instanceof KTAPI_Folder){ + $folder = $this->root->add_folder('test123'); + } + $folder_id = $folder->get_folderid(); + + $allocation = $this->ktapi->get_role_allocation_for_folder($folder_id); + $this->assertEqual($allocation['status_code'], 0); + + // Override + $result = $this->ktapi->override_role_allocation_on_folder($folder_id); + $this->assertEqual($result['status_code'], 0); + + $role_id = 2; // Publisher + $user_id = 1; // Admin + $group_id = 1; // System Administrators + $members = array('users' => array($user_id), 'groups' => array($group_id)); + + $result = $this->ktapi->add_members_to_role_on_folder($folder_id, $role_id, $members); + $this->assertEqual($result['status_code'], 0); + + $check = $this->ktapi->is_member_in_role_on_folder($folder_id, $role_id, $user_id, 'user'); + $this->assertEqual($check['status_code'], 0); + $this->assertEqual($check['results'], 'YES'); + + // Remove all + $result = $this->ktapi->remove_all_role_allocation_from_folder($folder_id, $role_id); + $this->assertEqual($result['status_code'], 0); + + $check = $this->ktapi->is_member_in_role_on_folder($folder_id, $role_id, $group_id, 'group'); + $this->assertEqual($check['status_code'], 0); + $this->assertEqual($check['results'], 'NO'); + + // Inherit + $result = $this->ktapi->inherit_role_allocation_on_folder($folder_id); + $this->assertEqual($result['status_code'], 0); + + // clean up + $folder->delete('Testing API'); + } + + /* *** Testing ACL classes *** */ + /** * * Test KTAPI_User getList(), getById(), getByName, getByUsername() diff --git a/tests/api/testApi.php b/tests/api/testApi.php index 19e84f6..1d6f2ef 100644 --- a/tests/api/testApi.php +++ b/tests/api/testApi.php @@ -449,8 +449,186 @@ class APITestCase extends KTUnitTestCase { $document->expunge(); } - function createRandomFile($content = 'this is some text') { - $temp = tempnam(dirname(__FILE__), 'myfile'); + /* *** Test webservice functions *** */ + + /** + * Testing folder creation and deletion, add document, get folder contents, folder detail + * Folder shortcuts and actions + */ + public function testFolderApiFunctions() + { + // check for a negative result + $result = $this->ktapi->create_folder(0, 'New test error api folder'); + $this->assertNotEqual($result['status_code'], 0); + + // Create a folder + $result1 = $this->ktapi->create_folder(1, 'New test api folder'); + $folder_id = $result1['results']['id']; + + $this->assertEqual($result1['status_code'], 0); + $this->assertTrue($result1['results']['parent_id'] == 1); + + // Create a sub folder + $result2 = $this->ktapi->create_folder($folder_id, 'New test api sub-folder'); + $folder_id2 = $result2['results']['id']; + $this->assertEqual($result2['status_code'], 0); + + // Add a document + global $default; + $dir = $default->uploadDirectory; + $tempfilename = $this->createRandomFile('some text', $dir); + $doc = $this->ktapi->add_document($folder_id, 'New API test doc', 'testdoc1.txt', 'Default', $tempfilename); + + $this->assertEqual($doc['status_code'], 0); + $this->assertEqual($doc['results']['title'], 'New API test doc'); + + // Get folder 1 contents + $contents = $this->ktapi->get_folder_contents($folder_id, $depth=1, $what='DFS'); + $this->assertEqual($contents['status_code'], 0); + $this->assertEqual(count($contents['results']['items']), 2); + + $detail = $this->ktapi->get_folder_detail($folder_id2); + $this->assertEqual($detail['status_code'], 0); + $this->assertTrue($detail['results']['parent_id'] == $folder_id); + + // Create a shortcut to the subfolder from the root folder + $shortcut = $this->ktapi->create_folder_shortcut(1, $folder_id2); + $this->assertEqual($shortcut['status_code'], 0); + $this->assertEqual($shortcut['results']['folder_name'], 'New test api sub-folder'); + $this->assertEqual($shortcut['results']['parent_id'], 1); + + $shortcut_list = $this->ktapi->get_folder_shortcuts($folder_id2); + $this->assertEqual($shortcut['status_code'], 0); + $this->assertEqual(count($shortcut_list['results']), 1); + + // Rename the folder + $renamed = $this->ktapi->rename_folder($folder_id, 'Renamed test folder'); + $this->assertEqual($renamed['status_code'], 0); + + $renamed_detail = $this->ktapi->get_folder_detail_by_name('Renamed test folder'); + $this->assertEqual($renamed_detail['status_code'], 0); + $this->assertEqual($renamed_detail['results']['id'], $folder_id); + +// $this->ktapi->copy_folder($source_id, $target_id, $reason); +// $this->ktapi->move_folder($source_id, $target_id, $reason); + + + // Clean up - delete the folder + $this->ktapi->delete_folder($folder_id, 'Testing API'); + $detail2 = $this->ktapi->get_folder_detail($folder_id); + $this->assertNotEqual($detail2['status_code'], 0); + } + + /** + * Testing document get, update, actions, delete, shortcuts and detail + */ + public function testDocumentApiFunctions() + { + // Create a folder + $result1 = $this->ktapi->create_folder(1, 'New test api folder'); + $folder_id = $result1['results']['id']; + $this->assertEqual($result1['status_code'], 0); + + // Create a sub folder + $result2 = $this->ktapi->create_folder($folder_id, 'New test api sub-folder'); + $folder_id2 = $result2['results']['id']; + $this->assertEqual($result2['status_code'], 0); + + // Add a document + global $default; + $dir = $default->uploadDirectory; + $tempfilename = $this->createRandomFile('some text', $dir); + $doc = $this->ktapi->add_document($folder_id, 'New API test doc', 'testdoc1.txt', 'Default', $tempfilename); + + $doc_id = $doc['results']['document_id']; + $this->assertEqual($doc['status_code'], 0); + + // Get document detail + $detail = $this->ktapi->get_document_detail($doc_id);//, 'MLTVH'); + $this->assertEqual($detail['status_code'], 0); + $this->assertEqual($detail['results']['document_type'], 'Default'); + $this->assertEqual($detail['results']['folder_id'], $folder_id); + + // Get document detail - filename + $detail2 = $this->ktapi->get_document_detail_by_filename($folder_id, 'testdoc1.txt'); + $this->assertEqual($detail2['status_code'], 0); + $this->assertEqual($detail2['results']['title'], 'New API test doc'); + + // Get document detail - title + $detail3 = $this->ktapi->get_document_detail_by_title($folder_id, 'New API test doc'); + $this->assertEqual($detail3['status_code'], 0); + $this->assertEqual($detail3['results']['filename'], 'testdoc1.txt'); + + // Get document detail - name + $detail4 = $this->ktapi->get_document_detail_by_name($folder_id, 'New API test doc'); + $this->assertEqual($detail4['status_code'], 0); + $this->assertEqual($detail4['results']['title'], 'New API test doc'); + + // Checkout the document + $result1 = $this->ktapi->checkout_document($doc_id, 'Testing API', true); + $this->assertEqual($result1['status_code'], 0); + $this->assertTrue(!empty($result1['results'])); + + // Checkin the document + $dir = $default->uploadDirectory; + $tempfilename = $this->createRandomFile('some text', $dir); + $result2 = $this->ktapi->checkin_document($doc_id, 'testdoc1.txt', 'Testing API', $tempfilename, false); + + $this->assertEqual($result2['status_code'], 0); + $this->assertEqual($result2['results']['document_id'], $doc_id); + + // Create document shortcut + $shortcut = $this->ktapi->create_document_shortcut(1, $doc_id); + $this->assertEqual($shortcut['status_code'], 0); + $this->assertEqual($shortcut['results']['title'], 'New API test doc'); + $this->assertEqual($shortcut['results']['folder_id'], $folder_id); + + // Delete the document + $result3 = $this->ktapi->delete_document($doc_id, 'Testing API'); + $this->assertEqual($result3['status_code'], 0); + + // Clean up - delete the folder + $this->ktapi->delete_folder($folder_id, 'Testing API'); + $detail2 = $this->ktapi->get_folder_detail($folder_id); + $this->assertNotEqual($detail2['status_code'], 0); + } + + /** + * 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 delete docs + */ + function deleteDocument($document) + { + $document->delete('Testing API'); + $document->expunge(); + } + + function createRandomFile($content = 'this is some text', $uploadDir = null) { + if(is_null($uploadDir)){ + $uploadDir = dirname(__FILE__); + } + $temp = tempnam($uploadDir, 'myfile'); $fp = fopen($temp, 'wt'); fwrite($fp, $content); fclose($fp); diff --git a/tests/api/testBulkActions.php b/tests/api/testBulkActions.php index a4bbf61..aab8e90 100644 --- a/tests/api/testBulkActions.php +++ b/tests/api/testBulkActions.php @@ -48,6 +48,147 @@ class APIBulkActionsTestCase extends KTUnitTestCase { $this->session->logout(); } + /* *** Test KTAPI functions *** */ + + /** + * Testing the bulk actions - copy, move, delete + */ + public function testApiBulkCopyMoveDelete() + { + // Create folder and documents + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt'); + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.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); + + $target_folder = $this->root->add_folder("New target folder"); + $this->assertNotError($target_folder); + if(PEAR::isError($target_folder)) return; + $target_folder_id = $target_folder->get_folderid(); + + $aItems = array(); + $aItems['documents'][] = $doc1->get_documentid(); + $aItems['documents'][] = $doc2->get_documentid(); + $aItems['folders'][] = $folder1->get_folderid(); + + // Call bulk action - copy + $response = $this->ktapi->performBulkAction('copy', $aItems, 'Testing API', $target_folder_id); + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + + // Test move action - delete and recreate target folder + $target_folder->delete('Testing API'); + + $target_folder = $this->root->add_folder("New target folder"); + $this->assertNotError($target_folder); + if(PEAR::isError($target_folder)) return; + $target_folder_id = $target_folder->get_folderid(); + + $response = $this->ktapi->performBulkAction('move', $aItems, 'Testing API', $target_folder_id); + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + + $response = $this->ktapi->performBulkAction('delete', $aItems, 'Testing API'); + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + + // Delete and expunge documents and folder + $target_folder->delete('Testing API'); + } + + /** + * Testing the bulk actions - checkout and cancel check out + */ + public function testApiBulkCheckout() + { + // Create folder and documents + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt'); + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.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); + + $doc1_id = $doc1->get_documentid(); + $doc2_id = $doc2->get_documentid(); + + $aItems = array(); + $aItems['documents'][] = $doc1_id; + $aItems['documents'][] = $doc2_id; + $aItems['folders'][] = $folder1->get_folderid(); + + // Call bulk action - checkout + $response = $this->ktapi->performBulkAction('checkout', $aItems, 'Testing API'); + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + + // update document object + $doc1 = $this->ktapi->get_document_by_id($doc1_id); + $this->assertTrue($doc1->is_checked_out()); + + // cancel the checkout + $response = $this->ktapi->performBulkAction('undo_checkout', $aItems, 'Testing API'); + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + + // delete items + $response = $this->ktapi->performBulkAction('delete', $aItems, 'Testing API'); + $this->assertEqual($response['status_code'], 0); + } + + /** + * Testing the bulk actions - checkout and cancel check out + */ + public function testApiBulkImmute() + { + // Create folder and documents + $doc1 = $this->createDocument('Test Doc One', 'testdoc1.txt'); + $doc2 = $this->createDocument('Test Doc Two', 'testdoc2.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); + + $doc1_id = $doc1->get_documentid(); + $doc2_id = $doc2->get_documentid(); + + $aItems = array(); + $aItems['documents'][] = $doc1_id; + $aItems['documents'][] = $doc2_id; + $aItems['folders'][] = $folder1->get_folderid(); + + // Call bulk action - checkout + $response = $this->ktapi->performBulkAction('immute', $aItems); + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + + // update document object + $doc1 = $this->ktapi->get_document_by_id($doc1_id); + $this->assertTrue($doc1->isImmutable()); + + // remove immutability for deletion + $doc1->unimmute(); + $doc2->unimmute(); + $doc4->unimmute(); + + // delete items + $response = $this->ktapi->performBulkAction('delete', $aItems, 'Testing API'); + $this->assertEqual($response['status_code'], 0); + } + + /* *** Test Bulk actions class *** */ + /** * Test the bulk copy functionality */ @@ -182,6 +323,9 @@ class APIBulkActionsTestCase extends KTUnitTestCase { $this->assertTrue($doc1->is_checked_out()); $this->assertTrue($doc2->is_checked_out()); $this->assertTrue($doc3->is_checked_out()); + + // refresh the doc4 document object to reflect changes + $doc4 = KTAPI_Document::get($this->ktapi, $doc4->get_documentid()); $this->assertTrue($doc4->is_checked_out()); $res = $this->bulk->undo_checkout($aItems, 'Testing bulk undo / cancel checkout'); @@ -191,6 +335,9 @@ class APIBulkActionsTestCase extends KTUnitTestCase { $this->assertFalse($doc1->is_checked_out()); $this->assertFalse($doc2->is_checked_out()); $this->assertFalse($doc3->is_checked_out()); + + // refresh the doc4 document object to reflect changes + $doc4 = KTAPI_Document::get($this->ktapi, $doc4->get_documentid()); $this->assertFalse($doc4->is_checked_out()); // Delete and expunge documents and folder @@ -226,6 +373,9 @@ class APIBulkActionsTestCase extends KTUnitTestCase { $this->assertTrue($doc1->isImmutable()); $this->assertTrue($doc2->isImmutable()); $this->assertTrue($doc3->isImmutable()); + + // refresh the doc4 document object to reflect changes + $doc4 = KTAPI_Document::get($this->ktapi, $doc4->get_documentid()); $this->assertTrue($doc4->isImmutable()); // remove immutability for deletion @@ -268,6 +418,9 @@ class APIBulkActionsTestCase extends KTUnitTestCase { $this->assertTrue($doc1->is_deleted()); $this->assertTrue($doc2->is_deleted()); $this->assertTrue($doc3->is_deleted()); + + // refresh the doc4 document object to reflect changes + $doc4 = KTAPI_Document::get($this->ktapi, $doc4->get_documentid()); $this->assertTrue($doc4->is_deleted()); // Check folder has been deleted @@ -305,6 +458,9 @@ class APIBulkActionsTestCase extends KTUnitTestCase { $document1 = $doc1->getObject(); $this->assertTrue($document1->getStatusID() == 4); + + // refresh the doc4 document object to reflect changes + $doc4 = KTAPI_Document::get($this->ktapi, $doc4->get_documentid()); $document4 = $doc4->getObject(); $this->assertTrue($document4->getStatusID() == 4); diff --git a/tests/webservices/testRest.php b/tests/webservices/testRest.php new file mode 100644 index 0000000..8261613 --- /dev/null +++ b/tests/webservices/testRest.php @@ -0,0 +1,297 @@ +rootUrl = $url.'/ktwebservice/KTWebService.php?'; + } + + /** + * This method is a placeholder + */ + public function tearDown() + { + } + + /** + * Test login + */ + public function testLogin() + { + // Login and authenticate + $url = $this->rootUrl.'method=login&password=admin&username=admin'; + $response = $this->call($url); + $response = $response['response']; + $session_id = $response['results']; + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(!empty($response['results'])); + + // Logout + $url = $this->rootUrl.'method=logout&session_id='.$session_id; + $response = $this->call($url); + $response = $response['response']; + + $this->assertEqual($response['status_code'], 0); + } + + /** + * Test the successful running of a method + */ + public function testFolderDetails() + { + // Login and authenticate + $url = $this->rootUrl.'method=login&password=admin&username=admin'; + $response = $this->call($url); + $response = $response['response']; + + $this->assertEqual($response['status_code'], 0); + $session_id = $response['results']; + + $url = $this->rootUrl.'method=get_folder_detail&session_id='.$session_id.'&folder_id=1'; + $response = $this->call($url); + $response = $response['response']; + + $this->assertEqual($response['status_code'], 0); + $this->assertTrue(!empty($response['results'])); + $this->assertEqual($response['results']['folder_name'], 'Root Folder'); + $this->assertEqual($response['results']['permissions'], 'RWA'); + + // Logout + $url = $this->rootUrl.'method=logout&session_id='.$session_id; + $response = $this->call($url); + $response = $response['response']; + + $this->assertEqual($response['status_code'], 0); + } + + /** + * Test incorrect authentication and no authentication + */ + public function testAuthenticationError() + { + // Incorrect password + $url = $this->rootUrl.'method=login&password=random&username=admin'; + $response = $this->call($url); + $response = $response['response']; + + $this->assertNotEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + $this->assertTrue(!empty($response['message'])); + + // No session set up - use a random session id + $url = $this->rootUrl.'method=get_folder_detail&session_id=09sfirandom3828492&folder_id=1'; + $response = $this->call($url); + $response = $response['response']; + + $this->assertNotEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + $this->assertTrue(!empty($response['message'])); + } + + /** + * Test incorrect method error and the error response on incorrect parameters + */ + public function testMethodErrors() + { + $url = $this->rootUrl.'method=incorrect_method¶meter=something'; + $response = $this->call($url); + $response = $response['response']; + + $this->assertNotEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + $this->assertTrue(!empty($response['message'])); + + $url = $this->rootUrl.'method=get_folder_detail¶meter=something'; + $response = $this->call($url); + $response = $response['response']; + + $this->assertNotEqual($response['status_code'], 0); + $this->assertTrue(empty($response['results'])); + $this->assertTrue(!empty($response['message'])); + } + + /** + * Convert xml into an array structure + * + * @param unknown_type $contents + * @param unknown_type $get_attributes + * @param unknown_type $priority + * @return unknown + */ + private function xml2array($contents, $get_attributes = 1, $priority = 'tag') + { + if (!function_exists('xml_parser_create')) + { + return array (); + } + $parser = xml_parser_create(''); + + xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + xml_parse_into_struct($parser, trim($contents), $xml_values); + xml_parser_free($parser); + + if (!$xml_values) + return; //Hmm... + + $xml_array = array (); + $parents = array (); + $opened_tags = array (); + $arr = array (); + $current = & $xml_array; + $repeated_tag_index = array (); + foreach ($xml_values as $data) + { + unset ($attributes, $value); + extract($data); + $result = array (); + $attributes_data = array (); + if (isset ($value)) + { + if ($priority == 'tag') + $result = $value; + else + $result['value'] = $value; + } + if (isset ($attributes) and $get_attributes) + { + foreach ($attributes as $attr => $val) + { + if ($priority == 'tag') + $attributes_data[$attr] = $val; + else + $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' + } + } + if ($type == "open") + { + $parent[$level -1] = & $current; + if (!is_array($current) or (!in_array($tag, array_keys($current)))) + { + $current[$tag] = $result; + if ($attributes_data) + $current[$tag . '_attr'] = $attributes_data; + $repeated_tag_index[$tag . '_' . $level] = 1; + $current = & $current[$tag]; + } + else + { + if (isset ($current[$tag][0])) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; + $repeated_tag_index[$tag . '_' . $level]++; + } + else + { + $current[$tag] = array ( + $current[$tag], + $result + ); + $repeated_tag_index[$tag . '_' . $level] = 2; + if (isset ($current[$tag . '_attr'])) + { + $current[$tag]['0_attr'] = $current[$tag . '_attr']; + unset ($current[$tag . '_attr']); + } + } + $last_item_index = $repeated_tag_index[$tag . '_' . $level] - 1; + $current = & $current[$tag][$last_item_index]; + } + } + elseif ($type == "complete") + { + if (!isset ($current[$tag])) + { + $current[$tag] = $result; + $repeated_tag_index[$tag . '_' . $level] = 1; + if ($priority == 'tag' and $attributes_data) + $current[$tag . '_attr'] = $attributes_data; + } + else + { + if (isset ($current[$tag][0]) and is_array($current[$tag])) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level]] = $result; + if ($priority == 'tag' and $get_attributes and $attributes_data) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; + } + $repeated_tag_index[$tag . '_' . $level]++; + } + else + { + $current[$tag] = array ( + $current[$tag], + $result + ); + $repeated_tag_index[$tag . '_' . $level] = 1; + if ($priority == 'tag' and $get_attributes) + { + if (isset ($current[$tag . '_attr'])) + { + $current[$tag]['0_attr'] = $current[$tag . '_attr']; + unset ($current[$tag . '_attr']); + } + if ($attributes_data) + { + $current[$tag][$repeated_tag_index[$tag . '_' . $level] . '_attr'] = $attributes_data; + } + } + $repeated_tag_index[$tag . '_' . $level]++; //0 and 1 index is already taken + } + } + } + elseif ($type == 'close') + { + $current = & $parent[$level -1]; + } + } + return ($xml_array); + } + + /** + * Use curl to run the webservice function + * + * @param unknown_type $url + * @return unknown + */ + private function call($url) { + $c = curl_init($url); + curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); + $xml = curl_exec($c); + curl_close($c); + + $xmlArray = $this->xml2array($xml); + return $xmlArray; + } +} +?> \ No newline at end of file