Commit 2b68ca023d074734c213a81885a23ac5378efc9d

Authored by Paul Barrett
1 parent bf8f7fb7

Story ID: 966930. Added support for move via AtomPub and CMIS

In order to be able to move content using a CMIS client, as a user, I would like KnowledgeTree's CMIS interface to support move

Committed by: Paul Barrett

Reviewed by: Jarrett Jordaan
lib/api/ktcmis/ktcmis.inc.php
@@ -538,7 +538,7 @@ class KTObjectService extends KTCMISBase { @@ -538,7 +538,7 @@ class KTObjectService extends KTCMISBase {
538 * @param string $versioningState optional version state value: checkedout/major/minor 538 * @param string $versioningState optional version state value: checkedout/major/minor
539 * @return string $objectId The id of the created folder object 539 * @return string $objectId The id of the created folder object
540 */ 540 */
541 - function createDocument($repositoryId, $typeId, $properties, $folderId = null, 541 + public function createDocument($repositoryId, $typeId, $properties, $folderId = null,
542 $contentStream = null, $versioningState = null) 542 $contentStream = null, $versioningState = null)
543 { 543 {
544 $objectId = null; 544 $objectId = null;
@@ -570,7 +570,7 @@ class KTObjectService extends KTCMISBase { @@ -570,7 +570,7 @@ class KTObjectService extends KTCMISBase {
570 * @param string $folderId The id of the folder which will be the parent of the created folder object 570 * @param string $folderId The id of the folder which will be the parent of the created folder object
571 * @return string $objectId The id of the created folder object 571 * @return string $objectId The id of the created folder object
572 */ 572 */
573 - function createFolder($repositoryId, $typeId, $properties, $folderId) 573 + public function createFolder($repositoryId, $typeId, $properties, $folderId)
574 { 574 {
575 $objectId = null; 575 $objectId = null;
576 576
@@ -592,6 +592,34 @@ class KTObjectService extends KTCMISBase { @@ -592,6 +592,34 @@ class KTObjectService extends KTCMISBase {
592 } 592 }
593 593
594 /** 594 /**
  595 + * Moves a fileable object from one folder to another.
  596 + *
  597 + * @param object $repositoryId
  598 + * @param object $objectId
  599 + * @param object $changeToken [optional]
  600 + * @param object $targetFolderId
  601 + * @param object $sourceFolderId [optional]
  602 + */
  603 + public function moveObject($repositoryId, $objectId, $changeToken = '', $targetFolderId, $sourceFolderId = null)
  604 + {
  605 + try {
  606 + $this->ObjectService->moveObject($repositoryId, $objectId, $changeToken, $targetFolderId, $sourceFolderId);
  607 + }
  608 + catch (Exception $e)
  609 + {
  610 + return array(
  611 + "status_code" => 1,
  612 + "message" => $e->getMessage()
  613 + );
  614 + }
  615 +
  616 + return array(
  617 + 'status_code' => 0,
  618 + 'results' => $objectId
  619 + );
  620 + }
  621 +
  622 + /**
595 * Deletes an object from the repository 623 * Deletes an object from the repository
596 * 624 *
597 * @param string $repositoryId 625 * @param string $repositoryId
@@ -601,10 +629,10 @@ class KTObjectService extends KTCMISBase { @@ -601,10 +629,10 @@ class KTObjectService extends KTCMISBase {
601 */ 629 */
602 // NOTE Invoking this service method on an object SHALL not delete the entire version series for a Document Object. 630 // NOTE Invoking this service method on an object SHALL not delete the entire version series for a Document Object.
603 // To delete an entire version series, use the deleteAllVersions() service 631 // To delete an entire version series, use the deleteAllVersions() service
604 - function deleteObject($repositoryId, $objectId, $changeToken = null) 632 + public function deleteObject($repositoryId, $objectId, $changeToken = null)
605 { 633 {
606 try { 634 try {
607 - $result = $this->ObjectService->deleteObject($repositoryId, $objectId, $changeToken); 635 + $this->ObjectService->deleteObject($repositoryId, $objectId, $changeToken);
608 } 636 }
609 catch (Exception $e) 637 catch (Exception $e)
610 { 638 {
lib/api/ktcmis/services/CMISObjectService.inc.php
@@ -198,7 +198,7 @@ class CMISObjectService { @@ -198,7 +198,7 @@ class CMISObjectService {
198 { 198 {
199 // TODO consider checking whether content is encoded (currently we expect encoded) 199 // TODO consider checking whether content is encoded (currently we expect encoded)
200 // TODO choose between this and the alternative decode function (see CMISUtil class) 200 // TODO choose between this and the alternative decode function (see CMISUtil class)
201 - // The current one appears to be miles better (1/0/3 vs 14/4/57 on respective test files) 201 + // this will require some basic benchmarking
202 $contentStream = CMISUtil::decodeChunkedContentStream($contentStream); 202 $contentStream = CMISUtil::decodeChunkedContentStream($contentStream);
203 203
204 // NOTE There is a function in CMISUtil to do this, written for the unit tests but since KTUploadManager exists 204 // NOTE There is a function in CMISUtil to do this, written for the unit tests but since KTUploadManager exists
@@ -390,7 +390,7 @@ class CMISObjectService { @@ -390,7 +390,7 @@ class CMISObjectService {
390 $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = ''); 390 $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = '');
391 if ($response['status_code'] != 0) 391 if ($response['status_code'] != 0)
392 { 392 {
393 - throw new StorageException('The repository was unable to create the folder - ' . $response['message']); 393 + throw new StorageException('The repository was unable to create the folder: ' . $response['message']);
394 } 394 }
395 else 395 else
396 { 396 {
@@ -401,6 +401,74 @@ class CMISObjectService { @@ -401,6 +401,74 @@ class CMISObjectService {
401 } 401 }
402 402
403 /** 403 /**
  404 + * Moves a fileable object from one folder to another.
  405 + *
  406 + * @param object $repositoryId
  407 + * @param object $objectId
  408 + * @param object $changeToken [optional]
  409 + * @param object $targetFolderId
  410 + * @param object $sourceFolderId [optional]
  411 + */
  412 + // TODO versioningException: The repository MAY throw this exception if the object is a non-current Document Version.
  413 + // TODO check whether object is in fact fileable? not strictly needed, but possibly should be here.
  414 + public function moveObject($repositoryId, $objectId, $changeToken = '', $targetFolderId, $sourceFolderId = null)
  415 + {
  416 + // The $sourceFolderId parameter SHALL be specified if the Repository supports the optional 'unfiling' capability
  417 + if (is_null($sourceFolderId))
  418 + {
  419 + $RepositoryService = new CMISRepositoryService();
  420 + $info = $RepositoryService->getRepositoryInfo($repositoryId);
  421 + $capabilities = $info->getCapabilities();
  422 + // check for unfiling capability
  423 + // NOTE this is only required once/if KnowledgeTree allows the source folder id to be optional,
  424 + // but it is required for CMIS specification compliance.
  425 + if ($capabilities->hasCapabilityUnfiling() === 'true') {
  426 + throw new RuntimeException('The source folder id MUST be supplied when unfiling is supported.');
  427 + }
  428 + }
  429 +
  430 + // Attempt to decode $objectId, use as is if not detected as encoded
  431 + $tmpObjectId = $objectId;
  432 + $tmpObjectId = CMISUtil::decodeObjectId($tmpObjectId, $typeId);
  433 + if ($tmpTypeId != 'Unknown') $objectId = $tmpObjectId;
  434 +
  435 + $targetFolderId = CMISUtil::decodeObjectId($targetFolderId);
  436 +
  437 + // check type id of object against allowed child types for destination folder
  438 + $CMISFolder = new CMISFolderObject($targetFolderId, $this->ktapi);
  439 + $allowed = $CMISFolder->getProperty('AllowedChildObjectTypeIds');
  440 + if (!is_array($allowed) || !in_array($typeId, $allowed))
  441 + {
  442 + throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')');
  443 + }
  444 +
  445 + // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository).
  446 + $exists = CMISUtil::contentExists($typeId, $objectId, $this->ktapi);
  447 + if (!$exists) {
  448 + throw new updateConflictException('Unable to move the object as it cannot be found.');
  449 + }
  450 +
  451 + // TODO add reasons and sig data
  452 + // attempt to move object
  453 + if ($typeId == 'Folder') {
  454 + $response = $this->ktapi->move_folder($objectId, $targetFolderId, $reason, $sig_username, $sig_password);
  455 + }
  456 + else if ($typeId == 'Document') {
  457 + $response = $this->ktapi->move_document($objectId, $targetFolderId, $reason, null, null, $sig_username, $sig_password);
  458 + }
  459 + else {
  460 + $response['status_code'] = 1;
  461 + $response['message'] = 'The object type could not be determined.';
  462 + }
  463 +
  464 + // if failed, throw StorageException
  465 + if ($response['status_code'] != 0)
  466 + {
  467 + throw new StorageException('The repository was unable to move the object: ' . $response['message']);
  468 + }
  469 + }
  470 +
  471 + /**
404 * Deletes an object from the repository 472 * Deletes an object from the repository
405 * 473 *
406 * @param string $repositoryId 474 * @param string $repositoryId
@@ -415,6 +483,7 @@ class CMISObjectService { @@ -415,6 +483,7 @@ class CMISObjectService {
415 // determine object type and internal id 483 // determine object type and internal id
416 $objectId = CMISUtil::decodeObjectId($objectId, $typeId); 484 $objectId = CMISUtil::decodeObjectId($objectId, $typeId);
417 485
  486 + // TODO this should probably be a function, it is now used in two places...
418 // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository). 487 // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository).
419 $exists = true; 488 $exists = true;
420 if ($typeId == 'Folder') { 489 if ($typeId == 'Folder') {
@@ -428,6 +497,7 @@ class CMISObjectService { @@ -428,6 +497,7 @@ class CMISObjectService {
428 if (PEAR::isError($object)) { 497 if (PEAR::isError($object)) {
429 $exists = false; 498 $exists = false;
430 } 499 }
  500 + // TODO check deleted status?
431 } 501 }
432 else { 502 else {
433 $exists = false; 503 $exists = false;
@@ -482,8 +552,6 @@ class CMISObjectService { @@ -482,8 +552,6 @@ class CMISObjectService {
482 if ($result['status_code'] == 1) { 552 if ($result['status_code'] == 1) {
483 throw new RuntimeException('There was an error deleting the object: ' . $result['message']); 553 throw new RuntimeException('There was an error deleting the object: ' . $result['message']);
484 } 554 }
485 -  
486 - return true;  
487 } 555 }
488 556
489 /** 557 /**
lib/api/ktcmis/util/CMISUtil.inc.php
@@ -397,30 +397,33 @@ class CMISUtil { @@ -397,30 +397,33 @@ class CMISUtil {
397 return $temp; 397 return $temp;
398 } 398 }
399 399
400 - // TODO run evaluations on each of the following two functions and determine which  
401 - // is generally more efficienct  
402 -  
403 /** 400 /**
404 - * Alternative function for decoding chunked streams, this will decode in blocks of 4.  
405 - * Not sure which method is more efficient, this or the function below (this does not  
406 - * re-encode but I am working on removing that step for the other function.) 401 + * Checks the contentStream and ensures that it is a correct base64 string;
  402 + * This is purely for clients such as CMISSpaces breaking the content into
  403 + * chunks before base64 encoding.
  404 + *
  405 + * If the stream is chunked, it is decoded in chunks and sent back as a single stream.
  406 + * If it is not chunked it is decoded as is and sent back as a single stream.
  407 + *
  408 + * NOTE there is an alternative version of this function called decodeChunkedContentStreamLong.
  409 + * that version checks line lengths, which should not be necessary.
  410 + * this version merely splits on one or two "=" which is less complex and possibly faster (test this assumption)
  411 + * (one or two "=" signs is the specified padding used for base64 encoding at the end of an encoded string, when needed)
407 * 412 *
408 - * NOTE The current one appears to be much slower (14/4/57 vs 1/0/3 on respective test files)  
409 - *  
410 - * @param string $contentStream the base64 encoded content stream  
411 - * @return string $decoded the decoded content stream 413 + * @param object $contentStream
  414 + * @return string decoded
412 */ 415 */
413 - static public function decodeContentStream($contentStream) 416 + static public function decodeChunkedContentStream($contentStream)
414 { 417 {
415 $decoded = ''; 418 $decoded = '';
416 419
417 - $contentStream = preg_replace('/\r?\n+/', '', $contentStream);  
418 -  
419 - // decode in chunks or 4 chars at a time  
420 - for($i = 0, $len = strlen($contentStream); $i < $len; $i += 4) {  
421 - $decoded .= base64_decode(substr($contentStream, $i, 4)); 420 + // split the content stream on ={1,2}
  421 + $parts = preg_split('/={1,2}/', $contentStream, null, PREG_SPLIT_NO_EMPTY);
  422 + foreach($parts as $part) {
  423 + // decode, append to output to be re-encoded
  424 + $decoded .= base64_decode($part);
422 } 425 }
423 - 426 +
424 return $decoded; 427 return $decoded;
425 } 428 }
426 429
@@ -438,7 +441,7 @@ class CMISUtil { @@ -438,7 +441,7 @@ class CMISUtil {
438 * @param object $contentStream 441 * @param object $contentStream
439 * @return string decoded 442 * @return string decoded
440 */ 443 */
441 - static public function decodeChunkedContentStream($contentStream) 444 + static public function decodeChunkedContentStreamLong($contentStream)
442 { 445 {
443 // check the content stream for any lines of unusual length (except the last line, which can be any length) 446 // check the content stream for any lines of unusual length (except the last line, which can be any length)
444 $count = -1; 447 $count = -1;
@@ -464,7 +467,7 @@ class CMISUtil { @@ -464,7 +467,7 @@ class CMISUtil {
464 { 467 {
465 // check for a new chunk 468 // check for a new chunk
466 // either we have an equals sign (or two) 469 // either we have an equals sign (or two)
467 - if (preg_match('/([^=]*={0,2})(.*)/', $line, $matches)) 470 + if (preg_match('/([^=]*={1,2})(.*)/', $line, $matches))
468 { 471 {
469 $lastChunk = $matches[1]; 472 $lastChunk = $matches[1];
470 $nextChunk = $matches[2]; 473 $nextChunk = $matches[2];
@@ -507,6 +510,39 @@ class CMISUtil { @@ -507,6 +510,39 @@ class CMISUtil {
507 510
508 return $decoded; 511 return $decoded;
509 } 512 }
  513 +
  514 + /**
  515 + * Function to check whether a specified object exists within the KnowledgeTree system
  516 + *
  517 + * @param string $typeId
  518 + * @param string $objectId
  519 + * @param object $ktapi
  520 + * @return boolean
  521 + */
  522 + public function contentExists($typeId, $objectId, &$ktapi)
  523 + {
  524 + $exists = true;
  525 + if ($typeId == 'Folder')
  526 + {
  527 + $object = $ktapi->get_folder_by_id($objectId);
  528 + if (PEAR::isError($object)) {
  529 + $exists = false;
  530 + }
  531 + }
  532 + else if ($typeId == 'Document')
  533 + {
  534 + $object = $ktapi->get_document_by_id($objectId);
  535 + if (PEAR::isError($object)) {
  536 + $exists = false;
  537 + }
  538 + // TODO check deleted status?
  539 + }
  540 + else {
  541 + $exists = false;
  542 + }
  543 +
  544 + return $exists;
  545 + }
510 546
511 } 547 }
512 548
webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
@@ -36,11 +36,14 @@ include_once CMIS_ATOM_LIB_FOLDER . &#39;ObjectService.inc.php&#39;; @@ -36,11 +36,14 @@ include_once CMIS_ATOM_LIB_FOLDER . &#39;ObjectService.inc.php&#39;;
36 include_once CMIS_ATOM_LIB_FOLDER . 'VersioningService.inc.php'; 36 include_once CMIS_ATOM_LIB_FOLDER . 'VersioningService.inc.php';
37 include_once 'KT_cmis_atom_service_helper.inc.php'; 37 include_once 'KT_cmis_atom_service_helper.inc.php';
38 38
39 -// TODO auth failed response requires WWW-Authenticate: Basic realm="KnowledgeTree DMS" header 39 +// TODO consider changing all responses from the webservice layer to return PEAR errors or success results instead of the half/half we have at the moment.
  40 +// the half/half occurred because on initial services PEAR Error seemed unnecessary, but it has proven useful for some of the newer functions :)
40 41
41 /** 42 /**
42 * AtomPub Service: folder 43 * AtomPub Service: folder
43 */ 44 */
  45 +// TODO implement failure responses for documents and folders not found. (KTS-4364: http://issues.knowledgetree.com/browse/KTS-4364)
  46 +// NOTE what about documents which are deleted, need to respond that those are also not found.
44 class KT_cmis_atom_service_folder extends KT_atom_service { 47 class KT_cmis_atom_service_folder extends KT_atom_service {
45 48
46 /** 49 /**
@@ -92,7 +95,7 @@ class KT_cmis_atom_service_folder extends KT_atom_service { @@ -92,7 +95,7 @@ class KT_cmis_atom_service_folder extends KT_atom_service {
92 95
93 /** 96 /**
94 * Deals with folder service POST actions. 97 * Deals with folder service POST actions.
95 - * This includes creation of both folders and documents. 98 + * This includes creation/moving of both folders and documents.
96 */ 99 */
97 public function POST_action() 100 public function POST_action()
98 { 101 {
@@ -100,48 +103,101 @@ class KT_cmis_atom_service_folder extends KT_atom_service { @@ -100,48 +103,101 @@ class KT_cmis_atom_service_folder extends KT_atom_service {
100 $repositories = $RepositoryService->getRepositories(); 103 $repositories = $RepositoryService->getRepositories();
101 $repositoryId = $repositories[0]['repositoryId']; 104 $repositoryId = $repositories[0]['repositoryId'];
102 105
  106 + // set default action, objectId and typeId
  107 + $action = 'create';
  108 + $objectId = null;
  109 + $typeId = null;
  110 +
103 $folderId = $this->params[0]; 111 $folderId = $this->params[0];
104 $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title'); 112 $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title');
105 $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary'); 113 $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary');
106 114
107 $properties = array('name' => $title, 'summary' => $summary); 115 $properties = array('name' => $title, 'summary' => $summary);
108 116
109 - // determine whether this is a folder or a document create  
110 - // document create will have a content tag <atom:content> or <content> containing base64 encoding of the document  
111 - $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content'); 117 + // determine whether this is a folder or a document action
  118 + // document action create will have a content tag <atom:content> or <content> containing base64 encoding of the document
  119 + // move action will have an existing id supplied as a parameter - not sure how this works yet as the CMIS clients we are
  120 + // testing don't support move functionality at this time (2009/07/23) and so we are presuming the following format:
  121 + // /folder/<folderId>/children/<objectId>
  122 + // also possible that there will be an existing ObjectId property, try to cater for both until we know how it really works
  123 +
  124 + // check for existing object id as parameter in url
  125 + if (isset($this->params[2]))
  126 + {
  127 + $action = 'move';
  128 + $objectId = $this->params[2];
  129 + }
  130 +
  131 + $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object']
  132 + [0]['@children']['cmis:properties']
  133 + [0]['@children']);
  134 +
  135 + // check for existing object id as property of submitted object data
  136 + if (!empty($cmisObjectProperties['ObjectId']))
  137 + {
  138 + $action = 'move';
  139 + $objectId = $cmisObjectProperties['ObjectId'];
  140 + }
  141 +
  142 + // TODO there may be more to do for the checking of an existing object.
  143 + // e.g. verifying that it does indeed exist, and throwing an exception if it does not:
  144 + // "If the objected property is present but not valid an exception will be thrown" (from CMIS specification)
  145 + // NOTE this exception should be thrown in the service API code and not here.
  146 +
  147 + // determine type if object is being moved
  148 + if (!is_null($objectId)) {
  149 + CMISUtil::decodeObjectId($objectId, $typeId);
  150 + }
112 151
113 - // check content for weird chars  
114 - $matches = array();  
115 - preg_match('/[^\w\d\/\+\n]*/', $content, $matches); 152 + // now check for content stream
  153 + $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content');
116 154
117 - if (is_null($content)) { 155 + // check content for weird chars - don't think this serves a purpose any longer, should probably be removed.
  156 + // was meant to check for any non-base64 characters in the content string.
  157 + // preg_match('/[^\w\d\/\+=\n]*/', $content);
  158 + // TODO this will possibly need to change somewhat once Relationship Objects come into play.
  159 + if ((($action == 'create') && (is_null($content))) || ($typeId == 'Folder')) {
118 $type = 'folder'; 160 $type = 'folder';
119 } 161 }
120 else { 162 else {
121 $type = 'document'; 163 $type = 'document';
122 } 164 }
123 165
124 - $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object']  
125 - [0]['@children']['cmis:properties']  
126 - [0]['@children']);  
127 -  
128 $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt()); 166 $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt());
129 167
130 - if ($type == 'folder')  
131 - $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId);  
132 - else  
133 - $newObjectId = $ObjectService->createDocument($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId, $content);  
134 -  
135 - // check if returned Object Id is a valid CMIS Object Id  
136 - CMISUtil::decodeObjectId($newObjectId, $typeId); 168 + $success = false;
  169 + $error = null;
  170 + if ($action == 'create')
  171 + {
  172 + if ($type == 'folder')
  173 + $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId);
  174 + else
  175 + $newObjectId = $ObjectService->createDocument($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId, $content);
  176 +
  177 + // check if returned Object Id is a valid CMIS Object Id
  178 + CMISUtil::decodeObjectId($newObjectId, $typeId);
  179 + if ($typeId != 'Unknown') $success = true;
  180 + else $error = $newObjectId['message'];
  181 + }
  182 + else if ($action == 'move')
  183 + {
  184 + $result = $ObjectService->moveObject($repositoryId, $objectId, '', $folderId);
  185 +
  186 + if (!PEAR::isError($result)) $success = true;
  187 + else $error = $result->getMessage();
  188 +
  189 + // same object as before
  190 + $newObjectId = $objectId;
  191 + $typeId = ucwords($type);
  192 + }
137 193
138 - if ($typeId != 'Unknown') 194 + if ($success)
139 { 195 {
140 - $this->setStatus(self::STATUS_CREATED); 196 + $this->setStatus(($action == 'create') ? self::STATUS_CREATED : self::STATUS_UPDATED);
141 $feed = KT_cmis_atom_service_helper::getObjectFeed($ObjectService, $repositoryId, $newObjectId, 'POST'); 197 $feed = KT_cmis_atom_service_helper::getObjectFeed($ObjectService, $repositoryId, $newObjectId, 'POST');
142 } 198 }
143 else { 199 else {
144 - $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $newObjectId['message']); 200 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $error);
145 } 201 }
146 202
147 //Expose the responseFeed 203 //Expose the responseFeed
webservice/classes/atompub/cmis/ObjectService.inc.php
@@ -32,6 +32,34 @@ class ObjectService extends KTObjectService { @@ -32,6 +32,34 @@ class ObjectService extends KTObjectService {
32 } 32 }
33 33
34 /** 34 /**
  35 + * Creates a new document within the repository
  36 + *
  37 + * @param string $repositoryId The repository to which the document must be added
  38 + * @param string $typeId Object Type id for the document object being created
  39 + * @param array $properties Array of properties which must be applied to the created document object
  40 + * @param string $folderId The id of the folder which will be the parent of the created document object
  41 + * This parameter is optional IF unfilingCapability is supported
  42 + * @param contentStream $contentStream optional content stream data
  43 + * @param string $versioningState optional version state value: checkedout/major/minor
  44 + * @return string $objectId The id of the created folder object
  45 + */
  46 + // TODO throw ConstraintViolationException if:
  47 + // value of any of the properties violates the min/max/required/length constraints
  48 + // specified in the property definition in the Object-Type.
  49 + public function createDocument($repositoryId, $typeId, $properties, $folderId = null,
  50 + $contentStream = null, $versioningState = null)
  51 + {
  52 + $result = parent::createDocument($repositoryId, $typeId, $properties, $folderId, $contentStream, $versioningState);
  53 +
  54 + if ($result['status_code'] == 0) {
  55 + return $result['results'];
  56 + }
  57 + else {
  58 + return $result;
  59 + }
  60 + }
  61 +
  62 + /**
35 * Creates a new folder within the repository 63 * Creates a new folder within the repository
36 * 64 *
37 * @param string $repositoryId The repository to which the folder must be added 65 * @param string $repositoryId The repository to which the folder must be added
@@ -40,7 +68,7 @@ class ObjectService extends KTObjectService { @@ -40,7 +68,7 @@ class ObjectService extends KTObjectService {
40 * @param string $folderId The id of the folder which will be the parent of the created folder object 68 * @param string $folderId The id of the folder which will be the parent of the created folder object
41 * @return string $objectId The id of the created folder object 69 * @return string $objectId The id of the created folder object
42 */ 70 */
43 - function createFolder($repositoryId, $typeId, $properties, $folderId) 71 + public function createFolder($repositoryId, $typeId, $properties, $folderId)
44 { 72 {
45 $result = parent::createFolder($repositoryId, $typeId, $properties, $folderId); 73 $result = parent::createFolder($repositoryId, $typeId, $properties, $folderId);
46 74
@@ -51,32 +79,25 @@ class ObjectService extends KTObjectService { @@ -51,32 +79,25 @@ class ObjectService extends KTObjectService {
51 return $result; 79 return $result;
52 } 80 }
53 } 81 }
54 - 82 +
55 /** 83 /**
56 - * Creates a new document within the repository  
57 - *  
58 - * @param string $repositoryId The repository to which the document must be added  
59 - * @param string $typeId Object Type id for the document object being created  
60 - * @param array $properties Array of properties which must be applied to the created document object  
61 - * @param string $folderId The id of the folder which will be the parent of the created document object  
62 - * This parameter is optional IF unfilingCapability is supported  
63 - * @param contentStream $contentStream optional content stream data  
64 - * @param string $versioningState optional version state value: checkedout/major/minor  
65 - * @return string $objectId The id of the created folder object 84 + * Moves a fileable object from one folder to another.
  85 + *
  86 + * @param object $repositoryId
  87 + * @param object $objectId
  88 + * @param object $changeToken [optional]
  89 + * @param object $targetFolderId
  90 + * @param object $sourceFolderId [optional]
66 */ 91 */
67 - // TODO throw ConstraintViolationException if:  
68 - // value of any of the properties violates the min/max/required/length constraints  
69 - // specified in the property definition in the Object-Type.  
70 - function createDocument($repositoryId, $typeId, $properties, $folderId = null,  
71 - $contentStream = null, $versioningState = null) 92 + public function moveObject($repositoryId, $objectId, $changeToken = '', $targetFolderId, $sourceFolderId = null)
72 { 93 {
73 - $result = parent::createDocument($repositoryId, $typeId, $properties, $folderId, $contentStream, $versioningState); 94 + $result = parent::moveObject($repositoryId, $objectId, $changeToken, $targetFolderId, $sourceFolderId);
74 95
75 if ($result['status_code'] == 0) { 96 if ($result['status_code'] == 0) {
76 return $result['results']; 97 return $result['results'];
77 } 98 }
78 else { 99 else {
79 - return $result; 100 + return new PEAR_Error($result['message']);
80 } 101 }
81 } 102 }
82 103
@@ -90,7 +111,7 @@ class ObjectService extends KTObjectService { @@ -90,7 +111,7 @@ class ObjectService extends KTObjectService {
90 */ 111 */
91 // NOTE Invoking this service method on an object SHALL not delete the entire version series for a Document Object. 112 // NOTE Invoking this service method on an object SHALL not delete the entire version series for a Document Object.
92 // To delete an entire version series, use the deleteAllVersions() service 113 // To delete an entire version series, use the deleteAllVersions() service
93 - function deleteObject($repositoryId, $objectId, $changeToken = null) 114 + public function deleteObject($repositoryId, $objectId, $changeToken = null)
94 { 115 {
95 $result = parent::deleteObject($repositoryId, $objectId, $changeToken); 116 $result = parent::deleteObject($repositoryId, $objectId, $changeToken);
96 117