diff --git a/lib/api/ktcmis/classes/CMISObject.inc.php b/lib/api/ktcmis/classes/CMISObject.inc.php index cb49313..1942663 100644 --- a/lib/api/ktcmis/classes/CMISObject.inc.php +++ b/lib/api/ktcmis/classes/CMISObject.inc.php @@ -155,7 +155,7 @@ abstract class CMISObject { $this->_get($objectId); } - private function _get($objectId) + protected function _get($objectId) { // override in child classes } diff --git a/lib/api/ktcmis/classes/CMISPropertyCollection.inc.php b/lib/api/ktcmis/classes/CMISPropertyCollection.inc.php index 2a6158e..48c2765 100644 --- a/lib/api/ktcmis/classes/CMISPropertyCollection.inc.php +++ b/lib/api/ktcmis/classes/CMISPropertyCollection.inc.php @@ -61,7 +61,7 @@ abstract class CMISPropertyCollection { // TODO these definitions belong in their own classe definition (see property type definions,) but here will do for now static public $propertyTypes; - function __construct() + public function __construct() { self::$propertyTypes = array('objectId' => 'propertyId', 'author' => 'propertyString', @@ -83,7 +83,7 @@ abstract class CMISPropertyCollection { /** * Gets the property value. */ - function getValue($field) + public function getValue($field) { return $this->{$field}; } @@ -92,12 +92,12 @@ abstract class CMISPropertyCollection { * Sets the property value. */ // for connection-tied live objects - function setValue($field, $value) + public function setValue($field, $value) { $this->{$field} = $value; } - function getFieldType($field) + public function getFieldType($field) { return $this->propertyTypes[$field]; } diff --git a/lib/api/ktcmis/ktObjectService.inc.php b/lib/api/ktcmis/ktObjectService.inc.php index 2b74953..d6d6750 100644 --- a/lib/api/ktcmis/ktObjectService.inc.php +++ b/lib/api/ktcmis/ktObjectService.inc.php @@ -113,22 +113,24 @@ class KTObjectService extends KTCMISBase { * Creates a new document within the repository * * @param string $repositoryId The repository to which the document must be added - * @param string $typeId Object Type id for the document object being created * @param array $properties Array of properties which must be applied to the created document object * @param string $folderId The id of the folder which will be the parent of the created document object * This parameter is optional IF unfilingCapability is supported - * @param contentStream $contentStream optional content stream data - * @param string $versioningState optional version state value: checkedout/major/minor + * @param string $contentStream optional content stream data - expected as a base64 encoded string + * @param string $versioningState optional version state value: none/checkedout/major/minor + * @param $policies List of policy ids that MUST be applied + * @param $addACEs List of ACEs that MUST be added + * @param $removeACEs List of ACEs that MUST be removed * @return string $objectId The id of the created folder object */ - public function createDocument($repositoryId, $typeId, $properties, $folderId = null, - $contentStream = null, $versioningState = null) + public function createDocument($repositoryId, $properties, $folderId = null, $contentStream = null, $versioningState = null, + $policies = array(), $addACEs = array(), $removeACEs = array()) { $objectId = null; try { - $objectId = $this->ObjectService->createDocument($repositoryId, $typeId, $properties, $folderId, - $contentStream, $versioningState); + $objectId = $this->ObjectService->createDocument($repositoryId, $typeId, $properties, $folderId, $contentStream, + $versioningState,$policies, $addACEs, $removeACEs); } catch (Exception $e) { diff --git a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php index 888f21b..df559a2 100644 --- a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php +++ b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php @@ -57,7 +57,7 @@ class CMISDocumentObject extends CMISObject { protected $ktapi; // TODO some of this should probably come from configuration files as it is repository specific - function __construct($documentId = null, &$ktapi = null, $uri = null) + public function __construct($documentId = null, &$ktapi = null, $uri = null) { $this->ktapi = $ktapi; @@ -102,7 +102,7 @@ class CMISDocumentObject extends CMISObject { } // TODO abstract shared stuff to base class where possible - private function _get($documentId) + protected function _get($documentId) { $object = $this->ktapi->get_document_by_id((int)$documentId); diff --git a/lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php b/lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php index d16cf06..442f01b 100644 --- a/lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php +++ b/lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php @@ -88,7 +88,7 @@ class CMISFolderObject extends CMISObject { } // TODO abstract shared stuff to base class where possible - private function _get($folderId) + protected function _get($folderId) { $object = $this->ktapi->get_folder_by_id((int)$folderId); @@ -125,7 +125,7 @@ class CMISFolderObject extends CMISObject { $this->_setPropertyInternal('changeToken', null); $this->_setPropertyInternal('name', $objectProperties['folder_name']); $this->_setPropertyInternal('parentId', CMISUtil::encodeObjectId(FOLDER, $objectProperties['parent_id'])); - $this->_setPropertyInternal('allowedChildObjectTypeIds', array('Document', 'Folder')); + $this->_setPropertyInternal('allowedChildObjectTypeIds', array('cmis:document', 'cmis:folder')); $this->_setPropertyInternal('author', $objectProperties['created_by']); } diff --git a/lib/api/ktcmis/services/CMISObjectService.inc.php b/lib/api/ktcmis/services/CMISObjectService.inc.php index 96c19de..9124682 100644 --- a/lib/api/ktcmis/services/CMISObjectService.inc.php +++ b/lib/api/ktcmis/services/CMISObjectService.inc.php @@ -34,33 +34,34 @@ class CMISObjectService { * Creates a new document within the repository * * @param string $repositoryId The repository to which the document must be added - * @param string $typeId Object Type id for the document object being created * @param array $properties Array of properties which must be applied to the created document object * @param string $folderId The id of the folder which will be the parent of the created document object * This parameter is optional IF unfilingCapability is supported * @param string $contentStream optional content stream data - expected as a base64 encoded string - * @param string $versioningState optional version state value: checkedout/major/minor + * @param string $versioningState optional version state value: none/checkedout/major/minor + * @param $policies List of policy ids that MUST be applied + * @param $addACEs List of ACEs that MUST be added + * @param $removeACEs List of ACEs that MUST be removed * @return string $objectId The id of the created folder object */ // 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. - public function createDocument($repositoryId, $typeId, $properties, $folderId = null, - $contentStream = null, $versioningState = null) + // TODO throw ConstraintViolationException if At least one of the permissions is used in + // an ACE provided which is not supported by the repository. + // NOTE typeId is supplied in the cmis:objectTypeId property in the properties array + public function createDocument($repositoryId, $properties, $folderId = null, $contentStream = null, + $versioningState = null, $policies = array(), $addACEs = array(), + $removeACEs = array()) { $objectId = null; // fetch type definition of supplied type and check for base type "document", if not true throw exception $RepositoryService = new CMISRepositoryService(); try { - $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $typeId); + $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $properties['objectTypeId']); } - // NOTE Not sure that we should throw this specific exception, maybe just let the underlying - // exception propogate upward... - // Alternatively: throw new exception with original exception message appended - // NOTE The latter method has been adopted for the moment - catch (Exception $e) - { + catch (Exception $e) { throw new ConstraintViolationException('Object base type could not be determined. ' . $e->getMessage()); } @@ -95,7 +96,7 @@ class CMISObjectService { { foreach($allowed as $type) { - if (strtolower($type) == strtolower($typeId)) + if (strtolower($type) == strtolower($properties['objectTypeId'])) { $typeAllowed = true; break; @@ -117,9 +118,23 @@ class CMISObjectService { } // if versionable attribute is set to false and versioningState is supplied, throw a ConstraintViolationException - if (!$typeDefinition['attributes']['versionable'] && !empty($versioningState)) { - throw new ConstraintViolationException('This repository does not support versioning'); + if (!$typeDefinition['attributes']['versionable'] && (!empty($versioningState) || $versioningState != 'none')) { + throw new ConstraintViolationException('This object-type does not support versioning'); + } + else if ($typeDefinition['attributes']['versionable'] && (empty($versioningState) || $versioningState == 'none')) { + throw new ConstraintViolationException('Invalid versioning state supplied'); } + + if (!$typeDefinition['attributes']['controllablePolicy'] && count($policies)) { + throw new ConstraintViolationException('This object-type does not support policies'); + } + + if (!$typeDefinition['attributes']['controllableACL'] && (count($addACEs) || count($removeACEs))) { + throw new ConstraintViolationException('This object-type does not support ACLs'); + } + + // TODO throw NameConstraintViolation if there is a violation with the given cmis:name property value + // OR choose a name which does not conflict // TODO deal with $versioningState when supplied @@ -146,6 +161,10 @@ class CMISObjectService { // this check isn't strictly necessary; however it is needed for a repository which does not support content streams if (!is_null($contentStream)) { + if (!$typeDefinition['attributes']['contentStreamAllowed']) { + throw new StreamNotSupportedException('Content streams are not supported by this object-type'); + } + $tempfilename = CMISUtil::createTemporaryFile($contentStream); // metadata @@ -210,6 +229,7 @@ class CMISObjectService { include_once(KT_LIB_DIR . '/mime.inc.php'); $KTMime = new KTMime(); $mimetype = $KTMime->getMimeTypeFromFile($tempfilename); + // extract type string from mimetype response preg_match('/^([^\/]*)\/([^\/]*)/', $mimetype, $matches); if (($matches[1] == 'text') || ($matches[1] == 'image') || ($matches[1] == 'audio')) { $mediatype = ucwords($matches[1]); 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 95a0759..ecfa3f7 100644 --- a/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php +++ b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php @@ -143,8 +143,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { $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 or 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 @@ -160,6 +158,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { } $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']); + $properties = array('name' => $title, 'summary' => $summary, 'typeId' => $cmisObjectProperties['objectTypeId']); // check for existing object id as property of submitted object data if (!empty($cmisObjectProperties['objectId'])) @@ -175,14 +174,20 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { // determine type if object is being moved if (!is_null($objectId)) { - CMISUtil::decodeObjectId($objectId, $typeId); + CMISUtil::decodeObjectId($objectId, $cmisObjectProperties['objectTypeId']); } // check for content stream - $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content'); + $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content'); + + global $default; +// $default->log->info('cmis object type id: ' . $cmisObjectProperties['objectTypeId']); +// $default->log->info(print_r($cmisObjectProperties, true)); +// $default->log->info(print_r($this->parsedXMLContent['@children'], true)); + $default->log->info(print_r($this->rawContent, true)); - // TODO this will possibly need to change somewhat once Relationship Objects come into play. - if ((($action == 'create') && (is_null($content))) || ($typeId == 'Folder')) { + // TODO this will need to change somewhat once other object-types come into play. + if ((($action == 'create') && (is_null($content))) || ($cmisObjectProperties['objectTypeId'] == 'cmis:folder')) { $type = 'folder'; } else { @@ -195,13 +200,14 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { $error = null; if ($action == 'create') { + // TODO detection and passing of optional parameters (policies, ACEs, etc...) 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); + CMISUtil::decodeObjectId($newObjectId, $cmisObjectProperties['objectTypeId']); if ($typeId != 'Unknown') $success = true; else $error = $newObjectId['message']; } 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 43c87fa..d351dcf 100644 --- a/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php +++ b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php @@ -479,9 +479,9 @@ class KT_cmis_atom_service_helper { $baseCmisObject = KT_cmis_atom_service_helper::findTag('cmisra:object', $entryObject['@children'], null, true); } - if(count($baseCmisObject)>0) + if(count($baseCmisObject) > 0) { - foreach($baseCmisObject['@children'] as $key => $childElement) + foreach($baseCmisObject[0]['@children'] as $key => $childElement) { if ($key == 'cmis:properties') { @@ -489,7 +489,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']; } } } @@ -605,7 +606,8 @@ class KT_cmis_atom_service_helper { } //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){ + static public function findTag($tagName=NULL,$xml=array(),$tagArray=NULL,$deep=false) + { $tagArray=is_array($tagArray)?$tagArray:array(); foreach($xml as $xmlTag=>$content){ if($xmlTag===$tagName){ diff --git a/webservice/classes/atompub/cmis/ObjectService.inc.php b/webservice/classes/atompub/cmis/ObjectService.inc.php index f1d007d..7528884 100644 --- a/webservice/classes/atompub/cmis/ObjectService.inc.php +++ b/webservice/classes/atompub/cmis/ObjectService.inc.php @@ -38,21 +38,25 @@ class ObjectService extends KTObjectService { * Creates a new document within the repository * * @param string $repositoryId The repository to which the document must be added - * @param string $typeId Object Type id for the document object being created * @param array $properties Array of properties which must be applied to the created document object * @param string $folderId The id of the folder which will be the parent of the created document object * This parameter is optional IF unfilingCapability is supported - * @param contentStream $contentStream optional content stream data - * @param string $versioningState optional version state value: checkedout/major/minor + * @param string $contentStream optional content stream data - expected as a base64 encoded string + * @param string $versioningState optional version state value: none/checkedout/major/minor + * @param $policies List of policy ids that MUST be applied + * @param $addACEs List of ACEs that MUST be added + * @param $removeACEs List of ACEs that MUST be removed * @return string $objectId The id of the created folder object */ // 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. - public function createDocument($repositoryId, $typeId, $properties, $folderId = null, - $contentStream = null, $versioningState = null) + public function createDocument($repositoryId, $properties, $folderId = null, $contentStream = null, + $versioningState = null, $policies = array(), $addACEs = array(), + $removeACEs = array()) { - $result = parent::createDocument($repositoryId, $typeId, $properties, $folderId, $contentStream, $versioningState); + $result = parent::createDocument($repositoryId, $properties, $folderId, $contentStream, $versioningState, + $policies, $addACEs, $removeACEs); if ($result['status_code'] == 0) { return $result['results'];