Commit 834f8d17e9eafc10fa964bc693b4aa584961a1c6
1 parent
6a1d367a
Added some CMIS exception classes. Used these exceptions in the createFolder fu…
…nction and a few other places according to the specification. Modified ktcmis interface to check for exceptions in appropriate cases. Extended Unit Tests for CMIS to double check folder creation instead of relying on initial output of createFolder function. Cleaned up some comments and unnecessary code in CMIS classes. Additional framework code for CMIS checkedout functionality Committed by: Paul Barrett
Showing
17 changed files
with
241 additions
and
95 deletions
ktatompub/services/cmis/NavigationService.inc.php
| ... | ... | @@ -99,6 +99,26 @@ class NavigationService extends KTNavigationService { |
| 99 | 99 | } |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | + /** | |
| 103 | + * Returns a list of checked out documents from the selected repository | |
| 104 | + * | |
| 105 | + * @param string $repositoryId | |
| 106 | + * @param string $folderId The folder for which checked out docs are requested | |
| 107 | + * @param string $filter | |
| 108 | + * @param int $maxItems | |
| 109 | + * @param int $skipCount | |
| 110 | + * @return array $checkedout The collection of checked out documents | |
| 111 | + */ | |
| 112 | + function getCheckedoutDocs($repositoryId, $folderId = null, $filter = '', $maxItems = 0, $skipCount = 0) | |
| 113 | + { | |
| 114 | + $checkedout = parent::getObjectParents($repositoryId, $folderId, $filter, $maxItems, $skipCount); | |
| 115 | + | |
| 116 | + if ($result['status_code'] == 0) | |
| 117 | + { | |
| 118 | + return $result['results']; | |
| 119 | + } | |
| 120 | + } | |
| 121 | + | |
| 102 | 122 | } |
| 103 | 123 | |
| 104 | 124 | ?> | ... | ... |
ktatompub/services/cmis/checkedout.inc.php
| ... | ... | @@ -20,8 +20,28 @@ $NavigationService->startSession($username, $password); |
| 20 | 20 | $repositories = $RepositoryService->getRepositories(); |
| 21 | 21 | $repositoryId = $repositories[0]['repositoryId']; |
| 22 | 22 | |
| 23 | +$checkedout = $NavigationService->getCheckedoutDocs($repositoryId); | |
| 24 | + | |
| 23 | 25 | $feed = new KTCMISAPPFeed(KT_APP_BASE_URI, 'Checked out Documents', null, null, null, 'urn:uuid:checkedout'); |
| 24 | 26 | |
| 27 | +foreach($checkedout as $document) | |
| 28 | +{ | |
| 29 | + $entry = $feed->newEntry(); | |
| 30 | + $objectElement = $feed->newElement('cmis:object'); | |
| 31 | + $propertiesElement = $feed->newElement('cmis:properties'); | |
| 32 | + | |
| 33 | + foreach($cmisEntry['properties'] as $propertyName => $property) | |
| 34 | + { | |
| 35 | + $propElement = $feed->newElement('cmis:' . $property['type']); | |
| 36 | + $propElement->appendChild($feed->newAttr('cmis:name', $propertyName)); | |
| 37 | + $feed->newField('value', CMISUtil::boolToString($property['value']), $propElement); | |
| 38 | + $propertiesElement->appendChild($propElement); | |
| 39 | + } | |
| 40 | + | |
| 41 | + $objectElement->appendChild($propertiesElement); | |
| 42 | + $entry->appendChild($objectElement); | |
| 43 | +} | |
| 44 | + | |
| 25 | 45 | $entry = null; |
| 26 | 46 | $feed->newField('hasMoreItems', 'false', $entry, true); |
| 27 | 47 | ... | ... |
ktatompub/services/cmis/folder.inc.php
| ... | ... | @@ -444,6 +444,7 @@ class CMISFolderFeed extends CMISObjectFeed { |
| 444 | 444 | // <cmis:hasMoreItems>false</cmis:hasMoreItems> |
| 445 | 445 | |
| 446 | 446 | $output = $feed->getAPPdoc(); |
| 447 | + | |
| 447 | 448 | $outputs = '<?xml version="1.0" encoding="UTF-8"?> |
| 448 | 449 | <feed xmlns="http://www.w3.org/2005/Atom" xmlns:cmis="http://www.cmis.org/2008/05"> |
| 449 | 450 | <entry> | ... | ... |
lib/api/ktcmis/classes/CMISPropertyCollection.inc.php
| ... | ... | @@ -54,8 +54,6 @@ abstract class CMISPropertyCollection { |
| 54 | 54 | static $LastModifiedBy; |
| 55 | 55 | static $LastModificationDate; |
| 56 | 56 | static $ChangeToken; |
| 57 | - static $ContentStreamLength; | |
| 58 | - static $ContentStreamMimeType; | |
| 59 | 57 | // TODO these definitions probably belong elsewhere, but here will do for now |
| 60 | 58 | static $propertyTypes; |
| 61 | 59 | ... | ... |
lib/api/ktcmis/classes/CMISRepository.inc.php
| ... | ... | @@ -167,44 +167,6 @@ class CMISRepository { |
| 167 | 167 | return $this->objectTypes; |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | -// // TODO this function MUST accept the same arguments as the calling functions and respond accordingly | |
| 171 | -// // TODO consider moving this into the RepositoryService class: | |
| 172 | -// // anything which requires a repository id seems like it does not belong in the repository class | |
| 173 | -// function getTypes() | |
| 174 | -// { | |
| 175 | -// $objectTypes = $this->objectTypes->getObjectTypes(); | |
| 176 | -// | |
| 177 | -// // fetch the attributes for each type | |
| 178 | -// foreach ($objectTypes as $key => $objectType) | |
| 179 | -// { | |
| 180 | -// $objectTypes[$key] = $this->getTypeDefinition($this->repositoryId, $objectType); | |
| 181 | -// } | |
| 182 | -// | |
| 183 | -// return $objectTypes; | |
| 184 | -// } | |
| 185 | - | |
| 186 | -// // TODO consider moving this into the RepositoryService class: | |
| 187 | -// // anything which requires a repository id seems like it does not belong in the repository class | |
| 188 | -// function getTypeDefinition($repositoryId, $typeId) | |
| 189 | -// { | |
| 190 | -// // TODO is this the best way of doing this? | |
| 191 | -// switch ($typeId) | |
| 192 | -// { | |
| 193 | -// case 'Document': | |
| 194 | -// require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php'); | |
| 195 | -// $tmpObject = new DocumentObject(); | |
| 196 | -// $objectAttributes = $tmpObject->getProperties(); | |
| 197 | -// break; | |
| 198 | -// case 'Folder': | |
| 199 | -// require_once(CMIS_DIR . '/objecttypes/CMISFolderObject.inc.php'); | |
| 200 | -// $tmpObject = new FolderObject(); | |
| 201 | -// $objectAttributes = $tmpObject->getProperties(); | |
| 202 | -// break; | |
| 203 | -// } | |
| 204 | -// | |
| 205 | -// return $objectAttributes; | |
| 206 | -// } | |
| 207 | - | |
| 208 | 170 | } |
| 209 | 171 | |
| 210 | 172 | ?> | ... | ... |
lib/api/ktcmis/exceptions/ConstraintViolationException.inc.php
0 → 100644
lib/api/ktcmis/exceptions/InvalidArgumentException.inc.php
0 → 100644
lib/api/ktcmis/exceptions/ObjectNotFoundException.inc.php
0 → 100644
lib/api/ktcmis/exceptions/StorageException.inc.php
0 → 100644
lib/api/ktcmis/ktcmis.inc.php
| ... | ... | @@ -85,7 +85,7 @@ class KTCMISBase { |
| 85 | 85 | return $this->session; |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | - // TODO what about destroying sessions? | |
| 88 | + // TODO what about destroying sessions? only on logout (which is not offered by the CMIS clients tested so far) | |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | /** |
| ... | ... | @@ -152,8 +152,8 @@ class KTRepositoryService extends KTCMISBase { |
| 152 | 152 | ); |
| 153 | 153 | } |
| 154 | 154 | |
| 155 | - // TODO output this manually, the function works but only for some objects so rather avoid it completely | |
| 156 | - // NOTE the fact that it works for this instance is irrelevant... | |
| 155 | + // TODO output this manually, the function works but only for some objects so rather avoid it completely? | |
| 156 | + // NOTE the problems appear to be due to recursive objects | |
| 157 | 157 | return array ( |
| 158 | 158 | "status_code" => 0, |
| 159 | 159 | "results" => CMISUtil::objectToArray($repositoryInfo) |
| ... | ... | @@ -168,13 +168,15 @@ class KTRepositoryService extends KTCMISBase { |
| 168 | 168 | public function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, |
| 169 | 169 | $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) |
| 170 | 170 | { |
| 171 | - $repositoryObjectTypeResult = $this->RepositoryService->getTypes($repositoryId, $typeId, $returnPropertyDefinitions, | |
| 172 | - $maxItems, $skipCount, $hasMoreItems); | |
| 173 | - if (PEAR::isError($repositoryObjectTypeResult)) | |
| 171 | + try { | |
| 172 | + $repositoryObjectTypeResult = $this->RepositoryService->getTypes($repositoryId, $typeId, $returnPropertyDefinitions, | |
| 173 | + $maxItems, $skipCount, $hasMoreItems); | |
| 174 | + } | |
| 175 | + catch (Exception $e) | |
| 174 | 176 | { |
| 175 | 177 | return array( |
| 176 | 178 | "status_code" => 1, |
| 177 | - "message" => "Failed getting supported object types" | |
| 179 | + "message" => $e->getMessage() | |
| 178 | 180 | ); |
| 179 | 181 | } |
| 180 | 182 | |
| ... | ... | @@ -202,13 +204,14 @@ class KTRepositoryService extends KTCMISBase { |
| 202 | 204 | */ |
| 203 | 205 | public function getTypeDefinition($repositoryId, $typeId) |
| 204 | 206 | { |
| 205 | - $typeDefinitionResult = $this->RepositoryService->getTypeDefinition($repositoryId, $typeId); | |
| 206 | - | |
| 207 | - if (PEAR::isError($typeDefinitionResult)) | |
| 207 | + try { | |
| 208 | + $typeDefinitionResult = $this->RepositoryService->getTypeDefinition($repositoryId, $typeId); | |
| 209 | + } | |
| 210 | + catch (Exception $e) | |
| 208 | 211 | { |
| 209 | 212 | return array( |
| 210 | 213 | "status_code" => 1, |
| 211 | - "message" => "Failed getting object type definition for $typeId" | |
| 214 | + "message" => $e->getMessage() | |
| 212 | 215 | ); |
| 213 | 216 | } |
| 214 | 217 | |
| ... | ... | @@ -380,6 +383,35 @@ class KTNavigationService extends KTCMISBase { |
| 380 | 383 | ); |
| 381 | 384 | } |
| 382 | 385 | |
| 386 | + /** | |
| 387 | + * Returns a list of checked out documents from the selected repository | |
| 388 | + * | |
| 389 | + * @param string $repositoryId | |
| 390 | + * @param string $folderId The folder for which checked out docs are requested | |
| 391 | + * @param string $filter | |
| 392 | + * @param int $maxItems | |
| 393 | + * @param int $skipCount | |
| 394 | + * @return array $checkedout The collection of checked out documents | |
| 395 | + */ | |
| 396 | + function getCheckedoutDocs($repositoryId, $folderId = null, $filter = '', $maxItems = 0, $skipCount = 0) | |
| 397 | + { | |
| 398 | + $checkedout = $this->NavigationService->getObjectParents($repositoryId, $objectId, $includeAllowableActions, | |
| 399 | + $includeRelationships); | |
| 400 | + | |
| 401 | + if (PEAR::isError($ancestryResult)) | |
| 402 | + { | |
| 403 | + return array( | |
| 404 | + "status_code" => 1, | |
| 405 | + "message" => "Failed getting list of checked out documents" | |
| 406 | + ); | |
| 407 | + } | |
| 408 | + | |
| 409 | + return array( | |
| 410 | + "status_code" => 0, | |
| 411 | + "results" => $checkedout | |
| 412 | + ); | |
| 413 | + } | |
| 414 | + | |
| 383 | 415 | } |
| 384 | 416 | |
| 385 | 417 | /** |
| ... | ... | @@ -415,13 +447,15 @@ class KTObjectService extends KTCMISBase { |
| 415 | 447 | public function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, |
| 416 | 448 | $returnVersion = false, $filter = '') |
| 417 | 449 | { |
| 418 | - $propertyCollection = $this->ObjectService->getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships); | |
| 419 | - | |
| 420 | - if (PEAR::isError($propertiesResult)) | |
| 450 | + try { | |
| 451 | + $propertyCollection = $this->ObjectService->getProperties($repositoryId, $objectId, $includeAllowableActions, | |
| 452 | + $includeRelationships); | |
| 453 | + } | |
| 454 | + catch (Exception $e) | |
| 421 | 455 | { |
| 422 | 456 | return array( |
| 423 | 457 | "status_code" => 1, |
| 424 | - "message" => "Failed getting properties for object" | |
| 458 | + "message" => $e->getMessage() | |
| 425 | 459 | ); |
| 426 | 460 | } |
| 427 | 461 | |
| ... | ... | @@ -446,13 +480,14 @@ class KTObjectService extends KTCMISBase { |
| 446 | 480 | { |
| 447 | 481 | $objectId = null; |
| 448 | 482 | |
| 449 | - $objectId = $this->ObjectService->createFolder($repositoryId, $typeId, $properties, $folderId); | |
| 450 | - | |
| 451 | - if (PEAR::isError($propertiesResult)) | |
| 483 | + try { | |
| 484 | + $objectId = $this->ObjectService->createFolder($repositoryId, $typeId, $properties, $folderId); | |
| 485 | + } | |
| 486 | + catch (Exception $e) | |
| 452 | 487 | { |
| 453 | 488 | return array( |
| 454 | 489 | "status_code" => 1, |
| 455 | - "message" => "Failed getting properties for object" | |
| 490 | + "message" => $e->getMessage() | |
| 456 | 491 | ); |
| 457 | 492 | } |
| 458 | 493 | ... | ... |
lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
| ... | ... | @@ -54,7 +54,7 @@ class CMISDocumentObject extends CMISBaseObject { |
| 54 | 54 | private $uri; |
| 55 | 55 | |
| 56 | 56 | // TODO some of this should probably come from configuration files as it is repository specific |
| 57 | - function CMISDocumentObject(&$ktapi = null, $uri = null) | |
| 57 | + function __construct($documentId = null, &$ktapi = null, $uri = null) | |
| 58 | 58 | { |
| 59 | 59 | $this->ktapi = $ktapi; |
| 60 | 60 | // uri to use for document links |
| ... | ... | @@ -92,12 +92,16 @@ class CMISDocumentObject extends CMISBaseObject { |
| 92 | 92 | // parent::__construct(); |
| 93 | 93 | |
| 94 | 94 | // set document specific property definitions |
| 95 | - | |
| 95 | + | |
| 96 | + if (!is_null($documentId)) | |
| 97 | + { | |
| 98 | + $this->_get($documentId); | |
| 99 | + } | |
| 96 | 100 | } |
| 97 | 101 | |
| 98 | - function get($objectId) | |
| 102 | + private function _get($documentId) | |
| 99 | 103 | { |
| 100 | - $object = $this->ktapi->get_document_by_id($objectId); | |
| 104 | + $object = $this->ktapi->get_document_by_id($documentId); | |
| 101 | 105 | |
| 102 | 106 | // error? |
| 103 | 107 | if (PEAR::isError($object)) | ... | ... |
lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php
| ... | ... | @@ -49,7 +49,7 @@ class CMISFolderObject extends CMISBaseObject { |
| 49 | 49 | var $ktapi; |
| 50 | 50 | var $uri; |
| 51 | 51 | |
| 52 | - function CMISFolderObject(&$ktapi = null, $uri = null) | |
| 52 | + function __construct($folderId = null, &$ktapi = null, $uri = null) | |
| 53 | 53 | { |
| 54 | 54 | $this->ktapi = $ktapi; |
| 55 | 55 | $this->uri = $uri; |
| ... | ... | @@ -69,11 +69,16 @@ class CMISFolderObject extends CMISBaseObject { |
| 69 | 69 | |
| 70 | 70 | // properties |
| 71 | 71 | $this->properties = new CMISFolderPropertyCollection(); |
| 72 | + | |
| 73 | + if (!is_null($folderId)) | |
| 74 | + { | |
| 75 | + $this->_get($folderId); | |
| 76 | + } | |
| 72 | 77 | } |
| 73 | 78 | |
| 74 | - function get($objectId) | |
| 79 | + private function _get($folderId) | |
| 75 | 80 | { |
| 76 | - $object = $this->ktapi->get_folder_by_id($objectId); | |
| 81 | + $object = $this->ktapi->get_folder_by_id($folderId); | |
| 77 | 82 | |
| 78 | 83 | // error? |
| 79 | 84 | if (PEAR::isError($object)) | ... | ... |
lib/api/ktcmis/services/CMISNavigationService.inc.php
| ... | ... | @@ -40,7 +40,6 @@ |
| 40 | 40 | * @version Version 0.1 |
| 41 | 41 | */ |
| 42 | 42 | |
| 43 | -// really wanted to keep KT code out of here but I don't see how | |
| 44 | 43 | require_once(KT_DIR . '/ktapi/ktapi.inc.php'); |
| 45 | 44 | require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); |
| 46 | 45 | |
| ... | ... | @@ -75,7 +74,6 @@ class CMISNavigationService { |
| 75 | 74 | // NOTE If the Repository supports the optional “VersionSpecificFiling” capability, |
| 76 | 75 | // then the repository SHALL return the document versions filed in the specified folder or its descendant folders. |
| 77 | 76 | // Otherwise, the latest version of the documents SHALL be returned. |
| 78 | - | |
| 79 | 77 | // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid |
| 80 | 78 | function getDescendants($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, |
| 81 | 79 | $depth = 1, $typeId = 'Any', $filter = '') |
| ... | ... | @@ -156,8 +154,8 @@ class CMISNavigationService { |
| 156 | 154 | * @return array $ancestry |
| 157 | 155 | */ |
| 158 | 156 | // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid |
| 157 | + // TODO If this service method is invoked on the root folder of the Repository, then the Repository SHALL return an empty result set. | |
| 159 | 158 | // NOTE SHOULD always include the “ObjectId” and “ParentId” properties for all objects returned |
| 160 | - // NOTE If this service method is invoked on the root folder of the Repository, then the Repository shall return an empty result set. | |
| 161 | 159 | function getFolderParent($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, $returnToRoot, $filter = '') |
| 162 | 160 | { |
| 163 | 161 | $ancestry = array(); |
| ... | ... | @@ -217,7 +215,7 @@ class CMISNavigationService { |
| 217 | 215 | * @return array $parents |
| 218 | 216 | */ |
| 219 | 217 | // TODO ConstraintViolationException: The Repository SHALL throw this exception if this method is invoked |
| 220 | - // on an object who Object-Type Defintion specifies that it is not fileable. | |
| 218 | + // on an object who Object-Type Definition specifies that it is not fileable. | |
| 221 | 219 | // FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid. |
| 222 | 220 | function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') |
| 223 | 221 | { |
| ... | ... | @@ -245,6 +243,26 @@ class CMISNavigationService { |
| 245 | 243 | return $ancestry; |
| 246 | 244 | } |
| 247 | 245 | |
| 246 | + /** | |
| 247 | + * Returns a list of checked out documents from the selected repository | |
| 248 | + * | |
| 249 | + * @param string $repositoryId | |
| 250 | + * @param string $folderId The folder for which checked out docs are requested | |
| 251 | + * @param string $filter | |
| 252 | + * @param int $maxItems | |
| 253 | + * @param int $skipCount | |
| 254 | + * @return array $checkedout The collection of checked out documents | |
| 255 | + */ | |
| 256 | + // NOTE NOT YET IMPLEMENTED (this function is just a place holder at the moment :)) | |
| 257 | + function getCheckedoutDocs($repositoryId, $folderId = null, $filter = '', $maxItems = 0, $skipCount = 0) | |
| 258 | + { | |
| 259 | + $checkedout = array(); | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + return $checkedout(); | |
| 264 | + } | |
| 265 | + | |
| 248 | 266 | } |
| 249 | 267 | |
| 250 | 268 | ?> | ... | ... |
lib/api/ktcmis/services/CMISObjectService.inc.php
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | -// really wanted to keep KT code out of here but I don't see how | |
| 4 | 3 | require_once(KT_DIR . '/ktapi/ktapi.inc.php'); |
| 4 | +require_once(CMIS_DIR . '/exceptions/ConstraintViolationException.inc.php'); | |
| 5 | +require_once(CMIS_DIR . '/exceptions/ObjectNotFoundException.inc.php'); | |
| 6 | +require_once(CMIS_DIR . '/exceptions/StorageException.inc.php'); | |
| 7 | +require_once(CMIS_DIR . '/services/CMISRepositoryService.inc.php'); | |
| 5 | 8 | require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php'); |
| 6 | 9 | require_once(CMIS_DIR . '/objecttypes/CMISFolderObject.inc.php'); |
| 7 | 10 | require_once(CMIS_DIR . '/classes/CMISRepository.inc.php'); |
| ... | ... | @@ -44,17 +47,21 @@ class CMISObjectService { |
| 44 | 47 | |
| 45 | 48 | $typeId = CMISUtil::decodeObjectId($objectId); |
| 46 | 49 | |
| 50 | + if ($typeId == 'Unknown') | |
| 51 | + { | |
| 52 | + throw new ObjectNotFoundException('The type of the requested object could not be determined'); | |
| 53 | + } | |
| 54 | + | |
| 47 | 55 | switch($typeId) |
| 48 | 56 | { |
| 49 | 57 | case 'Document': |
| 50 | - $CMISObject = new CMISDocumentObject($this->ktapi, $repository->getRepositoryURI()); | |
| 58 | + $CMISObject = new CMISDocumentObject($objectId, $this->ktapi, $repository->getRepositoryURI()); | |
| 51 | 59 | break; |
| 52 | 60 | case 'Folder': |
| 53 | - $CMISObject = new CMISFolderObject($this->ktapi, $repository->getRepositoryURI()); | |
| 61 | + $CMISObject = new CMISFolderObject($objectId, $this->ktapi, $repository->getRepositoryURI()); | |
| 54 | 62 | break; |
| 55 | 63 | } |
| 56 | 64 | |
| 57 | - $CMISObject->get($objectId); | |
| 58 | 65 | $properties = $CMISObject->getProperties(); |
| 59 | 66 | |
| 60 | 67 | return $properties; |
| ... | ... | @@ -70,14 +77,24 @@ class CMISObjectService { |
| 70 | 77 | * @return string $objectId The id of the created folder object |
| 71 | 78 | */ |
| 72 | 79 | // TODO throw ConstraintViolationException if: |
| 73 | - // typeID is not an Object-Type whose baseType is “Folder”. | |
| 74 | 80 | // value of any of the properties violates the min/max/required/length constraints |
| 75 | 81 | // specified in the property definition in the Object-Type. |
| 76 | - // typeID is NOT in the list of AllowedChildObjectTypeIds of the parent-folder specified by folderId | |
| 77 | - // TODO throw storageException under conditions specified in "specific exceptions" section | |
| 78 | 82 | function createFolder($repositoryId, $typeId, $properties, $folderId) |
| 79 | 83 | { |
| 80 | - $objectId = null; | |
| 84 | + // fetch type definition of supplied type and check for base type "folder", if not true throw exception | |
| 85 | + $RepositoryService = new CMISRepositoryService(); | |
| 86 | + try { | |
| 87 | + $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $typeId); | |
| 88 | + } | |
| 89 | + catch (Exception $e) | |
| 90 | + { | |
| 91 | + throw new ConstraintViolationException('Object is not of base type folder.'); | |
| 92 | + } | |
| 93 | + | |
| 94 | + if ($typeDefinition['attributes']['baseType'] != 'folder') | |
| 95 | + { | |
| 96 | + throw new ConstraintViolationException('Object is not of base type folder'); | |
| 97 | + } | |
| 81 | 98 | |
| 82 | 99 | // TODO determine whether this is in fact necessary or if we should require decoding in the calling code |
| 83 | 100 | // Attempt to decode $folderId, use as is if not detected as encoded |
| ... | ... | @@ -85,11 +102,21 @@ class CMISObjectService { |
| 85 | 102 | $tmpTypeId = CMISUtil::decodeObjectId($objectId); |
| 86 | 103 | if ($tmpTypeId != 'Unknown') |
| 87 | 104 | $folderId = $objectId; |
| 105 | + | |
| 106 | + // if parent folder is not allowed to hold this type, throw exception | |
| 107 | + $CMISFolder = new CMISFolderObject($folderId, $this->ktapi); | |
| 108 | + $folderProperties = $CMISFolder->getProperties(); | |
| 109 | + $allowed = $folderProperties->getValue('AllowedChildObjectTypeIds'); | |
| 110 | + if (!is_array($allowed) || !in_array($typeId, $allowed)) | |
| 111 | + { | |
| 112 | + throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')'); | |
| 113 | + } | |
| 88 | 114 | |
| 89 | 115 | $response = $this->ktapi->create_folder($folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = ''); |
| 90 | 116 | if ($response['status_code'] != 0) |
| 91 | 117 | { |
| 92 | - // TODO add some error handling here | |
| 118 | + // throw storageException | |
| 119 | + throw new StorageException('The repository was unable to create the folder - ' . $response['message']); | |
| 93 | 120 | } |
| 94 | 121 | else |
| 95 | 122 | { | ... | ... |
lib/api/ktcmis/services/CMISRepositoryService.inc.php
| ... | ... | @@ -43,6 +43,7 @@ |
| 43 | 43 | |
| 44 | 44 | require_once(CMIS_DIR . '/classes/CMISRepository.inc.php'); |
| 45 | 45 | require_once(CMIS_DIR . '/classes/CMISObjectTypes.inc.php'); |
| 46 | +require_once(CMIS_DIR . '/exceptions/InvalidArgumentException.inc.php'); | |
| 46 | 47 | |
| 47 | 48 | /** |
| 48 | 49 | * CMIS Repository Service. |
| ... | ... | @@ -98,10 +99,21 @@ class CMISRepositoryService { |
| 98 | 99 | * @return array $objectTypes |
| 99 | 100 | */ |
| 100 | 101 | // NOTE this code may fit better within the Repository Class |
| 102 | + // TODO return for specific type when $typeId is specified | |
| 103 | + // TODO other optional parameters | |
| 101 | 104 | function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, |
| 102 | 105 | $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) |
| 103 | 106 | { |
| 104 | - // TODO throw invalidArgumentException if invalid typeId submitted | |
| 107 | + if ($typeId != '') | |
| 108 | + { | |
| 109 | + try { | |
| 110 | + $typeDefinition = $this->getTypeDefinition($repositoryId, $typeId); | |
| 111 | + } | |
| 112 | + catch (Exception $e) | |
| 113 | + { | |
| 114 | + throw new InvalidArgumentException('Type ' . $typeId . ' is not supported'); | |
| 115 | + } | |
| 116 | + } | |
| 105 | 117 | |
| 106 | 118 | $repository = new CMISRepository($repositoryId); |
| 107 | 119 | $supportedTypes = $repository->getTypes(); |
| ... | ... | @@ -140,15 +152,24 @@ class CMISRepositoryService { |
| 140 | 152 | * @param string $typeId The ID of the object type requested |
| 141 | 153 | * @return $array $typeDefinition |
| 142 | 154 | */ |
| 155 | + // NOTE this code may fit better in the Repository Class | |
| 143 | 156 | function getTypeDefinition($repositoryId, $typeId) |
| 144 | 157 | { |
| 158 | + $object = 'CMIS' . $typeId . 'Object'; | |
| 159 | + | |
| 160 | + // check whether the object type exists, return error if not | |
| 161 | + // consider throwing an exception instead (see General Exceptions) | |
| 162 | + if (!file_exists(CMIS_DIR . '/objecttypes/' . $object . '.inc.php')) | |
| 163 | + { | |
| 164 | + throw new InvalidArgumentException('Type ' . $typeId . ' is not supported'); | |
| 165 | + } | |
| 166 | + | |
| 145 | 167 | $typeDefinition = array(); |
| 146 | 168 | |
| 147 | - require_once(CMIS_DIR . '/objecttypes/CMIS' . $typeId . 'Object.inc.php'); | |
| 148 | - $object = 'CMIS' . $typeId . 'Object'; | |
| 149 | - $tmpObject = new $object; | |
| 150 | - $typeDefinition['attributes'] = $tmpObject->getAttributes(); | |
| 151 | - $typeDefinition['properties'] = $tmpObject->getProperties(); | |
| 169 | + require_once(CMIS_DIR . '/objecttypes/' . $object . '.inc.php'); | |
| 170 | + $cmisObject = new $object; | |
| 171 | + $typeDefinition['attributes'] = $cmisObject->getAttributes(); | |
| 172 | + $typeDefinition['properties'] = $cmisObject->getProperties(); | |
| 152 | 173 | |
| 153 | 174 | return $typeDefinition; |
| 154 | 175 | } | ... | ... |
lib/api/ktcmis/util/CMISUtil.inc.php
| ... | ... | @@ -133,14 +133,13 @@ class CMISUtil { |
| 133 | 133 | switch($object['item_type']) |
| 134 | 134 | { |
| 135 | 135 | case 'D': |
| 136 | - $CMISObject = new CMISDocumentObject($ktapi, $repositoryURI); | |
| 136 | + $CMISObject = new CMISDocumentObject($object['id'], $ktapi, $repositoryURI); | |
| 137 | 137 | break; |
| 138 | 138 | case 'F': |
| 139 | - $CMISObject = new CMISFolderObject($ktapi, $repositoryURI); | |
| 139 | + $CMISObject = new CMISFolderObject($object['id'], $ktapi, $repositoryURI); | |
| 140 | 140 | break; |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | - $CMISObject->get($object['id']); | |
| 144 | 143 | $CMISArray[$count]['object'] = $CMISObject; |
| 145 | 144 | |
| 146 | 145 | // if sub-array |
| ... | ... | @@ -184,8 +183,7 @@ class CMISUtil { |
| 184 | 183 | |
| 185 | 184 | if (isset($detail['id'])) |
| 186 | 185 | { |
| 187 | - $CMISObject = new CMISFolderObject($ktapi, $repositoryURI); | |
| 188 | - $CMISObject->get($detail['id']); | |
| 186 | + $CMISObject = new CMISFolderObject($detail['id'], $ktapi, $repositoryURI); | |
| 189 | 187 | $CMISElement['object'] = $CMISObject; |
| 190 | 188 | |
| 191 | 189 | // if more parent elements | ... | ... |
tests/ktcmis/testCmisApi.php
| ... | ... | @@ -7,6 +7,7 @@ require_once (KT_LIB_DIR . '/api/ktcmis/ktcmis.inc.php'); |
| 7 | 7 | define (KT_TEST_USER, 'admin'); |
| 8 | 8 | define (KT_TEST_PASS, 'admin'); |
| 9 | 9 | |
| 10 | +// set to true to print out results | |
| 10 | 11 | define (DEBUG_CMIS, false); |
| 11 | 12 | |
| 12 | 13 | /** |
| ... | ... | @@ -339,15 +340,23 @@ class CMISTestCase extends KTUnitTestCase { |
| 339 | 340 | // TODO test invalid type |
| 340 | 341 | // TODO test invalid parent folder |
| 341 | 342 | // TODO other invalid parameters |
| 342 | - $created = $ObjectService->createFolder($repositoryId, 'Folder', array('name' => 'My Test Folder ' . mt_rand()), 1); | |
| 343 | + $created = $ObjectService->createFolder($repositoryId, 'Folder', array('name' => 'My Test Folder ' . mt_rand()), 'F1'); | |
| 343 | 344 | $this->assertNotNull($created['results']); |
| 344 | 345 | |
| 345 | - // delete created folder | |
| 346 | 346 | if (!is_null($created['results'])) |
| 347 | 347 | { |
| 348 | - $folder_id = $created['results']; | |
| 349 | - CMISUtil::decodeObjectId($folder_id); | |
| 350 | - $this->ktapi->delete_folder($folder_id, 'Testing API', KT_TEST_USER, KT_TEST_PASS); | |
| 348 | + $folderId = $created['results']; | |
| 349 | + | |
| 350 | + // check that folder object actually exists | |
| 351 | + $properties = $ObjectService->getProperties($repositoryId, $folderId, false, false); | |
| 352 | + $this->assertNotNull($properties['results']); | |
| 353 | + | |
| 354 | + // test printout | |
| 355 | + $this->printTable($properties['results'][0], 'Properties for CMIS Created Folder Object ' . $folderId . ' (getProperties())'); | |
| 356 | + | |
| 357 | + // delete | |
| 358 | + CMISUtil::decodeObjectId($folderId); | |
| 359 | + $this->ktapi->delete_folder($folderId, 'Testing API', KT_TEST_USER, KT_TEST_PASS); | |
| 351 | 360 | } |
| 352 | 361 | |
| 353 | 362 | // tear down the folder/doc tree structure with which we were testing | ... | ... |