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 bce4c4e..4f7d855 100644 --- a/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php +++ b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php @@ -42,6 +42,45 @@ include_once 'KT_cmis_atom_service_helper.inc.php'; // FIXME ContentStreamAllowed tag is empty (at least sometimes) /** + * AtomPub Service: object by id + */ +class KT_cmis_atom_service_objectbyid extends KT_cmis_atom_service { + + public function GET_action() + { + $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); + $objectId = $this->params[0]; + $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); + + $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId); + + // Expose the responseFeed + $this->responseFeed = $feed; + } + +} + +/** + * AtomPub Service: object by path + * Fetches an object using the path to the object instead of the object id + */ +class KT_cmis_atom_service_objectbypath extends KT_cmis_atom_service { + + public function GET_action() + { + $ktapi =& KT_cmis_atom_service_helper::getKt(); + $objectId = KT_cmis_atom_service_helper::getObjectId(explode('/', urldecode($this->params[0])), $ktapi, false); + $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); + + $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId); + + // Expose the responseFeed + $this->responseFeed = $feed; + } + +} + +/** * AtomPub Service: folder */ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -53,7 +92,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { public function GET_action() { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); - + // TODO implement full path/node separation as with Alfresco - i.e. path requests come in on path/ and node requests come in on node/ // path request e.g.: path/Root Folder/DroppedDocuments // node request e.g.: node/F1/children @@ -67,14 +106,14 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { else if ($this->params[0] == 'path') { $ktapi =& KT_cmis_atom_service_helper::getKt(); - $folderId = KT_cmis_atom_service_helper::getFolderId($this->params, $ktapi); + $folderId = KT_cmis_atom_service_helper::getObjectId($this->params, $ktapi); } else if (($this->params[1] == 'children') || ($this->params[1] == 'descendants')) { $folderId = $this->params[0]; $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); $response = $ObjectService->getProperties($repositoryId, $folderId, false, false); - + if ($response['status_code'] == 1) { $feed = KT_cmis_atom_service_helper::getErrorFeed($this, KT_cmis_atom_service::STATUS_SERVER_ERROR, $response['message']); $this->responseFeed = $feed; @@ -83,7 +122,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { else { $response = $response['results']; } - + $folderName = $response['properties']['name']['value']; } // NOTE parent changes to parents in later specification @@ -103,7 +142,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { else { $response = $response['results']; } - + // we know that a folder will only have one parent, so we can assume element 0 $folderId = $response['properties']['objectId']['value']; $folderName = $response['properties']['name']['value']; @@ -132,14 +171,14 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { * This includes creation/moving of both folders and documents. */ public function POST_action() - { + { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); // set default action, objectId and typeId - $action = 'create'; + $action = 'create'; $objectId = null; $typeId = null; - + $folderId = $this->params[0]; $title = KT_cmis_atom_service_helper::getAtomValues($this->rawContent, 'title'); $summary = KT_cmis_atom_service_helper::getAtomValues($this->rawContent, 'summary'); @@ -151,41 +190,41 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { // /folder/// // also possible that there will be an existing ObjectId property, try to cater for both until we know how it really works // NOTE this also applies to the source folder id, see above - + // check for existing object id as parameter in url // if sourceFolderId parameter is submitted (expected as parameter 3, or params[2]) then this is a move if (isset($this->params[2])) { $action = 'move'; $sourceFolderId = $this->params[2]; } - + // get object properties - todo send through original properties array and not modified version $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisObjectProperties($this->rawContent); $properties = array('name' => $title, 'summary' => $summary, 'objectTypeId' => $cmisObjectProperties['cmis:objectTypeId']); - + // check for existing object id as property of submitted object data if (!empty($cmisObjectProperties['cmis:objectId'])) { $objectId = $cmisObjectProperties['cmis: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); } - + // check for content stream $content = KT_cmis_atom_service_helper::getCmisContent($this->rawContent); // NOTE not sure about the text type, will need testing, most content will be base64 - $cmisContent = (isset($content['cmisra:base64']) - ? $content['cmisra:base64'] - : ((isset($content['cmisra:text'])) - ? $content['cmisra:text'] - : null)); + $cmisContent = (isset($content['cmisra:base64']) + ? $content['cmisra:base64'] + : ((isset($content['cmisra:text'])) + ? $content['cmisra:text'] + : null)); $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); @@ -220,20 +259,20 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { else if ($action == 'move') { $response = $ObjectService->moveObject($repositoryId, $objectId, $folderId, $sourceFolderId); - + if ($response['status_code'] == 0) { $success = true; } else { $error = $response['message']; } - + // same object as before $newObjectId = $objectId; // FIXME why set this? it does not appear to get used $typeId = ucwords($cmisObjectProperties['cmis:objectTypeId']); } - + if ($success) { $this->setStatus(($action == 'create') ? self::STATUS_CREATED : self::STATUS_UPDATED); @@ -246,7 +285,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { // 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 @@ -259,9 +298,9 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { // we COULD call deleteObject but when we delete a folder we expect to be trying to delete // the folder and all content. // TODO determine whether client is requesting deleteObject or deleteTree - + $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); - + $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); // attempt delete - last parameter sets $deleteAllVersions true @@ -277,17 +316,17 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { else { $response = $response['results']; } - + // list of failed objects? if (is_array($response)) { $this->setStatus(self::STATUS_SERVER_ERROR); - + $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI); $feed->newField('title', 'Error: Failed to delete all objects in tree: ' . self::STATUS_SERVER_ERROR, $feed); - + foreach($response as $failed) - { + { $entry = $feed->newEntry(); $objectElement = $feed->newElement('cmisra:object'); $propertiesElement = $feed->newElement('cmis:properties'); @@ -298,11 +337,11 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { $objectElement->appendChild($propertiesElement); $entry->appendChild($objectElement); } - + $this->responseFeed = $feed; return null; } - + // success $this->setStatus(self::STATUS_NO_CONTENT); } @@ -325,7 +364,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { // TODO how will client request depth? for now we assume as part of the url - will probably be covered by URI templates if (isset($this->params[2])) { $entries = $NavigationService->getDescendants($repositoryId, $folderId, $this->params[2]); - + } else { $entries = $NavigationService->getDescendants($repositoryId, $folderId); @@ -334,22 +373,22 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { else { // error, we shouldn't be here, if we are then the wrong service/function was called } - + // hack, for removing one level of access $entries = $entries['results']; // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI); $workspace = $feed->getWorkspace(); - + $feed->newField('title', $folderName . ' ' . ucwords($feedType), $feed); - + // TODO dynamic? $feedElement = $feed->newField('author'); $element = $feed->newField('name', 'System', $feedElement); $feed->appendChild($feedElement); - - // id + + // id $feed->newField('id', 'urn:uuid:' . $folderId . '-' . $feedType, $feed); // TODO get actual most recent update time, only use current if no other available @@ -359,7 +398,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { $link->appendChild($feed->newAttr('rel', 'self')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/' . $folderId . '/' . $feedType)); $feed->appendChild($link); - + $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'service')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'servicedocument')); @@ -392,11 +431,11 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { public function GET_action() { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); - + $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); $objectId = $this->params[0]; - + // TODO this is "parents" in later versions of the specification // update accordingly when updating to newer specification if ($this->params[1] == 'parent') @@ -412,7 +451,7 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { else { $response = $response['results']; } - + // for now a document will only have one parent as KnowledgeTree does not support multi-filing // TODO update this code if/when multi-filing support is added $objectId = $response[0]['properties']['objectId']['value']; @@ -430,7 +469,7 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { // 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 @@ -439,12 +478,12 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { * @return 204 on success, 500 on error */ public function DELETE_action() - { + { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); - + $VersioningService = new KTVersioningService(KT_cmis_atom_service_helper::getKt()); $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); - + // attempt delete $response = $ObjectService->deleteObject($repositoryId, $this->params[0]); @@ -454,15 +493,15 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { $this->responseFeed = $feed; return null; } - + // success - $this->setStatus(self::STATUS_NO_CONTENT); + $this->setStatus(self::STATUS_NO_CONTENT); } - + } class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { - + protected $serviceType = 'PWC'; /** @@ -472,7 +511,7 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { public function GET_action() { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); - + $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); // determine whether we want the Private Working Copy entry feed or the actual physical Private Working Copy content. @@ -488,7 +527,7 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { // Expose the responseFeed $this->responseFeed = $feed; } - + /** * Deals with DELETE actions for Private Working Copies. * This includes deletion of a specific version of a document (latest version) via deleteObject @@ -499,79 +538,79 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { public function DELETE_action() { // call the cancel checkout function - - $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); + + $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); $VersioningService = new KTVersioningService(KT_cmis_atom_service_helper::getKt()); - + $response = $VersioningService->cancelCheckout($repositoryId, $this->params[0]); if ($response['status_code'] == 1) { $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response['message']); - // Expose the responseFeed + // Expose the responseFeed $this->responseFeed = $feed; return null; } - + $this->setStatus(self::STATUS_NO_CONTENT); $this->responseFeed = null; } - + public function PUT_action() { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); $VersioningService = new KTVersioningService(KT_cmis_atom_service_helper::getKt()); $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); - + // get object properties $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisObjectProperties($this->rawContent); // check for content stream $content = KT_cmis_atom_service_helper::getCmisContent($this->rawContent); // NOTE not sure about the text type, will need testing, most content will be base64 - $cmisContent = (isset($content['cmisra:base64']) - ? $content['cmisra:base64'] - : ((isset($content['cmisra:text'])) - ? $content['cmisra:text'] - : null)); + $cmisContent = (isset($content['cmisra:base64']) + ? $content['cmisra:base64'] + : ((isset($content['cmisra:text'])) + ? $content['cmisra:text'] + : null)); // if we haven't found it now, the hack begins - retrieve the EXISTING content and submit this as the contentStream - // this is needed because KnowledgeTree will not accept a checkin without a content stream but CMISSpaces (and possibly + // this is needed because KnowledgeTree will not accept a checkin without a content stream but CMISSpaces (and possibly // other CMIS clients are the same, does not send a content stream on checkin nor does it offer the user a method to choose one) // NOTE that if the content is INTENDED to be empty this and all the above checks will FAIL! // FIXME this is horrible, terrible, ugly and bad! if (empty($cmisContent)) { $cmisContent = base64_encode(KT_cmis_atom_service_helper::getContentStream($this, $ObjectService, $repositoryId)); } - + // and if we don't have the content stream by now, we give up...but leave the error to be generated by the underlying KnowledgeTree code // checkin function call - // TODO dynamically detect version change type - leaving this for now as the CMIS clients tested do not appear to + // TODO dynamically detect version change type - leaving this for now as the CMIS clients tested do not appear to // offer the choice to the user - perhaps it will turn out that this will come from somewhere else but for now // we assume minor version updates only $major = false; $checkinComment = ''; $response = $VersioningService->checkIn($repositoryId, $this->params[0], $major, $cmisObjectProperties, $cmisContent, $checkinComment); - + if ($response['status_code'] == 1) { $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response['message']); // Expose the responseFeed $this->responseFeed = $feed; return null; } - + $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]); // Expose the responseFeed $this->responseFeed = $feed; } - + } /** * AtomPub Service: checkedout */ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { - + /** * Deals with GET actions for checkedout documents. */ @@ -581,31 +620,31 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { $NavigationService = new KTNavigationService(KT_cmis_atom_service_helper::getKt()); $checkedout = $NavigationService->getCheckedOutDocs($repositoryId); - + // hack, for removing one level of access $checkedout = $checkedout['results']; //Create a new response feed $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI); $workspace = $feed->getWorkspace(); - + $feed->newField('title', 'Checked out Documents', $feed); - + // TODO dynamic? $feedElement = $feed->newField('author'); $element = $feed->newField('name', 'admin', $feedElement); $feed->appendChild($feedElement); - + $feed->appendChild($feed->newElement('id', 'urn:uuid:checkedout')); // 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())); - + $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'self')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/checkedout')); $feed->appendChild($link); - + $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel','first')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/checkedout/pageNo=1&pageSize=0')); @@ -628,7 +667,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { // Expose the responseFeed $this->responseFeed = $feed; } - + public function POST_action() { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); @@ -636,7 +675,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisObjectProperties($this->rawContent); - + // check for existing object id as property of submitted object data if (empty($cmisObjectProperties['cmis:objectId'])) { @@ -645,16 +684,16 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { $this->responseFeed = $feed; return null; } - + $response = $VersioningService->checkOut($repositoryId, $cmisObjectProperties['cmis:objectId']); - + if ($response['status_code'] == 1) { $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, 'No object was specified for checkout'); // Expose the responseFeed $this->responseFeed = $feed; return null; } - + $this->setStatus(self::STATUS_CREATED); $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['cmis:objectId'], 'POST'); @@ -675,17 +714,17 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service { $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); $types = $RepositoryService->getTypes($repositoryId); - + // hack for removing one level of access $types = $types['results']; - + $type = ((empty($this->params[0])) ? 'all' : $this->params[0]); $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); // Expose the responseFeed $this->responseFeed = $feed; } - + } /** diff --git a/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php index 03a12f4..d3c6a1f 100644 --- a/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php +++ b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php @@ -7,7 +7,7 @@ class KT_cmis_atom_service_helper { public static $ktapi = null; public static $repositoryId = null; - + /** * Helper function to set internal repository id * @@ -18,16 +18,16 @@ class KT_cmis_atom_service_helper { if (is_null($RepositoryService)) { $RepositoryService = new KTRepositoryService(); } - + $repositories = $RepositoryService->getRepositories(); - + // hack for removing one level of access $repositories = $repositories['results']; - + // TODO handle multiple repositories - self::$repositoryId = $repositories[0]['repositoryId']; + self::$repositoryId = $repositories[0]['repositoryId']; } - + /** * Helper function to fetch internal repository id * @@ -40,11 +40,11 @@ class KT_cmis_atom_service_helper { * @return string */ static public function getRepositoryId(&$RepositoryService = null, $set = true) - { + { if (empty(self::$repositoryId) || $set) { self::setRepositoryId($RepositoryService); } - + return self::$repositoryId; } @@ -60,7 +60,7 @@ class KT_cmis_atom_service_helper { static public function getObjectFeed(&$service, $ObjectService, $repositoryId, $objectId, $method = 'GET') { self::$repositoryId = $repositoryId; - + $serviceType = $service->getServiceType(); $response = $ObjectService->getProperties($repositoryId, $objectId, false, false); @@ -70,7 +70,7 @@ class KT_cmis_atom_service_helper { $cmisEntry = $response['results']; $response = null; - + // POST/PWC responses only send back an entry, not a feed if (($serviceType == 'PWC') || ($method == 'POST')) { if ($method == 'POST') { @@ -88,10 +88,10 @@ class KT_cmis_atom_service_helper { if ($serviceType == 'PWC') $pwc = true; else $pwc = false; KT_cmis_atom_service_helper::createObjectEntry($response, $cmisEntry, $cmisEntry['properties']['parentId']['value'], $pwc, $method); - + return $response; } - + static public function createObjectFeed(&$feed, $entries, $folderName) { foreach($entries as $cmisEntry) { @@ -109,10 +109,10 @@ class KT_cmis_atom_service_helper { * @param $method The request method used (POST/GET/...) */ static public function createObjectEntry(&$feed, $cmisEntry, $parent, $pwc = false, $method = 'GET') - { + { $workspace = $feed->getWorkspace(); - // create entry + // create entry $entry = $feed->newEntry(); // When request is a POST we will be returning only an object entry, not a full feed, and so this belongs here @@ -124,10 +124,10 @@ class KT_cmis_atom_service_helper { $entry->appendChild($feed->newAttr('xmlns:cmis', 'http://docs.oasis-open.org/ns/cmis/core/200908/')); $entry->appendChild($feed->newAttr('xmlns:cmisra', 'http://docs.oasis-open.org/ns/cmis/restatom/200908/')); } - + self::createObjectEntryContent($entry, $feed, $workspace, $cmisEntry, $parent, $pwc, $method); } - + /** * Creates an AtomPub child feed for a CMIS entry and adds it to the supplied entry * @@ -152,15 +152,15 @@ class KT_cmis_atom_service_helper { // which does not directly support nesting - attempting to create a new feed and append it within the outer // feed resulted in an empty cmisra:children node, so this approach was substituted static public function createChildObjectEntry(&$childrenFeed, $cmisEntry, $workspace, $feed, $folderNam) - { + { $type = strtolower($cmisEntry['properties']['objectTypeId']['value']); - + // create entry $entry = $feed->newElement('entry'); self::createObjectEntryContent($entry, $feed, $workspace, $cmisEntry);//, $parent, $pwc, $method); $childrenFeed->appendChild($entry); } - + /** * Creates the actual object entry: this is shared between other functions which require this content * @@ -174,59 +174,59 @@ class KT_cmis_atom_service_helper { static public function createObjectEntryContent($entry, &$feed, $workspace, $cmisEntry, $parent = '', $pwc = false, $method = 'GET') { $type = $cmisEntry['properties']['objectTypeId']['value']; - + // TODO dynamic actual creator name $responseElement = $feed->newField('author'); $element = $feed->newField('name', 'admin', $responseElement); $entry->appendChild($responseElement); - + $typeString = str_replace('cmis:', '', $type); - + if (!empty($cmisEntry['properties']['contentStreamLength']['value'])) { $field = $feed->newElement('content'); $field->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value'])); - $field->appendChild($feed->newAttr('src', CMIS_APP_BASE_URI . $workspace . '/' . $typeString - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); + $field->appendChild($feed->newAttr('src', CMIS_APP_BASE_URI . $workspace . '/' . $typeString + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); $entry->appendChild($field); } - - // content & id tags + + // content & id tags $id = $cmisEntry['properties']['objectId']['value']; $feed->newField('id', 'urn:uuid:' . $id, $entry); // links $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'self')); - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' - . (!$pwc ? $typeString : 'pwc') . '/' - . $cmisEntry['properties']['objectId']['value'])); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' + . (!$pwc ? $typeString : 'pwc') . '/' + . $cmisEntry['properties']['objectId']['value'])); $entry->appendChild($link); $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'edit')); - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString - . '/' . $cmisEntry['properties']['objectId']['value'])); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString + . '/' . $cmisEntry['properties']['objectId']['value'])); $entry->appendChild($link); - - if ((strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:document') - && (!empty($cmisEntry['properties']['contentStreamLength']['value']))) + + if ((strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:document') + && (!empty($cmisEntry['properties']['contentStreamLength']['value']))) { $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'edit-media')); $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value'])); - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); $entry->appendChild($link); $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'enclosure')); $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value'])); - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); $entry->appendChild($link); } @@ -235,7 +235,7 @@ class KT_cmis_atom_service_helper { $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/' - . $cmisEntry['properties']['objectId']['value'] . '/allowableactions')); + . $cmisEntry['properties']['objectId']['value'] . '/allowableactions')); $entry->appendChild($link); // according to spec this MUST be present, but spec says that links for function which are not supported @@ -243,12 +243,12 @@ class KT_cmis_atom_service_helper { $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/relationships')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/' - . $cmisEntry['properties']['objectId']['value'] . '/rels')); + . $cmisEntry['properties']['objectId']['value'] . '/rels')); $entry->appendChild($link); - + // if there is no parent or parent is 0, do not add the parent link // also if this is specifically the root folder, do not add the parent link -// if (!empty($cmisEntry['properties']['parentId']['value']) && !CMISUtil::isRootFolder(self::$repositoryId, $cmisEntry['properties']['objectId']['value'])) + // if (!empty($cmisEntry['properties']['parentId']['value']) && !CMISUtil::isRootFolder(self::$repositoryId, $cmisEntry['properties']['objectId']['value'])) if (!CMISUtil::isRootFolder(self::$repositoryId, $cmisEntry['properties']['objectId']['value'], self::$ktapi)) { @@ -256,7 +256,7 @@ class KT_cmis_atom_service_helper { $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'up')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/' - . $cmisEntry['properties']['parentId']['value'])); + . $cmisEntry['properties']['parentId']['value'])); $entry->appendChild($link); } @@ -266,18 +266,18 @@ class KT_cmis_atom_service_helper { $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'down')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' - . $typeString - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/children')); + . $typeString + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/children')); $entry->appendChild($link); $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'down')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' - . $typeString - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/descendants')); + . $typeString + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/descendants')); $entry->appendChild($link); - + // TODO add folder tree link when we have folder tree implemented // this will probably use (much) the same code as the folder children functionality } @@ -290,9 +290,9 @@ class KT_cmis_atom_service_helper { $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'stream')); $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value'])); - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); $entry->appendChild($link); } @@ -303,24 +303,24 @@ class KT_cmis_atom_service_helper { { $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'pwc')); - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); $entry->appendChild($link); $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'source')); - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type - . '/' . $cmisEntry['properties']['objectId']['value'] - . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type + . '/' . $cmisEntry['properties']['objectId']['value'] + . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); $entry->appendChild($link); } -// $link = $feed->newElement('link'); -// $link->appendChild($feed->newAttr('rel', 'stream')); -// $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type -// . '/' . $cmisEntry['properties']['objectId']['value'] -// . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); - } + // $link = $feed->newElement('link'); + // $link->appendChild($feed->newAttr('rel', 'stream')); + // $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type + // . '/' . $cmisEntry['properties']['objectId']['value'] + // . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); + } $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel', 'describedby')); @@ -342,26 +342,26 @@ class KT_cmis_atom_service_helper { $objectElement = $feed->newElement('cmisra:object'); $objectElement->appendChild(self::createEntryPropertiesElement($feed, $cmisEntry['properties'])); $entry->appendChild($objectElement); - + // TODO check determination of when to add app:edited tag -// if ($method == 'POST') { - $entry->appendChild($feed->newElement('app:edited', self::formatDatestamp())); -// } + // if ($method == 'POST') { + $entry->appendChild($feed->newElement('app:edited', self::formatDatestamp())); + // } // TODO pathSegment entry - + // deal with child objects if (isset($cmisEntry['children'])) { // add children node and fill with child entries $childrenFeed = $feed->newElement('feed'); self::createObjectChildrenFeed($childrenFeed, $cmisEntry['children'], $workspace, $feed, '' /*folderName not passed through*/); - + $childrenElement = $feed->newElement('cmisra:children'); $childrenElement->appendChild($childrenFeed); $entry->appendChild($childrenElement); } } - + /** * Shared function for creating an object properties node * @@ -376,7 +376,7 @@ class KT_cmis_atom_service_helper { foreach($properties as $propertyName => $property) { $propElement = $feed->newElement('cmis:' . $property['type']); -// $propElement->appendChild($feed->newAttr('localName', 'rep-cmis:' . $propertyName)); + // $propElement->appendChild($feed->newAttr('localName', 'rep-cmis:' . $propertyName)); $propElement->appendChild($feed->newAttr('propertyDefinitionId', 'cmis:' . $propertyName)); if (!empty($property['value'])) { @@ -387,7 +387,7 @@ class KT_cmis_atom_service_helper { } $propertiesElement->appendChild($propElement); } - + return $propertiesElement; } @@ -419,12 +419,12 @@ class KT_cmis_atom_service_helper { //Create a new response feed $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI); $workspace = $feed->getWorkspace(); - + $feed->newField('title', $typesHeading, $feed); $feed->newField('id', 'urn:uuid:' . $typesString, $feed); // TODO set page number correctly - to be done when we support paging the the API - + // author // TODO generate this dynamically (based on???)\ $feedElement = $feed->newField('author'); @@ -434,7 +434,7 @@ class KT_cmis_atom_service_helper { foreach($types as $type) { $entry = $feed->newEntry(); - + $feedElement = $feed->newField('author'); $element = $feed->newField('name', 'admin', $feedElement); $entry->appendChild($feedElement); @@ -442,7 +442,7 @@ class KT_cmis_atom_service_helper { $entry->appendChild($feedElement); $feed->newField('id', 'urn:uuid:type-' . $type['baseId'], $feed); - + // links $link = $feed->newElement('link'); $link->appendChild($feed->newAttr('rel','self')); @@ -459,11 +459,11 @@ class KT_cmis_atom_service_helper { $link->appendChild($feed->newAttr('rel','repository')); $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument')); $entry->appendChild($link); - + $entry->appendChild($feed->newElement('summary', 'Summary for ' . $type['baseId'] . ' type')); $entry->appendChild($feed->newElement('title', $type['baseId'])); $entry->appendChild($feed->newElement('updated', self::formatDatestamp())); - + $objectElement = $feed->newElement('cmisra:type'); foreach($type as $property => $value) { $feed->newField('cmis:' . $property, CMISUtil::boolToString($value), $objectElement); @@ -478,7 +478,7 @@ class KT_cmis_atom_service_helper { { $service->setStatus($status); $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI); - + $feed->newField('title', 'Error: ' . $status, $feed); $entry = $feed->newEntry(); $feed->newField('error', $message, $entry); @@ -493,31 +493,49 @@ class KT_cmis_atom_service_helper { * @param object $ktapi KTAPI instance */ // TODO make this much more efficient than this method - static public function getFolderId($path, &$ktapi) + static public function getObjectId($path, &$ktapi, $shift = true) { - // lose first item - array_shift($path); + // lose first item, if not specified to keep ($shift == false) + // NOTE the shift was for the way info comes from the Drupal module, which may now have changed + if ($shift) { + array_shift($path); + } + // we always start at the root + $lastFolderId = $objectId = 1; $numQ = count($path); - $numFolders = $numQ; - $folderId = 1; - + $numObjects = $numQ; $start = 0; - while($start < $numFolders) + $type = FOLDER; + + while($start < $numObjects) { - $name = $path[$numQ-$numFolders+$start]; - // fix for possible url encoding issue + $name = $path[$numQ - $numObjects + $start]; + // fix for possible url encoding issue - this was for the Drupal code and hopefully one day we can remove it $name = str_replace('%2520', '%20', $name); - $folderName = urldecode($name); - $folder = $ktapi->get_folder_by_name($folderName, $folderId); - $folderId = $folder->get_folderid(); + $objectName = urldecode($name); + // try to get a folder by that name + $object = $ktapi->get_folder_by_name($objectName, $lastFolderId); + if (PEAR::isError($object)) { + // probably not a folder, so let's try for a document by that name + $object = $ktapi->get_document_detail_by_name($lastFolderId, $objectName); + $objectId = $object['results']['document_id']; + // this must be the end (can't have sub-documents or sub-folders within a document + $type = DOCUMENT; + break; + } + else { + $objectId = $object->get_folderid(); + $lastFolderId = $objectId; + } + ++$start; } - - return CMISUtil::encodeObjectId(FOLDER, $folderId); + + return CMISUtil::encodeObjectId($type, $objectId); } - + static public function getCmisObjectProperties(&$xml) { $xmlReader = new XMLReader(); @@ -551,10 +569,10 @@ class KT_cmis_atom_service_helper { } } } - + return $cmisObjectPropertiesCollection; } - + static public function getCmisContent(&$xml) { $xmlReader = new XMLReader(); @@ -577,14 +595,14 @@ class KT_cmis_atom_service_helper { $cmisObjectContent[$cmisContentProperty] = $xmlReader->value; } } - + return $cmisObjectContent; } - + static public function getAtomValues(&$xml, $tag) { $returnTag = null; - + $xmlReader = new XMLReader(); $xmlReader->XML($xml); $foundTag = false; @@ -603,14 +621,14 @@ class KT_cmis_atom_service_helper { } } } - + return $returnTag; } static public function getCmisPropertiesOld($xmlArray) { $properties = array(); - + // find cmisra:object tag $baseCmisObject = KT_cmis_atom_service_helper::findTag('cmisra:object', $xmlArray, null, false); if(count($baseCmisObject) <= 0) @@ -618,7 +636,7 @@ class KT_cmis_atom_service_helper { $entryObject = KT_cmis_atom_service_helper::findTag('entry', $xmlArray, null, false); $baseCmisObject = KT_cmis_atom_service_helper::findTag('cmisra:object', $entryObject['@children'], null, true); } - + if(count($baseCmisObject) > 0) { foreach($baseCmisObject[0]['@children'] as $key => $childElement) @@ -629,8 +647,8 @@ class KT_cmis_atom_service_helper { { foreach($cmisPropertyDefinition as $propertyType => $propertyDefinition) { - $properties[$propertyDefinition['@attributes']['cmis:name']] - = $propertyDefinition['@children']['cmis:value'][0]['@value']; + $properties[$propertyDefinition['@attributes']['cmis:name']] + = $propertyDefinition['@children']['cmis:value'][0]['@value']; } } } @@ -643,9 +661,9 @@ class KT_cmis_atom_service_helper { static public function getAtomValuesOld($xmlArray, $tag) { if (!is_null($xmlArray['atom:'.$tag])) - return $xmlArray['atom:'.$tag][0]['@value']; + return $xmlArray['atom:'.$tag][0]['@value']; else if (!is_null($xmlArray[$tag])) - return $xmlArray[$tag][0]['@value']; + return $xmlArray[$tag][0]['@value']; return null; } @@ -655,23 +673,23 @@ class KT_cmis_atom_service_helper { * * @return object */ - public static function getKt() + public static function getKt() { - if(!isset(self::$ktapi)) + if(!isset(self::$ktapi)) { - self::$ktapi = new KTAPI(); - $active = self::$ktapi->get_active_session(session_id()); - - if (PEAR::isError($active)) - { - // invoke auth code, session must be restarted - if(!KT_atom_HTTPauth::isLoggedIn()) { - KT_atom_HTTPauth::login('KnowledgeTree DMS', 'You must authenticate to enter this realm'); - } - } - } - return self::$ktapi; - } + self::$ktapi = new KTAPI(); + $active = self::$ktapi->get_active_session(session_id()); + + if (PEAR::isError($active)) + { + // invoke auth code, session must be restarted + if(!KT_atom_HTTPauth::isLoggedIn()) { + KT_atom_HTTPauth::login('KnowledgeTree DMS', 'You must authenticate to enter this realm'); + } + } + } + return self::$ktapi; + } // TODO adjust for time zones? static public function formatDatestamp($time = null) @@ -679,7 +697,7 @@ class KT_cmis_atom_service_helper { if (is_null($time)) $time = time(); return date('Y-m-d H:i:s', $time); } - + /** * Fetches the document content stream for internal use * @@ -693,12 +711,12 @@ class KT_cmis_atom_service_helper { if ($response['status_code'] == 1) { return null; } - + $contentStream = $ObjectService->getContentStream($repositoryId, $service->params[0]); - + // hack for removing one level of access $contentStream = $contentStream['results']; - + return $contentStream; } /** @@ -719,41 +737,41 @@ class KT_cmis_atom_service_helper { else { $response = $response['results']; } - + // TODO also check If-Modified-Since? -// $service->headers['If-Modified-Since'] => 2009-07-24 17:16:54 + // $service->headers['If-Modified-Since'] => 2009-07-24 17:16:54 $service->setContentDownload(true); $eTag = md5($response['properties']['lastModificationDate']['value'] . $response['properties']['contentStreamLength']['value']); - + if ($service->headers['If-None-Match'] == $eTag) { $service->setStatus(KT_cmis_atom_service::STATUS_NOT_MODIFIED); $service->setContentDownload(false); return null; } - + $contentStream = $ObjectService->getContentStream($repositoryId, $service->params[0]); - + // hack for removing one level of access $contentStream = $contentStream['results']; - + // headers specific to output $service->setEtag($eTag); $service->setHeader('Last-Modified', $response['properties']['lastModificationDate']['value']); if (!empty($response['properties']['contentStreamMimeType']['value'])) { - $service->setHeader('Content-type', $response['properties']['contentStreamMimeType']['value'] . ';charset=utf-8'); + $service->setHeader('Content-type', $response['properties']['contentStreamMimeType']['value'] . ';charset=utf-8'); } else { - $service->setHeader('Content-type', 'text/plain;charset=utf-8'); + $service->setHeader('Content-type', 'text/plain;charset=utf-8'); } - + $service->setHeader('Content-Disposition', 'attachment;filename="' . $response['properties']['contentStreamFilename']['value'] . '"'); - $service->setHeader('Content-Length', $response['properties']['contentStreamLength']['value']); + $service->setHeader('Content-Length', $response['properties']['contentStreamLength']['value']); $service->setOutput($contentStream); } - + //TODO: Add key information to be able to find the same tag in the original struct (MarkH) static public function findTag($tagName=NULL,$xml=array(),$tagArray=NULL,$deep=false) { @@ -773,11 +791,11 @@ class KT_cmis_atom_service_helper { //TODO: this is very ugly. Change it. (MarkH) return self::rebaseArray($tagArray); } - + static public function rebaseArray($arr=array()){ //Force Array $arr=is_array($arr)?$arr:array(); - + //Rebase recursively if(count($arr)===1)$arr=self::rebaseArray($arr[0]); return $arr; diff --git a/webservice/atompub/cmis/index.php b/webservice/atompub/cmis/index.php index f4601fe..6f28d79 100644 --- a/webservice/atompub/cmis/index.php +++ b/webservice/atompub/cmis/index.php @@ -115,6 +115,9 @@ if ($workspace != 'servicedocument') $APP->registerService('dms', 'type', 'KT_cmis_atom_service_type', 'Object Type Entry', null, 'type'); $APP->registerService('dms', 'document', 'KT_cmis_atom_service_document', 'Document Entry', null, 'document'); $APP->registerService('dms', 'pwc', 'KT_cmis_atom_service_pwc', 'Private Working Copy', null, 'pwc'); + $APP->registerService('dms', 'objectbyid', 'KT_cmis_atom_service_objectbyid', 'Object By Id', null, 'objectbyid'); + $APP->registerService('dms', 'objectbypath', 'KT_cmis_atom_service_objectbypath', 'Object By Path', null, 'objectbypath'); + $APP->registerService('dms', 'typebyid', 'KT_cmis_atom_service_type', 'Type By Id', null, 'typebyid'); } //Execute the current url/header request diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php index 417121d..7423ac3 100644 --- a/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php @@ -69,21 +69,18 @@ class KT_cmis_atom_server extends KT_atom_server { //Creating the Default Workspace for use with standard atomPub Clients $ws = $service->newWorkspace(); - $hadDetail=false; - if(isset($this->workspaceDetail[$workspace])) - { - if(is_array($this->workspaceDetail[$workspace])) - { - foreach ($this->workspaceDetail[$workspace] as $wsTag=>$wsValue) - { - $ws->appendChild($service->newElement($wsTag,$wsValue)); + $hadDetail = false; + if(isset($this->workspaceDetail[$workspace])) { + if(is_array($this->workspaceDetail[$workspace])) { + foreach ($this->workspaceDetail[$workspace] as $wsTag => $wsValue){ + $ws->appendChild($service->newElement($wsTag, $wsValue)); $hadDetail=true; } } } if(!$hadDetail) { - $ws->appendChild($service->newElement('atom:title',$workspace)); + $ws->appendChild($service->newElement('atom:title', $workspace)); } $ws->appendChild($service->newAttr('cmis:repositoryRelationship', $this->repositoryInfo['repositoryRelationship'])); @@ -99,11 +96,9 @@ class KT_cmis_atom_server extends KT_atom_server { if (!is_array($repoData)) { $element->appendChild($service->newElement('cmis:' . $key, $repoData)); } - else - { + else { $elementSub = $service->newElement('cmis:' . $key); - foreach($repoData as $key2 => $data) - { + foreach($repoData as $key2 => $data) { $elementSub->appendChild($service->newElement('cmis:' . $key2, CMISUtil::boolToString($data))); } $element->appendChild($elementSub); @@ -111,21 +106,24 @@ class KT_cmis_atom_server extends KT_atom_server { } $ws->appendChild($element); + // collections + // TODO check collectionType usage against spec foreach($collection as $serviceName => $serviceInstance) { foreach($serviceInstance as $instance) { $collectionStr = CMIS_APP_BASE_URI . $workspace . '/' . $serviceName . '/' . (is_array($instance['parameters']) ? implode('/', $instance['parameters']).'/' : ''); + // FIXME? do we need to return the value from the function? $col = $service->newCollection($collectionStr, $instance['title'], $instance['collectionType'], $instance['accept'], $ws); } } + + // uri templates - getObjectById, getObjectByPath, getTypeById + $ws->appendChild($service->uriTemplate('objectbyid', $workspace)); + $ws->appendChild($service->uriTemplate('objectbypath', $workspace)); + $ws->appendChild($service->uriTemplate('typebyid', $workspace)); } - -// ob_start(); -// readfile('C:\Users\Paul\Documents\Downloads\cmis_mod_kt.xml'); -// $this->output = ob_get_contents(); -// ob_end_clean(); $this->output = $service->getAPPdoc(); } diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php index 3cf8c2b..3e471f7 100644 --- a/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php @@ -83,7 +83,7 @@ class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc { $this->DOM->appendChild($this->service); } - public function &newCollection($url = NULL, $title = NULL, $cmisCollectionType = NULL, $accept = null, &$ws = NULL) + public function newCollection($url = NULL, $title = NULL, $cmisCollectionType = NULL, $accept = null, &$ws = NULL) { $collection=$this->newElement('collection'); $collection->appendChild($this->newAttr('href', $url)); @@ -93,8 +93,45 @@ class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc { $collection->appendChild($this->newElement('accept', $accept)); } if(isset($ws))$ws->appendChild($collection); + + // FIXME? do we need to return the value from the function if $ws is supplied? return $collection; } + + /** + * Creates the specified URI template within the AtomPub response + * + * @param string $templateType + * @param string $workspace + * @return string $uriTemplate + * + * NOTE not adding in all the arguments for optional functionality not supported, e.g. ACL/Policies/Relationships/Renditions; + * arguments for functionality which is non-optional (filters/allowableActions) are included but not yet supported + * by the API code + */ + public function uriTemplate($templateType, $workspace) + { + $content = array('template' => CMIS_APP_BASE_URI . $workspace, 'mediatype' => 'application/atom+xml;type=entry'); + + switch($templateType) { + case 'objectbyid': + $content['template'] .= '/objectbyid/{id}/{filter}/{includeAllowableActions}'; + break; + case 'objectbypath': + $content['template'] .= '/objectbypath/{path}/{filter}/{includeAllowableActions}'; + break; + case 'typebyid': + $content['template'] .= '/typebyid/{id}'; + break; + } + + $uriTemplate = $this->newElement('cmisra:uritemplate'); + $uriTemplate->appendChild($this->newElement('cmisra:template', $content['template'])); + $uriTemplate->appendChild($this->newElement('cmisra:type', $content)); + $uriTemplate->appendChild($this->newElement('cmisra:mediatype', $content['mediatype'])); + + return $uriTemplate; + } }