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,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,8 +20,28 @@ $NavigationService->startSession($username, $password); | ||
| 20 | $repositories = $RepositoryService->getRepositories(); | 20 | $repositories = $RepositoryService->getRepositories(); |
| 21 | $repositoryId = $repositories[0]['repositoryId']; | 21 | $repositoryId = $repositories[0]['repositoryId']; |
| 22 | 22 | ||
| 23 | +$checkedout = $NavigationService->getCheckedoutDocs($repositoryId); | ||
| 24 | + | ||
| 23 | $feed = new KTCMISAPPFeed(KT_APP_BASE_URI, 'Checked out Documents', null, null, null, 'urn:uuid:checkedout'); | 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 | $entry = null; | 45 | $entry = null; |
| 26 | $feed->newField('hasMoreItems', 'false', $entry, true); | 46 | $feed->newField('hasMoreItems', 'false', $entry, true); |
| 27 | 47 |
ktatompub/services/cmis/folder.inc.php
| @@ -444,6 +444,7 @@ class CMISFolderFeed extends CMISObjectFeed { | @@ -444,6 +444,7 @@ class CMISFolderFeed extends CMISObjectFeed { | ||
| 444 | // <cmis:hasMoreItems>false</cmis:hasMoreItems> | 444 | // <cmis:hasMoreItems>false</cmis:hasMoreItems> |
| 445 | 445 | ||
| 446 | $output = $feed->getAPPdoc(); | 446 | $output = $feed->getAPPdoc(); |
| 447 | + | ||
| 447 | $outputs = '<?xml version="1.0" encoding="UTF-8"?> | 448 | $outputs = '<?xml version="1.0" encoding="UTF-8"?> |
| 448 | <feed xmlns="http://www.w3.org/2005/Atom" xmlns:cmis="http://www.cmis.org/2008/05"> | 449 | <feed xmlns="http://www.w3.org/2005/Atom" xmlns:cmis="http://www.cmis.org/2008/05"> |
| 449 | <entry> | 450 | <entry> |
lib/api/ktcmis/classes/CMISPropertyCollection.inc.php
| @@ -54,8 +54,6 @@ abstract class CMISPropertyCollection { | @@ -54,8 +54,6 @@ abstract class CMISPropertyCollection { | ||
| 54 | static $LastModifiedBy; | 54 | static $LastModifiedBy; |
| 55 | static $LastModificationDate; | 55 | static $LastModificationDate; |
| 56 | static $ChangeToken; | 56 | static $ChangeToken; |
| 57 | - static $ContentStreamLength; | ||
| 58 | - static $ContentStreamMimeType; | ||
| 59 | // TODO these definitions probably belong elsewhere, but here will do for now | 57 | // TODO these definitions probably belong elsewhere, but here will do for now |
| 60 | static $propertyTypes; | 58 | static $propertyTypes; |
| 61 | 59 |
lib/api/ktcmis/classes/CMISRepository.inc.php
| @@ -167,44 +167,6 @@ class CMISRepository { | @@ -167,44 +167,6 @@ class CMISRepository { | ||
| 167 | return $this->objectTypes; | 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,7 +85,7 @@ class KTCMISBase { | ||
| 85 | return $this->session; | 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,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 | return array ( | 157 | return array ( |
| 158 | "status_code" => 0, | 158 | "status_code" => 0, |
| 159 | "results" => CMISUtil::objectToArray($repositoryInfo) | 159 | "results" => CMISUtil::objectToArray($repositoryInfo) |
| @@ -168,13 +168,15 @@ class KTRepositoryService extends KTCMISBase { | @@ -168,13 +168,15 @@ class KTRepositoryService extends KTCMISBase { | ||
| 168 | public function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, | 168 | public function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, |
| 169 | $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) | 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 | return array( | 177 | return array( |
| 176 | "status_code" => 1, | 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,13 +204,14 @@ class KTRepositoryService extends KTCMISBase { | ||
| 202 | */ | 204 | */ |
| 203 | public function getTypeDefinition($repositoryId, $typeId) | 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 | return array( | 212 | return array( |
| 210 | "status_code" => 1, | 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,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,13 +447,15 @@ class KTObjectService extends KTCMISBase { | ||
| 415 | public function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, | 447 | public function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, |
| 416 | $returnVersion = false, $filter = '') | 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 | return array( | 456 | return array( |
| 423 | "status_code" => 1, | 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,13 +480,14 @@ class KTObjectService extends KTCMISBase { | ||
| 446 | { | 480 | { |
| 447 | $objectId = null; | 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 | return array( | 488 | return array( |
| 454 | "status_code" => 1, | 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,7 +54,7 @@ class CMISDocumentObject extends CMISBaseObject { | ||
| 54 | private $uri; | 54 | private $uri; |
| 55 | 55 | ||
| 56 | // TODO some of this should probably come from configuration files as it is repository specific | 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 | $this->ktapi = $ktapi; | 59 | $this->ktapi = $ktapi; |
| 60 | // uri to use for document links | 60 | // uri to use for document links |
| @@ -92,12 +92,16 @@ class CMISDocumentObject extends CMISBaseObject { | @@ -92,12 +92,16 @@ class CMISDocumentObject extends CMISBaseObject { | ||
| 92 | // parent::__construct(); | 92 | // parent::__construct(); |
| 93 | 93 | ||
| 94 | // set document specific property definitions | 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 | // error? | 106 | // error? |
| 103 | if (PEAR::isError($object)) | 107 | if (PEAR::isError($object)) |
lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php
| @@ -49,7 +49,7 @@ class CMISFolderObject extends CMISBaseObject { | @@ -49,7 +49,7 @@ class CMISFolderObject extends CMISBaseObject { | ||
| 49 | var $ktapi; | 49 | var $ktapi; |
| 50 | var $uri; | 50 | var $uri; |
| 51 | 51 | ||
| 52 | - function CMISFolderObject(&$ktapi = null, $uri = null) | 52 | + function __construct($folderId = null, &$ktapi = null, $uri = null) |
| 53 | { | 53 | { |
| 54 | $this->ktapi = $ktapi; | 54 | $this->ktapi = $ktapi; |
| 55 | $this->uri = $uri; | 55 | $this->uri = $uri; |
| @@ -69,11 +69,16 @@ class CMISFolderObject extends CMISBaseObject { | @@ -69,11 +69,16 @@ class CMISFolderObject extends CMISBaseObject { | ||
| 69 | 69 | ||
| 70 | // properties | 70 | // properties |
| 71 | $this->properties = new CMISFolderPropertyCollection(); | 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 | // error? | 83 | // error? |
| 79 | if (PEAR::isError($object)) | 84 | if (PEAR::isError($object)) |
lib/api/ktcmis/services/CMISNavigationService.inc.php
| @@ -40,7 +40,6 @@ | @@ -40,7 +40,6 @@ | ||
| 40 | * @version Version 0.1 | 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 | require_once(KT_DIR . '/ktapi/ktapi.inc.php'); | 43 | require_once(KT_DIR . '/ktapi/ktapi.inc.php'); |
| 45 | require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); | 44 | require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); |
| 46 | 45 | ||
| @@ -75,7 +74,6 @@ class CMISNavigationService { | @@ -75,7 +74,6 @@ class CMISNavigationService { | ||
| 75 | // NOTE If the Repository supports the optional “VersionSpecificFiling” capability, | 74 | // NOTE If the Repository supports the optional “VersionSpecificFiling” capability, |
| 76 | // then the repository SHALL return the document versions filed in the specified folder or its descendant folders. | 75 | // then the repository SHALL return the document versions filed in the specified folder or its descendant folders. |
| 77 | // Otherwise, the latest version of the documents SHALL be returned. | 76 | // Otherwise, the latest version of the documents SHALL be returned. |
| 78 | - | ||
| 79 | // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid | 77 | // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid |
| 80 | function getDescendants($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, | 78 | function getDescendants($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, |
| 81 | $depth = 1, $typeId = 'Any', $filter = '') | 79 | $depth = 1, $typeId = 'Any', $filter = '') |
| @@ -156,8 +154,8 @@ class CMISNavigationService { | @@ -156,8 +154,8 @@ class CMISNavigationService { | ||
| 156 | * @return array $ancestry | 154 | * @return array $ancestry |
| 157 | */ | 155 | */ |
| 158 | // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid | 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 | // NOTE SHOULD always include the “ObjectId” and “ParentId” properties for all objects returned | 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 | function getFolderParent($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, $returnToRoot, $filter = '') | 159 | function getFolderParent($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, $returnToRoot, $filter = '') |
| 162 | { | 160 | { |
| 163 | $ancestry = array(); | 161 | $ancestry = array(); |
| @@ -217,7 +215,7 @@ class CMISNavigationService { | @@ -217,7 +215,7 @@ class CMISNavigationService { | ||
| 217 | * @return array $parents | 215 | * @return array $parents |
| 218 | */ | 216 | */ |
| 219 | // TODO ConstraintViolationException: The Repository SHALL throw this exception if this method is invoked | 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 | // FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid. | 219 | // FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid. |
| 222 | function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') | 220 | function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') |
| 223 | { | 221 | { |
| @@ -245,6 +243,26 @@ class CMISNavigationService { | @@ -245,6 +243,26 @@ class CMISNavigationService { | ||
| 245 | return $ancestry; | 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 | <?php | 1 | <?php |
| 2 | 2 | ||
| 3 | -// really wanted to keep KT code out of here but I don't see how | ||
| 4 | require_once(KT_DIR . '/ktapi/ktapi.inc.php'); | 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 | require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php'); | 8 | require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php'); |
| 6 | require_once(CMIS_DIR . '/objecttypes/CMISFolderObject.inc.php'); | 9 | require_once(CMIS_DIR . '/objecttypes/CMISFolderObject.inc.php'); |
| 7 | require_once(CMIS_DIR . '/classes/CMISRepository.inc.php'); | 10 | require_once(CMIS_DIR . '/classes/CMISRepository.inc.php'); |
| @@ -44,17 +47,21 @@ class CMISObjectService { | @@ -44,17 +47,21 @@ class CMISObjectService { | ||
| 44 | 47 | ||
| 45 | $typeId = CMISUtil::decodeObjectId($objectId); | 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 | switch($typeId) | 55 | switch($typeId) |
| 48 | { | 56 | { |
| 49 | case 'Document': | 57 | case 'Document': |
| 50 | - $CMISObject = new CMISDocumentObject($this->ktapi, $repository->getRepositoryURI()); | 58 | + $CMISObject = new CMISDocumentObject($objectId, $this->ktapi, $repository->getRepositoryURI()); |
| 51 | break; | 59 | break; |
| 52 | case 'Folder': | 60 | case 'Folder': |
| 53 | - $CMISObject = new CMISFolderObject($this->ktapi, $repository->getRepositoryURI()); | 61 | + $CMISObject = new CMISFolderObject($objectId, $this->ktapi, $repository->getRepositoryURI()); |
| 54 | break; | 62 | break; |
| 55 | } | 63 | } |
| 56 | 64 | ||
| 57 | - $CMISObject->get($objectId); | ||
| 58 | $properties = $CMISObject->getProperties(); | 65 | $properties = $CMISObject->getProperties(); |
| 59 | 66 | ||
| 60 | return $properties; | 67 | return $properties; |
| @@ -70,14 +77,24 @@ class CMISObjectService { | @@ -70,14 +77,24 @@ class CMISObjectService { | ||
| 70 | * @return string $objectId The id of the created folder object | 77 | * @return string $objectId The id of the created folder object |
| 71 | */ | 78 | */ |
| 72 | // TODO throw ConstraintViolationException if: | 79 | // TODO throw ConstraintViolationException if: |
| 73 | - // typeID is not an Object-Type whose baseType is “Folder”. | ||
| 74 | // value of any of the properties violates the min/max/required/length constraints | 80 | // value of any of the properties violates the min/max/required/length constraints |
| 75 | // specified in the property definition in the Object-Type. | 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 | function createFolder($repositoryId, $typeId, $properties, $folderId) | 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 | // TODO determine whether this is in fact necessary or if we should require decoding in the calling code | 99 | // TODO determine whether this is in fact necessary or if we should require decoding in the calling code |
| 83 | // Attempt to decode $folderId, use as is if not detected as encoded | 100 | // Attempt to decode $folderId, use as is if not detected as encoded |
| @@ -85,11 +102,21 @@ class CMISObjectService { | @@ -85,11 +102,21 @@ class CMISObjectService { | ||
| 85 | $tmpTypeId = CMISUtil::decodeObjectId($objectId); | 102 | $tmpTypeId = CMISUtil::decodeObjectId($objectId); |
| 86 | if ($tmpTypeId != 'Unknown') | 103 | if ($tmpTypeId != 'Unknown') |
| 87 | $folderId = $objectId; | 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 | $response = $this->ktapi->create_folder($folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = ''); | 115 | $response = $this->ktapi->create_folder($folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = ''); |
| 90 | if ($response['status_code'] != 0) | 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 | else | 121 | else |
| 95 | { | 122 | { |
lib/api/ktcmis/services/CMISRepositoryService.inc.php
| @@ -43,6 +43,7 @@ | @@ -43,6 +43,7 @@ | ||
| 43 | 43 | ||
| 44 | require_once(CMIS_DIR . '/classes/CMISRepository.inc.php'); | 44 | require_once(CMIS_DIR . '/classes/CMISRepository.inc.php'); |
| 45 | require_once(CMIS_DIR . '/classes/CMISObjectTypes.inc.php'); | 45 | require_once(CMIS_DIR . '/classes/CMISObjectTypes.inc.php'); |
| 46 | +require_once(CMIS_DIR . '/exceptions/InvalidArgumentException.inc.php'); | ||
| 46 | 47 | ||
| 47 | /** | 48 | /** |
| 48 | * CMIS Repository Service. | 49 | * CMIS Repository Service. |
| @@ -98,10 +99,21 @@ class CMISRepositoryService { | @@ -98,10 +99,21 @@ class CMISRepositoryService { | ||
| 98 | * @return array $objectTypes | 99 | * @return array $objectTypes |
| 99 | */ | 100 | */ |
| 100 | // NOTE this code may fit better within the Repository Class | 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 | function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, | 104 | function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, |
| 102 | $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) | 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 | $repository = new CMISRepository($repositoryId); | 118 | $repository = new CMISRepository($repositoryId); |
| 107 | $supportedTypes = $repository->getTypes(); | 119 | $supportedTypes = $repository->getTypes(); |
| @@ -140,15 +152,24 @@ class CMISRepositoryService { | @@ -140,15 +152,24 @@ class CMISRepositoryService { | ||
| 140 | * @param string $typeId The ID of the object type requested | 152 | * @param string $typeId The ID of the object type requested |
| 141 | * @return $array $typeDefinition | 153 | * @return $array $typeDefinition |
| 142 | */ | 154 | */ |
| 155 | + // NOTE this code may fit better in the Repository Class | ||
| 143 | function getTypeDefinition($repositoryId, $typeId) | 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 | $typeDefinition = array(); | 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 | return $typeDefinition; | 174 | return $typeDefinition; |
| 154 | } | 175 | } |
lib/api/ktcmis/util/CMISUtil.inc.php
| @@ -133,14 +133,13 @@ class CMISUtil { | @@ -133,14 +133,13 @@ class CMISUtil { | ||
| 133 | switch($object['item_type']) | 133 | switch($object['item_type']) |
| 134 | { | 134 | { |
| 135 | case 'D': | 135 | case 'D': |
| 136 | - $CMISObject = new CMISDocumentObject($ktapi, $repositoryURI); | 136 | + $CMISObject = new CMISDocumentObject($object['id'], $ktapi, $repositoryURI); |
| 137 | break; | 137 | break; |
| 138 | case 'F': | 138 | case 'F': |
| 139 | - $CMISObject = new CMISFolderObject($ktapi, $repositoryURI); | 139 | + $CMISObject = new CMISFolderObject($object['id'], $ktapi, $repositoryURI); |
| 140 | break; | 140 | break; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | - $CMISObject->get($object['id']); | ||
| 144 | $CMISArray[$count]['object'] = $CMISObject; | 143 | $CMISArray[$count]['object'] = $CMISObject; |
| 145 | 144 | ||
| 146 | // if sub-array | 145 | // if sub-array |
| @@ -184,8 +183,7 @@ class CMISUtil { | @@ -184,8 +183,7 @@ class CMISUtil { | ||
| 184 | 183 | ||
| 185 | if (isset($detail['id'])) | 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 | $CMISElement['object'] = $CMISObject; | 187 | $CMISElement['object'] = $CMISObject; |
| 190 | 188 | ||
| 191 | // if more parent elements | 189 | // if more parent elements |
tests/ktcmis/testCmisApi.php
| @@ -7,6 +7,7 @@ require_once (KT_LIB_DIR . '/api/ktcmis/ktcmis.inc.php'); | @@ -7,6 +7,7 @@ require_once (KT_LIB_DIR . '/api/ktcmis/ktcmis.inc.php'); | ||
| 7 | define (KT_TEST_USER, 'admin'); | 7 | define (KT_TEST_USER, 'admin'); |
| 8 | define (KT_TEST_PASS, 'admin'); | 8 | define (KT_TEST_PASS, 'admin'); |
| 9 | 9 | ||
| 10 | +// set to true to print out results | ||
| 10 | define (DEBUG_CMIS, false); | 11 | define (DEBUG_CMIS, false); |
| 11 | 12 | ||
| 12 | /** | 13 | /** |
| @@ -339,15 +340,23 @@ class CMISTestCase extends KTUnitTestCase { | @@ -339,15 +340,23 @@ class CMISTestCase extends KTUnitTestCase { | ||
| 339 | // TODO test invalid type | 340 | // TODO test invalid type |
| 340 | // TODO test invalid parent folder | 341 | // TODO test invalid parent folder |
| 341 | // TODO other invalid parameters | 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 | $this->assertNotNull($created['results']); | 344 | $this->assertNotNull($created['results']); |
| 344 | 345 | ||
| 345 | - // delete created folder | ||
| 346 | if (!is_null($created['results'])) | 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 | // tear down the folder/doc tree structure with which we were testing | 362 | // tear down the folder/doc tree structure with which we were testing |