function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') { $ancestry = array(); $objectId = CMISUtil::decodeObjectId($objectId, $typeId); // TODO - what about other types? only implementing folders and documents at the moment so ignore for now switch ($typeId) { case 'Document': $document = $this->ktapi->get_document_by_id($objectId); $parent = $document->ktapi_folder; $ancestry[] = $parent; break; case 'Folder': $folder = $this->ktapi->get_folder_by_id($objectId); $parent = $this->ktapi->get_folder_by_id($folder->get_parent_folder_id()); $ancestry[] = $parent; break; } $ancestry = CMISUtil::createParentObjectHierarchy($ancestry, $repository->getRepositoryURI, $this->ktapi); return $ancestry; }
public function setContentStream($repositoryId, $documentId, $overwriteFlag, $contentStream, $changeToken = null) { // if no document id was supplied, we are going to create the underlying physical document // NOTE while it might have been nice to keep this out of here, KTAPI has no method for creating a document without // a physical upload, so we cannot create the document first and then add the upload as a content stream, the // entire creation step needs to happen here. // Attempt to decode $documentId, use as is if not detected as encoded $tmpObjectId = $documentId; $tmpObjectId = CMISUtil::decodeObjectId($tmpObjectId, $tmpTypeId); if ($tmpTypeId != 'Unknown') { $documentId = $tmpObjectId; } // TODO deal with other types except documents // fetch type definition of supplied document $CMISDocument = new CMISDocumentObject($documentId, $this->ktapi); // if content stream is not allowed for this object type definition, throw a ConstraintViolationException if ($CMISDocument->getAttribute('contentStreamAllowed') == 'notAllowed') { // NOTE spec version 0.61c specifies both a ConstraintViolationException and a StreamNotSupportedException // for this case. Choosing to throw StreamNotSupportedException until the specification is clarified // as it is a more specific exception throw new StreamNotSupportedException('Content Streams are not allowed for this object type'); } $csFileName = $CMISDocument->getProperty('ContentStreamFilename'); if (!empty($csFileName) && !$overwriteFlag) { throw new ContentAlreadyExistsException('Unable to overwrite existing content stream'); } $tempfilename = CMISUtil::createTemporaryFile($contentStream); // update the document content from this temporary file as per usual // TODO Use checkin_document_with_metadata instead if metadata content submitted || update metadata separately? $response = $this->ktapi->checkin_document($documentId, $csFileName, 'CMIS setContentStream action', $tempfilename, false); if ($response['status_code'] != 0) { throw new StorageException('Unable to update the content stream. ' . $response['message']); } // else // { // $objectId = CMISUtil::encodeObjectId('Document', $response['results']['id']); // } @unlink($csFile); // update the CMIS document object with the content stream information // $CMISDocument->reload($document['result']['document_id']); return $CMISDocument->getProperty('ObjectId'); }
/** * Deals with folder service POST actions. * This includes creation/moving of both folders and documents. */ public function POST_action() { $RepositoryService = new RepositoryService(); $repositories = $RepositoryService->getRepositories(); $repositoryId = $repositories[0]['repositoryId']; // set default action, objectId and typeId $action = 'create'; $objectId = null; $typeId = null; $folderId = $this->params[0]; $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title'); $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary'); $properties = array('name' => $title, 'summary' => $summary); // determine whether this is a folder or a document action // document action create will have a content tag <atom:content> or <content> containing base64 encoding of the document // move action will have an existing id supplied as a parameter - not sure how this works yet as the CMIS clients we are // testing don't support move functionality at this time (2009/07/23) and so we are presuming the following format: // /folder/<folderId>/children/<objectId> // also possible that there will be an existing ObjectId property, try to cater for both until we know how it really works // check for existing object id as parameter in url if (isset($this->params[2])) { $action = 'move'; $objectId = $this->params[2]; } $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object']); // check for existing object id as property of submitted object data if (!empty($cmisObjectProperties['ObjectId'])) { $action = 'move'; $objectId = $cmisObjectProperties['ObjectId']; } // TODO there may be more to do for the checking of an existing object. // e.g. verifying that it does indeed exist, and throwing an exception if it does not: // "If the objected property is present but not valid an exception will be thrown" (from CMIS specification) // NOTE this exception should be thrown in the service API code and not here. // determine type if object is being moved if (!is_null($objectId)) { CMISUtil::decodeObjectId($objectId, $typeId); } // now check for content stream $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content'); // TODO this will possibly need to change somewhat once Relationship Objects come into play. if ($action == 'create' && is_null($content) || $typeId == 'Folder') { $type = 'folder'; } else { $type = 'document'; } $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt()); $success = false; $error = null; if ($action == 'create') { if ($type == 'folder') { $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId); } else { $newObjectId = $ObjectService->createDocument($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId, $content); } // check if returned Object Id is a valid CMIS Object Id CMISUtil::decodeObjectId($newObjectId, $typeId); if ($typeId != 'Unknown') { $success = true; } else { $error = $newObjectId['message']; } } else { if ($action == 'move') { $response = $ObjectService->moveObject($repositoryId, $objectId, '', $folderId); if (!PEAR::isError($response)) { $success = true; } else { $error = $response->getMessage(); } // same object as before $newObjectId = $objectId; $typeId = ucwords($type); } } if ($success) { $this->setStatus($action == 'create' ? self::STATUS_CREATED : self::STATUS_UPDATED); $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $newObjectId, 'POST'); } else { $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $error); } //Expose the responseFeed $this->responseFeed = $feed; }
function testObjectService() { $ObjectService = new KTObjectService($this->ktapi); // $ObjectService->startSession(KT_TEST_USER, KT_TEST_PASS); // set up the folder/doc tree structure with which we will be testing $this->createFolderDocStructure(); $RepositoryService = new KTRepositoryService(); $response = $RepositoryService->getRepositories(); $this->assertEqual($response['status_code'], 0); $this->assertNotNull($response['results'][0]); // we only expect one repository $repository = $response['results'][0]; $repositoryId = $repository['repositoryId']; // TEST 1 // test getting properties for a specific object $objectId = 'F' . $this->folders[0]; $properties = $ObjectService->getProperties($repositoryId, $objectId, false, false); $this->assertNotNull($properties['results']); // echo '<pre>'.print_r($properties['results'], true).'</pre>'; // // test printout $this->printTable($properties['results'][0], 'Properties for Folder Object ' . $objectId . ' (getProperties())'); $objectId = 'D' . $this->docs[0]->get_documentid(); $properties = $ObjectService->getProperties($repositoryId, $objectId, false, false); $this->assertNotNull($properties['results']); // test printout $this->printTable($properties['results'][0], 'Properties for Folder Object ' . $objectId . ' (getProperties())'); // TEST 2 // test creation of a folder (random name so that we don't have to clean up after) // TODO test invalid type // TODO test invalid parent folder // TODO other invalid parameters $created = $ObjectService->createFolder($repositoryId, 'Folder', array('name' => 'My Test Folder ' . mt_rand()), 'F1'); $this->assertNotNull($created['results']); if (!is_null($created['results'])) { $folderId = $created['results']; // check that folder object actually exists $properties = $ObjectService->getProperties($repositoryId, $folderId, false, false); $this->assertNotNull($properties['results']); // test printout $this->printTable($properties['results'][0], 'Properties for CMIS Created Folder Object ' . $folderId . ' (getProperties())'); // delete $this->ktapi->delete_folder(CMISUtil::decodeObjectId($folderId), 'Testing API', KT_TEST_USER, KT_TEST_PASS); } // TEST 3 // test creation of document $folderId = 'F' . $this->folders[0]; // $folderId = 'F1'; $properties = array('name' => 'Test CMIS Document 1', 'title' => 'test_cmis_doc_' . mt_rand() . '.txt'); $contentStream = base64_encode('Some arbitrary text content'); $created = $ObjectService->createDocument($repositoryId, 'Document', $properties, $folderId, $contentStream); $this->assertNotNull($created['results']); // echo '<pre>'.print_r($created, true).'</pre>'; if (!is_null($created['results'])) { $documentId = $created['results']; // check that document object actually exists $properties = $ObjectService->getProperties($repositoryId, $documentId, false, false); $this->assertNotNull($properties['results']); // test printout $this->printTable($properties['results'][0], 'Properties for CMIS Created Document Object ' . $documentId . ' (getProperties())'); } // // TEST 5 // // test updating content stream for existing document // $contentStream = base64_encode('Some updated text content for the content stream'); // $updated = $ObjectService->setContentStream($repositoryId, $documentId, true, $contentStream); // // $this->assertNotNull($updated['results']); // //// echo '<pre>'.print_r($created, true).'</pre>'; // // if (!is_null($updated['results'])) // { //// $documentId = $updated['results']; // // // TODO test getContentStream here when we have it // // } // delete created document $this->ktapi->delete_document(CMISUtil::decodeObjectId($documentId), 'Testing API', false); // TEST $folderId = 'F' . $this->folders[0]; $objectId = 'D' . $this->docs[0]->get_documentid(); // test attempted delete via single object delete on folder which contains content - should fail $response = $ObjectService->deleteObject($repositoryId, $folderId); $this->assertEqual($response['status_code'], 1); $this->assertNotNull($response['message']); // test deletion of folder tree - should succeed unless there are non-deletable objects (checked out) (not testing latter) $response = $ObjectService->deleteTree($repositoryId, $folderId); $this->assertEqual($response['status_code'], 0); $this->assertNotNull($response['results']); // TODO test deleteTree with checkedout documents // test attempted delete of document with single version via single object delete. // should succeed unless there is a valid reason (checked out/immutable) (not testing latter) // TODO test failure on attempt to delete document with more than one version $response = $ObjectService->deleteObject($repositoryId, $objectId); $this->assertEqual($response['status_code'], 0); $this->assertNotNull($response['results']); // TEST // TODO test failed moves (checked out, etc) // folder to move - folder 2 $folderId = 'F' . $this->folders[1]; // document to move - document 3 $objectId = 'D' . $this->docs[1]->get_documentid(); // target folder for all moves $root = $this->ktapi->get_root_folder(); $targetFolderId = 'F' . $root->get_folderid(); // test moving of object (document) $response = $ObjectService->moveObject($repositoryId, $objectId, null, $targetFolderId); $this->assertEqual($response['status_code'], 0); $this->assertNotNull($response['results']); // test moving of object (folder) $response = $ObjectService->moveObject($repositoryId, $folderId, null, $targetFolderId); $this->assertEqual($response['status_code'], 0); $this->assertNotNull($response['results']); // TEST // TODO test failure conditions // TODO test fetching of content stream $response = $ObjectService->getContentStream($repositoryId, $objectId); $this->assertEqual($response['status_code'], 0); $this->assertNotNull($response['results']); // TEST // TODO test setContentStream? unused at the moment // tear down the folder/doc tree structure with which we were testing $this->cleanupFolderDocStructure(); // test printout if (DEBUG_CMIS) { echo '<div> </div>'; } }
public function checkIn($repositoryId, $documentId, $major, $contentStream = null, $changeToken = '', $properties = array(), $checkinComment = '') { $documentId = CMISUtil::decodeObjectId($documentId, $typeId); // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository). try { $pwc = new CMISDocumentObject($documentId, $this->ktapi); } catch (exception $e) { throw new UpdateConflictException($e->getMessage()); } // throw exception if the object is not versionable if (!$pwc->getAttribute('versionable')) { throw new ConstraintViolationException('This document is not versionable and may not be checked in'); } $RepositoryService = new CMISRepositoryService(); try { $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $typeId); } catch (exception $e) { // if we can't get the type definition, then we can't store the content throw new StorageException($e->getMessage()); } if ($typeDefinition['attributes']['contentStreamAllowed'] == 'notAllowed' && !empty($contentStream)) { throw new StreamNotSupportedException('Content Streams are not supported'); } // check that this is the latest version if ($pwc->getProperty('IsLatestVersion') != true) { throw new VersioningException('The document is not the latest version and cannot be checked in'); } // now do the checkin $tempfilename = CMISUtil::createTemporaryFile($contentStream); $response = $this->ktapi->checkin_document($documentId, $pwc->getProperty('ContentStreamFilename'), $reason, $tempfilename, $major, $sig_username, $sig_password); // if there was any error in cancelling the checkout if ($response['status_code'] == 1) { throw new RuntimeException('There was an error checking in the document: ' . $response['message']); } return CMISUtil::encodeObjectId(DOCUMENT, $documentId); }
public function checkIn($repositoryId, $documentId, $major, $changeToken = '', $properties = array(), $contentStream = null, $checkinComment = '') { $documentId = CMISUtil::decodeObjectId($documentId, $typeId); // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository). try { $pwc = new CMISDocumentObject($documentId, $this->ktapi); } catch (exception $e) { throw new UpdateConflictException($e->getMessage()); } // throw exception if the object is not versionable if (!$pwc->getAttribute('versionable')) { throw new ConstraintViolationException('This document is not versionable and may not be checked in'); } return $documentId; }