diff --git a/lib/api/ktcmis/ktObjectService.inc.php b/lib/api/ktcmis/ktObjectService.inc.php index d6d6750..c0a72ab 100644 --- a/lib/api/ktcmis/ktObjectService.inc.php +++ b/lib/api/ktcmis/ktObjectService.inc.php @@ -123,13 +123,13 @@ class KTObjectService extends KTCMISBase { * @param $removeACEs List of ACEs that MUST be removed * @return string $objectId The id of the created folder object */ - public function createDocument($repositoryId, $properties, $folderId = null, $contentStream = null, $versioningState = null, + public function createDocument($repositoryId, $properties, $folderId = null, $contentStream = null, $versioningState = 'none', $policies = array(), $addACEs = array(), $removeACEs = array()) { $objectId = null; try { - $objectId = $this->ObjectService->createDocument($repositoryId, $typeId, $properties, $folderId, $contentStream, + $objectId = $this->ObjectService->createDocument($repositoryId, $properties, $folderId, $contentStream, $versioningState,$policies, $addACEs, $removeACEs); } catch (Exception $e) diff --git a/lib/api/ktcmis/services/CMISObjectService.inc.php b/lib/api/ktcmis/services/CMISObjectService.inc.php index 9124682..e99b16e 100644 --- a/lib/api/ktcmis/services/CMISObjectService.inc.php +++ b/lib/api/ktcmis/services/CMISObjectService.inc.php @@ -50,8 +50,12 @@ class CMISObjectService { // 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 + // TODO support submission of content stream as an array containing mimetype and stream; + // for now we just filter on the other side so that only the stream comes through + // and continue to check the mime type dynamically (may need that anyway if none specified + // by CMIS client) public function createDocument($repositoryId, $properties, $folderId = null, $contentStream = null, - $versioningState = null, $policies = array(), $addACEs = array(), + $versioningState = 'none', $policies = array(), $addACEs = array(), $removeACEs = array()) { $objectId = null; @@ -164,7 +168,7 @@ class CMISObjectService { if (!$typeDefinition['attributes']['contentStreamAllowed']) { throw new StreamNotSupportedException('Content streams are not supported by this object-type'); } - + $tempfilename = CMISUtil::createTemporaryFile($contentStream); // metadata diff --git a/lib/api/ktcmis/services/CMISRepositoryService.inc.php b/lib/api/ktcmis/services/CMISRepositoryService.inc.php index 8393a4a..9f0f15c 100644 --- a/lib/api/ktcmis/services/CMISRepositoryService.inc.php +++ b/lib/api/ktcmis/services/CMISRepositoryService.inc.php @@ -160,6 +160,7 @@ class CMISRepositoryService { // NOTE this code may fit better in the Repository Class function getTypeDefinition($repositoryId, $typeId) { + $typeId = ucwords(str_replace('cmis:', '', $typeId)); $object = 'CMIS' . $typeId . 'Object'; // check whether the object type exists, return error if not @@ -173,7 +174,7 @@ class CMISRepositoryService { require_once(CMIS_DIR . '/objecttypes/' . $object . '.inc.php'); $cmisObject = new $object; - //$typeDefinition['attributes'] = $cmisObject->getAttributes(); + $typeDefinition['attributes'] = $cmisObject->getAttributes(); $typeDefinition['properties'] = $cmisObject->getProperties(); return $typeDefinition; 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 ecfa3f7..e7d8562 100644 --- a/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php +++ b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php @@ -131,7 +131,7 @@ 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 @@ -140,8 +140,8 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { $typeId = null; $folderId = $this->params[0]; - $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title'); - $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary'); + $title = KT_cmis_atom_service_helper::getAtomValues($this->rawContent, 'title'); + $summary = KT_cmis_atom_service_helper::getAtomValues($this->rawContent, '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 @@ -157,14 +157,14 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { $objectId = $this->params[2]; } - $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']); - $properties = array('name' => $title, 'summary' => $summary, 'typeId' => $cmisObjectProperties['objectTypeId']); + $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($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['objectId'])) + if (!empty($cmisObjectProperties['cmis:objectId'])) { $action = 'move'; - $objectId = $cmisObjectProperties['objectId']; + $objectId = $cmisObjectProperties['cmis:objectId']; } // TODO there may be more to do for the checking of an existing object. @@ -174,53 +174,61 @@ 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, $cmisObjectProperties['objectTypeId']); + CMISUtil::decodeObjectId($objectId, $cmisObjectProperties['cmis:objectTypeId']); } // check for content stream - $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 need to change somewhat once other object-types come into play. - if ((($action == 'create') && (is_null($content))) || ($cmisObjectProperties['objectTypeId'] == 'cmis:folder')) { - $type = 'folder'; - } - else { - $type = 'document'; - } + $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)); $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt()); - + + global $default; $success = false; $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); + // TODO detection and passing of optional parameters (policies, ACEs, etc...) as well as support for other object-types + if ($cmisObjectProperties['cmis:objectTypeId'] == 'folder') + $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['cmis: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, $cmisObjectProperties['objectTypeId']); - if ($typeId != 'Unknown') $success = true; - else $error = $newObjectId['message']; + // NOTE for the moment only creation in minor versioning state + $newObjectId = $ObjectService->createDocument($repositoryId, $properties, $folderId, $cmisContent, 'minor'); + + if (!PEAR::isError($newObjectId)) { + // check if returned Object Id is a valid CMIS Object Id + CMISUtil::decodeObjectId($newObjectId, $cmisObjectProperties['cmis:objectTypeId']); + if ($typeId != 'Unknown') { + $success = true; + } + else { + $error = 'Unknown Object Type'; + } + } + else { + $error = $newObjectId->getMessage(); + } } else if ($action == 'move') { $response = $ObjectService->moveObject($repositoryId, $objectId, '', $folderId); - if (!PEAR::isError($response)) $success = true; - else $error = $response->getMessage(); + if (!PEAR::isError($response)) { + $success = true; + } + else { + $error = $response->getMessage(); + } // same object as before $newObjectId = $objectId; - $typeId = ucwords($type); + // FIXME why set this? it does not appear to get used + $typeId = ucwords($cmisObjectProperties['cmis:objectTypeId']); } if ($success) @@ -510,7 +518,7 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { // NOTE this is a hack! will not work with CMISSpaces at least, probably not with any client except RestTest and similar // where we can manually modify the input // first we try for an atom content tag - $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content'); + $content = KT_cmis_atom_service_helper::getAtomValues($this->rawContent, 'content'); if (!empty($content)) { $contentStream = $content; } @@ -625,10 +633,10 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { $VersioningService = new VersioningService(KT_cmis_atom_service_helper::getKt()); $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt()); - $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']); + $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->rawContent); // check for existing object id as property of submitted object data - if (empty($cmisObjectProperties['objectId'])) + if (empty($cmisObjectProperties['cmis:objectId'])) { $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, 'No object was specified for checkout'); // Expose the responseFeed @@ -636,7 +644,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { return null; } - $response = $VersioningService->checkOut($repositoryId, $cmisObjectProperties['objectId']); + $response = $VersioningService->checkOut($repositoryId, $cmisObjectProperties['cmis:objectId']); if (PEAR::isError($response)) { @@ -647,7 +655,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { } $this->setStatus(self::STATUS_CREATED); - $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['objectId'], 'POST'); + $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['cmis:objectId'], 'POST'); // 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 d351dcf..4373f61 100644 --- a/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php +++ b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php @@ -466,8 +466,97 @@ class KT_cmis_atom_service_helper { return CMISUtil::encodeObjectId(FOLDER, $folderId); } + + static public function getCmisProperties(&$xml) + { + $xmlReader = new XMLReader(); + $xmlReader->XML($xml); + $object = false; + $objectProperties = false; + $cmisObjectProperty = null; + $cmisObjectPropertiesCollection = array(); + while ($xmlReader->read()) { + // get cmis object properties + if ($xmlReader->name == 'cmisra:object') { + $object = ($xmlReader->nodeType == XMLReader::ELEMENT); + // exit if we have finished reading the cmis object node + if (!$object) { + break; + } + } + else if ($object && ($xmlReader->name == 'cmis:properties')) { + $objectProperties = ($xmlReader->nodeType == XMLReader::ELEMENT); + } + else if ($objectProperties && ($xmlReader->nodeType == XMLReader::ELEMENT)) { + if (strstr($xmlReader->name, 'cmis:property') && $xmlReader->nodeType == XMLReader::ELEMENT) { + $cmisObjectProperty = $xmlReader->getAttribute('propertyDefinitionId'); + } + else if ($xmlReader->name == 'cmis:value' && $xmlReader->nodeType == XMLReader::ELEMENT) { + // push to next read, which will be the text contained within the node + $xmlReader->read(); + $cmisObjectPropertiesCollection[$cmisObjectProperty] = $xmlReader->value; + // reset for next value - may leave this out of final code + $cmisObjectProperty = null; + } + } + } + + return $cmisObjectPropertiesCollection; + } + + static public function getCmisContent(&$xml) + { + $xmlReader = new XMLReader(); + $xmlReader->XML($xml); + $content = false; + $cmisContentProperty = null; + $cmisObjectContent = array(); + while ($xmlReader->read()) { + if ($xmlReader->name == 'cmisra:content') { + $content = ($xmlReader->nodeType == XMLReader::ELEMENT); + // exit if we have finished reading the cmis content node + if (!$content) { + break; + } + } + else if ($content && ($xmlReader->nodeType == XMLReader::ELEMENT)) { + $cmisContentProperty = $xmlReader->name; + // push to next read, which will be the text contained within the node + $xmlReader->read(); + $cmisObjectContent[$cmisContentProperty] = $xmlReader->value; + } + } + + return $cmisObjectContent; + } + + static public function getAtomValues(&$xml, $tag) + { + $returnTag = null; + + $xmlReader = new XMLReader(); + $xmlReader->XML($xml); + $foundTag = false; + while ($xmlReader->read()) { + // using strstr because we may or may not have the tag preceded by "atom:" + // TODO ensure that this does not return incorrect matches + if (strstr($xmlReader->name, $tag)) { + $foundTag = ($xmlReader->nodeType == XMLReader::ELEMENT); + // exit if we have finished reading the cmis content node + if ($foundTag) { + $xmlReader->read(); + $returnTag = $xmlReader->value; + } + else { + break; + } + } + } + + return $returnTag; + } - static public function getCmisProperties($xmlArray) + static public function getCmisPropertiesOld($xmlArray) { $properties = array(); @@ -500,7 +589,7 @@ class KT_cmis_atom_service_helper { return $properties; } - static public function getAtomValues($xmlArray, $tag) + static public function getAtomValuesOld($xmlArray, $tag) { if (!is_null($xmlArray['atom:'.$tag])) return $xmlArray['atom:'.$tag][0]['@value']; diff --git a/webservice/classes/atompub/KT_atom_service.inc.php b/webservice/classes/atompub/KT_atom_service.inc.php index c20f178..4f095a3 100644 --- a/webservice/classes/atompub/KT_atom_service.inc.php +++ b/webservice/classes/atompub/KT_atom_service.inc.php @@ -68,12 +68,14 @@ class KT_atom_service{ public $parsedXMLContent=''; public $headers=array(); - public function __construct($method,$params,$content){ + public function __construct($method,$params,$content,$parse = true){ $this->method=$method; $this->params=$params; $this->rawContent=$content; $this->parseHeaders(); - $this->parsedXMLContent=$this->xml2array($this->rawContent); + if ($parse) { + $this->parsedXMLContent=$this->xml2array($this->rawContent); + } $this->setStatus(self::STATUS_OK); $this->responseFeed=new KT_atom_responseFeed(KT_APP_BASE_URI); switch(strtoupper($this->method)){ diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php index 2b1760d..1ae6fc8 100644 --- a/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php +++ b/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php @@ -9,6 +9,15 @@ class KT_cmis_atom_service extends KT_atom_service { protected $serviceType = null; protected $contentDownload = false; + public function __construct($method, $params, $content) + { + // We are not going to use the parsed xml content, but rather the raw content; + // This is due to changes in the CMIS spec more than once requiring a change in + // the functions which fetch information from the parsed content; using XMLReader + // now which should be able to handle changes easier + parent::__construct($method, $params, $content, false); + } + public function setContentDownload($contentDownload) { $this->contentDownload = $contentDownload; diff --git a/webservice/classes/atompub/cmis/ObjectService.inc.php b/webservice/classes/atompub/cmis/ObjectService.inc.php index 7528884..7a4e46d 100644 --- a/webservice/classes/atompub/cmis/ObjectService.inc.php +++ b/webservice/classes/atompub/cmis/ObjectService.inc.php @@ -48,21 +48,18 @@ class ObjectService extends KTObjectService { * @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, $properties, $folderId = null, $contentStream = null, - $versioningState = null, $policies = array(), $addACEs = array(), + $versioningState = 'none', $policies = array(), $addACEs = array(), $removeACEs = array()) { $result = parent::createDocument($repositoryId, $properties, $folderId, $contentStream, $versioningState, $policies, $addACEs, $removeACEs); - + if ($result['status_code'] == 0) { return $result['results']; } else { - return $result; + return new PEAR_Error($result['message']); } } @@ -83,7 +80,7 @@ class ObjectService extends KTObjectService { return $result['results']; } else { - return $result; + return new PEAR_Error($result['message']); } } @@ -102,7 +99,7 @@ class ObjectService extends KTObjectService { return $result['results']; } else { - return new PEAR_Error($result['message']); + return new PEAR_Error($result['message']); } }