diff --git a/lib/api/ktcmis/ktcmis.inc.php b/lib/api/ktcmis/ktcmis.inc.php
index 2d9dfc7..0f564bb 100644
--- a/lib/api/ktcmis/ktcmis.inc.php
+++ b/lib/api/ktcmis/ktcmis.inc.php
@@ -56,6 +56,7 @@ require_once(CMIS_DIR . '/exceptions/PermissionDeniedException.inc.php');
require_once(CMIS_DIR . '/services/CMISRepositoryService.inc.php');
require_once(CMIS_DIR . '/services/CMISNavigationService.inc.php');
require_once(CMIS_DIR . '/services/CMISObjectService.inc.php');
+require_once(CMIS_DIR . '/services/CMISVersioningService.inc.php');
require_once(CMIS_DIR . '/util/CMISUtil.inc.php');
/**
@@ -73,7 +74,6 @@ class KTCMISBase {
{
// TODO confirm KTAPI instance active??? shouldn't really be responsibility of this code
if (is_null($ktapi) && (!is_null($username) && !is_null($password))) {
-// echo ":WGHWTWGWGHW";
$this->startSession($username, $password);
}
else {
@@ -87,18 +87,15 @@ class KTCMISBase {
// NOTE left in to allow transport protocol to delegate auth to this level, but not actually used in any code at present
public function startSession($username, $password)
{
-// echo $username." :: ".$password."
";
// attempt to recover session if one exists
if (!is_null(self::$session) && !PEAR::isError(self::$session))
{
-// echo "ATTEMPT TO RECOVER SESSION: ".print_r(self::$session, true)."
\n";
self::$session =& self::$ktapi->get_active_session(self::$session->get_sessionid());
}
// start new session if no existing session or problem getting existing session (expired, etc...)
if (is_null(self::$session) || PEAR::isError(self::$session))
{
-// echo "ATTEMPT TO START NEW SESSION
\n";
self::$ktapi = new KTAPI();
self::$session =& self::$ktapi->start_session($username, $password);
}
@@ -109,7 +106,6 @@ class KTCMISBase {
throw new PermissionDeniedException('You must be authenticated to perform this action');
}
-// print_r(self::$ktapi);
return self::$session;
}
@@ -594,6 +590,54 @@ class KTObjectService extends KTCMISBase {
'results' => $objectId
);
}
+
+ /**
+ * Deletes an object from the repository
+ *
+ * @param string $repositoryId
+ * @param string $objectId
+ * @param string $changeToken [optional]
+ * @return array
+ */
+ // NOTE Invoking this service method on an object SHALL not delete the entire version series for a Document Object.
+ // To delete an entire version series, use the deleteAllVersions() service
+ function deleteObject($repositoryId, $objectId, $changeToken = null)
+ {
+ try {
+ $result = $this->ObjectService->deleteObject($repositoryId, $objectId, $changeToken);
+ }
+ catch (Exception $e)
+ {
+ return array(
+ "status_code" => 1,
+ "message" => $e->getMessage()
+ );
+ }
+
+ return array(
+ 'status_code' => 0,
+ 'results' => $objectId
+ );
+ }
+
+ public function deleteTree($repositoryId, $objectId, $changeToken = null, $unfileNonfolderObject = 'delete', $continueOnFailure = false)
+ {
+ try {
+ $result = $this->ObjectService->deleteTree($repositoryId, $objectId, $changeToken, $unfileNonfolderObject, $continueOnFailure);
+ }
+ catch (Exception $e)
+ {
+ return array(
+ "status_code" => 1,
+ "message" => $e->getMessage()
+ );
+ }
+
+ return array(
+ 'status_code' => 0,
+ 'results' => $objectId
+ );
+ }
/**
* Sets the content stream data for an existing document
@@ -614,7 +658,7 @@ class KTObjectService extends KTCMISBase {
function setContentStream($repositoryId, $documentId, $overwriteFlag, $contentStream, $changeToken = null)
{
try {
- $objectId = $this->ObjectService->setContentStream($repositoryId, $documentId, $overwriteFlag, $contentStream, $changeToken);
+ $documentId = $this->ObjectService->setContentStream($repositoryId, $documentId, $overwriteFlag, $contentStream, $changeToken);
}
catch (Exception $e)
{
@@ -632,4 +676,60 @@ class KTObjectService extends KTCMISBase {
}
+/**
+ * Handles requests for and actions on versionable objects
+ */
+class KTVersioningService extends KTCMISBase {
+
+ protected $VersioningService;
+
+ public function __construct(&$ktapi = null, $username = null, $password = null)
+ {
+ parent::__construct($ktapi, $username, $password);
+ // instantiate underlying CMIS service
+ $this->VersioningService = new CMISVersioningService();
+ $this->setInterface();
+ }
+
+ public function startSession($username, $password)
+ {
+ parent::startSession($username, $password);
+ $this->setInterface();
+ return self::$session;
+ }
+
+ public function setInterface(&$ktapi = null)
+ {
+ parent::setInterface($ktapi);
+ $this->VersioningService->setInterface(self::$ktapi);
+ }
+
+ /**
+ * Deletes all Document Objects in the specified Version Series, including the Private Working Copy
+ *
+ * @param string $repositoryId
+ * @param string $versionSeriesId
+ * @return boolean true if successful
+ */
+ public function deleteAllVersions($repositoryId, $versionSeriesId)
+ {
+ try {
+ $result = $this->VersioningService->deleteAllVersions($repositoryId, $versionSeriesId);
+ }
+ catch (Exception $e)
+ {
+ return array(
+ "status_code" => 1,
+ "message" => $e->getMessage()
+ );
+ }
+
+ return array(
+ 'status_code' => 0,
+ 'results' => $result
+ );
+ }
+
+}
+
?>
diff --git a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
index 90aec9e..557afc4 100644
--- a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
+++ b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
@@ -144,8 +144,9 @@ class CMISDocumentObject extends CMISBaseObject {
// NOTE see ktapi::is_latest_version
$this->_setPropertyInternal('IsLatestMajorVersion', true);
$this->_setPropertyInternal('VersionLabel', $objectProperties['version']);
- // TODO what determines this, do we have anything?
- $this->_setPropertyInternal('VersionSeriesId', null);
+ // VersionSeriesId should be the id of the latest version
+ // NOTE this may change in the future but is easiest for the current implementation
+ $this->_setPropertyInternal('VersionSeriesId', $objectProperties['version']);
if ($objectProperties['checked_out_by'] != 'n/a')
{
$checkedOut = true;
diff --git a/lib/api/ktcmis/services/CMISNavigationService.inc.php b/lib/api/ktcmis/services/CMISNavigationService.inc.php
index eb4393a..c8e692f 100644
--- a/lib/api/ktcmis/services/CMISNavigationService.inc.php
+++ b/lib/api/ktcmis/services/CMISNavigationService.inc.php
@@ -48,7 +48,7 @@ class CMISNavigationService {
protected $ktapi;
/**
- * Sets the interface to be used to query the repository
+ * Sets the interface to be used to interact with the repository
*
* @param object $ktapi The KnowledgeTree API interface
*/
diff --git a/lib/api/ktcmis/services/CMISObjectService.inc.php b/lib/api/ktcmis/services/CMISObjectService.inc.php
index 372a9c9..14a6b60 100644
--- a/lib/api/ktcmis/services/CMISObjectService.inc.php
+++ b/lib/api/ktcmis/services/CMISObjectService.inc.php
@@ -21,11 +21,11 @@ class CMISObjectService {
protected $ktapi;
/**
- * Sets the interface to be used to query the repository
+ * Sets the interface to be used to interact with the repository
*
* @param object $ktapi The KnowledgeTree API interface
*/
- function setInterface(&$ktapi)
+ public function setInterface(&$ktapi)
{
$this->ktapi = $ktapi;
}
@@ -43,8 +43,8 @@ class CMISObjectService {
*/
// TODO optional parameter support
// TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid
- function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships,
- $returnVersion = false, $filter = '')
+ public function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships,
+ $returnVersion = false, $filter = '')
{
$repository = new CMISRepository($repositoryId);
@@ -87,8 +87,8 @@ class CMISObjectService {
// TODO throw ConstraintViolationException if:
// value of any of the properties violates the min/max/required/length constraints
// specified in the property definition in the Object-Type.
- function createDocument($repositoryId, $typeId, $properties, $folderId = null,
- $contentStream = null, $versioningState = null)
+ public function createDocument($repositoryId, $typeId, $properties, $folderId = null,
+ $contentStream = null, $versioningState = null)
{
$objectId = null;
@@ -344,7 +344,7 @@ class CMISObjectService {
// TODO throw ConstraintViolationException if:
// value of any of the properties violates the min/max/required/length constraints
// specified in the property definition in the Object-Type.
- function createFolder($repositoryId, $typeId, $properties, $folderId)
+ public function createFolder($repositoryId, $typeId, $properties, $folderId)
{
$objectId = null;
@@ -399,6 +399,148 @@ class CMISObjectService {
return $objectId;
}
+
+ /**
+ * Deletes an object from the repository
+ *
+ * @param string $repositoryId
+ * @param string $objectId
+ * @param string $changeToken [optional]
+ * @return boolean true on success (exception should be thrown otherwise)
+ */
+ // NOTE Invoking this service method on an object SHALL not delete the entire version series for a Document Object.
+ // To delete an entire version series, use the deleteAllVersions() service
+ public function deleteObject($repositoryId, $objectId, $changeToken = null)
+ {
+ // determine object type and internal id
+ $objectId = CMISUtil::decodeObjectId($objectId, $typeId);
+
+ // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository).
+ $exists = true;
+ if ($typeId == 'Folder') {
+ $object = $this->ktapi->get_folder_by_id($objectId);
+ if (PEAR::isError($object)) {
+ $exists = false;
+ }
+ }
+ else if ($typeId == 'Document') {
+ $object = $this->ktapi->get_document_by_id($objectId);
+ if (PEAR::isError($object)) {
+ $exists = false;
+ }
+ }
+ else {
+ $exists = false;
+ }
+
+ if (!$exists) {
+ throw new updateConflictException('Unable to delete the object as it cannot be found.');
+ }
+
+ // throw ConstraintViolationException if method is invoked on a Folder object that contains one or more objects
+ if ($typeId == 'Folder')
+ {
+ $folderContent = $object->get_listing();
+ if (!PEAR::isError($folderContent))
+ {
+ if (count($folderContent) > 0) {
+ throw new ConstraintViolationException('Unable to delete a folder with content. Use deleteTree instead.');
+ }
+ }
+
+ // now try the delete and throw an exception if there is an error
+ // TODO add a default reason
+ // TODO add the electronic signature capability
+ $result = $this->ktapi->delete_folder($objectId, $reason, $sig_username, $sig_password);
+ }
+ else if ($typeId == 'Document')
+ {
+ // since we do not allow deleting of only the latest version we must throw an exception when this function is called on any document
+ // which has more than one version. Okay to delete if there is only the one version.
+ $versions = $object->get_version_history();
+ if (count($versions) > 1)
+ {
+ // NOTE possibly may want to just throw a RuntimeException rather than this CMIS specific exception.
+ throw new ConstraintViolationException('This function may not be used to delete an object which has multiple versions. '
+ . 'Since the repository does not allow deleting of only the latest version, nothing can be deleted.');
+ }
+
+ // do not allow deletion of a checked out document - this is actually handled by the ktapi code,
+ // but is possibly slightly more efficient to check before trying to delete
+ if ($object->is_checked_out()) {
+ throw new RuntimeException('The object cannot be deleted as it is currently checked out');
+ }
+
+ // now try the delete and throw an exception if there is an error
+ // TODO add a default reason
+ // TODO add the electronic signature capability
+ $auth_sig = true;
+ $result = $this->ktapi->delete_document($objectId, $reason, $auth_sig, $sig_username, $sig_password);
+ }
+
+ // if there was an error performing the delete, throw exception
+ if ($result['status_code'] == 1) {
+ throw new RuntimeException('There was an error deleting the object: ' . $result['message']);
+ }
+
+ return true;
+ }
+
+ /**
+ * Deletes an entire tree including all subfolders and other filed objects
+ *
+ * @param string $repositoryId
+ * @param string $objectId
+ * @param string $changeToken [optional]
+ * @param boolean $unfileNonfolderObject [optional] - note that since KnowledgeTree does not allow unfiling this will be ignored
+ * @param boolean $continueOnFailure [optional] - note that since KnowledgeTree does not allow continue on failure this will be ignored
+ * @return array $failedToDelete A list of identifiers of objects in the folder tree that were not deleted.
+ */
+ // NOTE • A Repository MAY attempt to delete child- and descendant-objects of the specified folder in any order.
+ // • Any child- or descendant-object that the Repository cannot delete SHALL persist in a valid state in the CMIS domain model.
+ // • This is not transactional.
+ // • However, if DeleteSingleFiled is chosen and some objects fail to delete, then single-filed objects are either deleted or kept,
+ // never just unfiled. This is so that a user can call this command again to recover from the error by using the same tree.
+ public function deleteTree($repositoryId, $objectId, $changeToken = null, $unfileNonfolderObject = 'delete', $continueOnFailure = false)
+ {
+ // NOTE since we do not currently allow partial deletes this will always be empty
+ // (unless there is a failure at the requested folder level - what do we do then? exception or array of all objects?)
+ $failedToDelete = array();
+
+ // determine object type and internal id
+ $objectId = CMISUtil::decodeObjectId($objectId, $typeId);
+
+ // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository).
+ $exists = true;
+ if ($typeId == 'Folder') {
+ $object = $this->ktapi->get_folder_by_id($objectId);
+ if (PEAR::isError($object)) {
+ $exists = false;
+ }
+ }
+ // if not of type folder then we have a general problem, throw exception
+ else {
+ throw new RuntimeException('Cannot call deleteTree on a non-folder object.');
+ }
+
+ if (!$exists) {
+ throw new updateConflictException('Unable to delete the object as it cannot be found.');
+ }
+
+ // attempt to delete tree, throw RuntimeException if failed
+ // TODO add a default reason
+ // TODO add the electronic signature capability
+ $result = $this->ktapi->delete_folder($objectId, $reason, $sig_username, $sig_password);
+ // if there was an error performing the delete, throw exception
+ // TODO list of objects which failed in $failedToDelete array;
+ // since we do not delete the folder or any contents if anything cannot be deleted, this will contain the entire tree listing
+ // NOTE once we do this we will need to deal with it externally as well, since we can no longer just catch an exception.
+ if ($result['status_code'] == 1) {
+ throw new RuntimeException('There was an error deleting the object: ' . $result['message']);
+ }
+
+ return $failedToDelete;
+ }
// NOTE this function is presently incomplete and untested. Completion deferred to implementation of Checkout/Checkin
// functionality
@@ -428,7 +570,7 @@ class CMISObjectService {
// updateConflictException: The operation is attempting to update an object that is no longer current
// (as determined by the repository).
// versioningException: The repository MAY throw this exception if the object is a non-current Document Version.
- function setContentStream($repositoryId, $documentId, $overwriteFlag, $contentStream, $changeToken = null)
+ 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
diff --git a/lib/api/ktcmis/services/CMISVersioningService.inc.php b/lib/api/ktcmis/services/CMISVersioningService.inc.php
new file mode 100644
index 0000000..6ced85b
--- /dev/null
+++ b/lib/api/ktcmis/services/CMISVersioningService.inc.php
@@ -0,0 +1,74 @@
+ktapi = $ktapi;
+ }
+
+ /**
+ * Deletes all Document Objects in the specified Version Series, including the Private Working Copy
+ *
+ * @param string $repositoryId
+ * @param string $versionSeriesId
+ * @return boolean true if successful
+ */
+ // NOTE For KnowledgeTree the $versionSeriesId should be the latest version, if not it will be taken as implied.
+ // Should we decide to implement the ability to delete individual versions,
+ // then an exception may be thrown under certain circumstances (to be determined)
+ // NOTE I am not really sure how this is going to be handled by CMIS clients.
+ // Testing with CMISSpaces we have it sending the actual document id, not a version series id.
+ // This may be due to the data sent back from our code, or it may just be how CMISSpaces does it.
+ // There is a note in their source code about this.
+ // Meantime we will try based on document id and adjust as needed later
+ public function deleteAllVersions($repositoryId, $versionSeriesId)
+ {
+ // attempt to delete based on versionSeriesId as document/object id
+ // determine object type and internal id
+ $objectId = CMISUtil::decodeObjectId($versionSeriesId, $typeId);
+
+ // if not a versionable object, throw exception
+ // NOTE that we are assuming only documents are versionable at the moment
+ if ($typeId != 'Document') {
+ throw new RuntimeException('The object type is not versionable and cannot be deleted using deleteAllVersions.');
+ }
+
+ // try to delete
+ // TODO add a default reason
+ // TODO add the electronic signature capability
+ $auth_sig = true;
+ $result = $this->ktapi->delete_document($objectId, $reason, $auth_sig, $sig_username, $sig_password);
+
+ // if there was an error performing the delete, throw exception
+ if ($result['status_code'] == 1) {
+ throw new RuntimeException('There was an error deleting the object: ' . $result['message']);
+ }
+
+ return true;
+ }
+
+}
+
+?>
diff --git a/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
index 5c6a965..c1d325b 100644
--- a/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
+++ b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
@@ -33,18 +33,20 @@ When POSTing an Atom Document, the atom fields take precedence over the CMIS pro
include_once CMIS_ATOM_LIB_FOLDER . 'RepositoryService.inc.php';
include_once CMIS_ATOM_LIB_FOLDER . 'NavigationService.inc.php';
include_once CMIS_ATOM_LIB_FOLDER . 'ObjectService.inc.php';
+include_once CMIS_ATOM_LIB_FOLDER . 'VersioningService.inc.php';
include_once 'KT_cmis_atom_service_helper.inc.php';
// TODO auth failed response requires WWW-Authenticate: Basic realm="KnowledgeTree DMS" header
/**
* AtomPub Service: folder
- *
- * Returns children, descendants (up to arbitrary depth) or detail for a particular folder
- *
*/
class KT_cmis_atom_service_folder extends KT_atom_service {
+ /**
+ * Deals with GET actions for folders.
+ * This includes children and tree/descendant listings as well as individual folder retrieval
+ */
public function GET_action()
{
$RepositoryService = new RepositoryService();
@@ -88,6 +90,10 @@ class KT_cmis_atom_service_folder extends KT_atom_service {
$this->responseFeed = $feed;
}
+ /**
+ * Deals with folder service POST actions.
+ * This includes creation of both folders and documents.
+ */
public function POST_action()
{
$RepositoryService = new RepositoryService();
@@ -131,23 +137,50 @@ class KT_cmis_atom_service_folder extends KT_atom_service {
if ($typeId != 'Unknown')
{
- /*$f = fopen('c:\kt-stuff\here.txt', 'w');
- fwrite($f, 'fgfgfgfg');
- fclose($f);*/
$this->setStatus(self::STATUS_CREATED);
$feed = KT_cmis_atom_service_helper::getObjectFeed($ObjectService, $repositoryId, $newObjectId, 'POST');
}
- else
- {
- /*$f = fopen('c:\kt-stuff\failed.txt', 'w');
- fwrite($f, 'fgfgfgfg');
- fclose($f);*/
+ else {
$feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $newObjectId['message']);
}
//Expose the responseFeed
$this->responseFeed = $feed;
}
+
+ /**
+ * Deals with DELETE actions for folders.
+ * This includes deleting a single folder (with no content) and deleting an entire folder tree
+ *
+ * @return 204 on success, 500 on error
+ */
+ public function DELETE_action()
+ {
+ // NOTE due to the way KnowledgeTree works with folders this is always going to call deleteTree.
+ // we COULD call deleteObject but when we delete a folder we expect to be trying to delete
+ // the folder and all content.
+
+ $RepositoryService = new RepositoryService();
+ $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt());
+
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ // attempt delete
+ $result = $ObjectService->deleteTree($repositoryId, $this->params[0]);
+
+ // error?
+ if (PEAR::isError($result))
+ {
+ $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $result->getMessage());
+ //Expose the responseFeed
+ $this->responseFeed = $feed;
+ return null;
+ }
+
+ // success
+ $this->setStatus(self::STATUS_NO_CONTENT);
+ }
/**
* Retrieves children/descendants of the specified folder
@@ -217,9 +250,6 @@ class KT_cmis_atom_service_folder extends KT_atom_service {
/**
* AtomPub Service: types
- *
- * Returns a list of supported object types
- *
*/
class KT_cmis_atom_service_types extends KT_atom_service {
@@ -241,9 +271,6 @@ class KT_cmis_atom_service_types extends KT_atom_service {
/**
* AtomPub Service: type
- *
- * Returns the type defintion for the selected type
- *
*/
class KT_cmis_atom_service_type extends KT_atom_service {
@@ -318,13 +345,13 @@ class KT_cmis_atom_service_type extends KT_atom_service {
/**
* AtomPub Service: checkedout
- *
- * Returns a list of checked out documents for the logged in user
- *
*/
// NOTE this is always an empty document, underlying API code still to be implemented
class KT_cmis_atom_service_checkedout extends KT_atom_service {
-
+
+ /**
+ * Deals with GET actions for checkedout documents.
+ */
public function GET_action()
{
$RepositoryService = new RepositoryService();
@@ -350,7 +377,6 @@ class KT_cmis_atom_service_checkedout extends KT_atom_service {
// TODO get actual most recent update time, only use current if no other available
$feed->appendChild($feed->newElement('updated', KT_cmis_atom_service_helper::formatDatestamp()));
-//'urn:uuid:checkedout'
foreach($checkedout as $document)
{
$entry = $feed->newEntry();
@@ -380,12 +406,13 @@ class KT_cmis_atom_service_checkedout extends KT_atom_service {
/**
* AtomPub Service: document
- *
- * Returns detail on a particular document
- *
*/
class KT_cmis_atom_service_document extends KT_atom_service {
+ /**
+ * Deals with GET actions for documents.
+ * This includes individual document retrieval
+ */
public function GET_action()
{
$RepositoryService = new RepositoryService();
@@ -400,16 +427,48 @@ class KT_cmis_atom_service_document extends KT_atom_service {
$feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI);
$feed->newField('title', $cmisEntry['properties']['ObjectTypeId']['value'], $feed);
- $feed->newField('id', 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value'], $feed); ;
+ $feed->newField('id', 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value'], $feed);
KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $cmisEntry['properties']['ParentId']['value']);
- // false
-
//Expose the responseFeed
$this->responseFeed=$feed;
}
+ /**
+ * Deals with DELETE actions for documents.
+ * This includes deletion of a specific version of a document (latest version) via deleteObject
+ * as well as deleteAllVersions
+ *
+ * @return 204 on success, 500 on error
+ */
+ public function DELETE_action()
+ {
+ // NOTE due to the way KnowledgeTree works with documents this is always going to call deleteAllVersions.
+ // we do not have support for deleting only specific versions (this may be added in the future.)
+
+ $RepositoryService = new RepositoryService();
+ $VersioningService = new VersioningService(KT_cmis_atom_service_helper::getKt());
+
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ // attempt delete
+ $result = $VersioningService->deleteAllVersions($repositoryId, $this->params[0]);
+
+ // error?
+ if (PEAR::isError($result))
+ {
+ $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $result->getMessage());
+ //Expose the responseFeed
+ $this->responseFeed = $feed;
+ return null;
+ }
+
+ // success
+ $this->setStatus(self::STATUS_NO_CONTENT);
+ }
+
}
?>
\ No newline at end of file
diff --git a/webservice/classes/atompub/KT_atom_service.inc.php b/webservice/classes/atompub/KT_atom_service.inc.php
index 4a3c410..832a1b2 100644
--- a/webservice/classes/atompub/KT_atom_service.inc.php
+++ b/webservice/classes/atompub/KT_atom_service.inc.php
@@ -2,6 +2,7 @@
class KT_atom_service{
const STATUS_OK = '200 OK';
const STATUS_NOT_FOUND = '204 No Content';
+ const STATUS_NO_CONTENT = '204 No Content';
const STATUS_NOT_ALLOWED = '204 Not Allowed';
const STATUS_CREATED = '201 Created';
const STATUS_UPDATED = '200 Updated';
diff --git a/webservice/classes/atompub/cmis/ObjectService.inc.php b/webservice/classes/atompub/cmis/ObjectService.inc.php
index 90171e6..897736a 100644
--- a/webservice/classes/atompub/cmis/ObjectService.inc.php
+++ b/webservice/classes/atompub/cmis/ObjectService.inc.php
@@ -26,8 +26,7 @@ class ObjectService extends KTObjectService {
$result = parent::getProperties($repositoryId, $objectId, $includeAllowableActions,
$returnVersion, $filter);
- if ($result['status_code'] == 0)
- {
+ if ($result['status_code'] == 0) {
return $result['results'];
}
}
@@ -45,12 +44,10 @@ class ObjectService extends KTObjectService {
{
$result = parent::createFolder($repositoryId, $typeId, $properties, $folderId);
- if ($result['status_code'] == 0)
- {
+ if ($result['status_code'] == 0) {
return $result['results'];
}
- else
- {
+ else {
return $result;
}
}
@@ -75,15 +72,57 @@ class ObjectService extends KTObjectService {
{
$result = parent::createDocument($repositoryId, $typeId, $properties, $folderId, $contentStream, $versioningState);
- if ($result['status_code'] == 0)
- {
+ if ($result['status_code'] == 0) {
return $result['results'];
}
- else
- {
+ else {
return $result;
}
}
+
+ /**
+ * Deletes an object from the repository
+ *
+ * @param string $repositoryId
+ * @param string $objectId
+ * @param string $changeToken [optional]
+ * @return boolean true on success, false on failure
+ */
+ // NOTE Invoking this service method on an object SHALL not delete the entire version series for a Document Object.
+ // To delete an entire version series, use the deleteAllVersions() service
+ function deleteObject($repositoryId, $objectId, $changeToken = null)
+ {
+ $result = parent::deleteObject($repositoryId, $objectId, $changeToken);
+
+ if ($result['status_code'] == 0) {
+ return $result['results'];
+ }
+ else {
+ return new PEAR_Error($result['message']);
+ }
+ }
+
+ /**
+ * Deletes an entire tree including all subfolders and other filed objects
+ *
+ * @param string $repositoryId
+ * @param string $objectId
+ * @param string $changeToken [optional]
+ * @param boolean $unfileNonfolderObject [optional] - note that since KnowledgeTree does not allow unfiling this will be ignored
+ * @param boolean $continueOnFailure [optional] - note that since KnowledgeTree does not allow continue on failure this will be ignored
+ * @return array $failedToDelete A list of identifiers of objects in the folder tree that were not deleted.
+ */
+ public function deleteTree($repositoryId, $objectId, $changeToken = null, $unfileNonfolderObject = 'delete', $continueOnFailure = false)
+ {
+ $result = parent::deleteTree($repositoryId, $objectId, $changeToken, $unfileNonfolderObject, $continueOnFailure);
+
+ if ($result['status_code'] == 0) {
+ return $result['results'];
+ }
+ else {
+ return new PEAR_Error($result['message']);
+ }
+ }
}
diff --git a/webservice/classes/atompub/cmis/VersioningService.inc.php b/webservice/classes/atompub/cmis/VersioningService.inc.php
new file mode 100644
index 0000000..6a2c3aa
--- /dev/null
+++ b/webservice/classes/atompub/cmis/VersioningService.inc.php
@@ -0,0 +1,33 @@
+