Commit d6f4d51f6b123dcc539e8286445fa89a27a45885

Authored by Paul Barrett
1 parent 53ab10ed

Added API and AtomPub support for document checkin via CMIS (note: document cont…

…ent update not included as the tested clients do not allow it.)

Story ID:1093056

Committed by: Paul Barrett

Reviewed by: Jarrett Jordaan
ktapi/ktapi.inc.php
@@ -2928,7 +2928,7 @@ class KTAPI @@ -2928,7 +2928,7 @@ class KTAPI
2928 * @param string $tempfilename 2928 * @param string $tempfilename
2929 * @return kt_document_detail. status_code can be KTWS_ERR_INVALID_SESSION, KTWS_ERR_INVALID_FOLDER, KTWS_ERR_INVALID_DOCUMENT or KTWS_SUCCESS 2929 * @return kt_document_detail. status_code can be KTWS_ERR_INVALID_SESSION, KTWS_ERR_INVALID_FOLDER, KTWS_ERR_INVALID_DOCUMENT or KTWS_SUCCESS
2930 */ 2930 */
2931 - public function checkin_document($document_id, $filename, $reason, $tempfilename, $major_update, 2931 + public function checkin_document($document_id, $filename, $reason, $tempfilename, $major_update,
2932 $sig_username = '', $sig_password = '') 2932 $sig_username = '', $sig_password = '')
2933 { 2933 {
2934 $response = $this->_check_electronic_signature($document_id, $sig_username, $sig_password, $reason, $reason, 2934 $response = $this->_check_electronic_signature($document_id, $sig_username, $sig_password, $reason, $reason,
lib/api/ktcmis/classes/CMISDocumentPropertyCollection.inc.php
@@ -71,6 +71,7 @@ class CMISDocumentPropertyCollection extends CMISPropertyCollection { @@ -71,6 +71,7 @@ class CMISDocumentPropertyCollection extends CMISPropertyCollection {
71 'ContentStreamMimeType' => 'propertyString', 71 'ContentStreamMimeType' => 'propertyString',
72 'ContentStreamFilename' => 'propertyString', 72 'ContentStreamFilename' => 'propertyString',
73 'ContentStreamUri' => 'propertyUri', 73 'ContentStreamUri' => 'propertyUri',
  74 + 'IsLatestVersion' => 'propertyBoolean',
74 'IsVersionSeriesCheckedOut' => 'propertyBoolean', 75 'IsVersionSeriesCheckedOut' => 'propertyBoolean',
75 'VersionSeriesCheckedOutBy' => 'propertyString', 76 'VersionSeriesCheckedOutBy' => 'propertyString',
76 'VersionSeriesCheckedOutId' => 'propertyId', 77 'VersionSeriesCheckedOutId' => 'propertyId',
lib/api/ktcmis/ktcmis.inc.php
@@ -874,10 +874,10 @@ class KTVersioningService extends KTCMISBase { @@ -874,10 +874,10 @@ class KTVersioningService extends KTCMISBase {
874 * @param string $checkinComment [optional] 874 * @param string $checkinComment [optional]
875 * @return string $documentId 875 * @return string $documentId
876 */ 876 */
877 - public function checkIn($repositoryId, $documentId, $major, $changeToken = '', $properties = array(), $contentStream = null, $checkinComment = '') 877 + public function checkIn($repositoryId, $documentId, $major, $contentStream = null, $changeToken = '', $properties = array(), $checkinComment = '')
878 { 878 {
879 try { 879 try {
880 - $result = $this->VersioningService->checkIn($repositoryId, $documentId, $major, $changeToken, $properties, $contentStream, $checkinComment); 880 + $result = $this->VersioningService->checkIn($repositoryId, $documentId, $major, $contentStream, $changeToken, $properties, $checkinComment);
881 } 881 }
882 catch (Exception $e) 882 catch (Exception $e)
883 { 883 {
lib/api/ktcmis/services/CMISObjectService.inc.php
@@ -61,7 +61,7 @@ class CMISObjectService { @@ -61,7 +61,7 @@ class CMISObjectService {
61 // NOTE The latter method has been adopted for the moment 61 // NOTE The latter method has been adopted for the moment
62 catch (Exception $e) 62 catch (Exception $e)
63 { 63 {
64 - throw new ConstraintViolationException('Object is not of base type document. ' . $e->getMessage()); 64 + throw new ConstraintViolationException('Object base type could not be determined. ' . $e->getMessage());
65 } 65 }
66 66
67 if ($typeDefinition['attributes']['baseType'] != 'document') 67 if ($typeDefinition['attributes']['baseType'] != 'document')
@@ -103,49 +103,41 @@ class CMISObjectService { @@ -103,49 +103,41 @@ class CMISObjectService {
103 } 103 }
104 } 104 }
105 105
106 - if (!$typeAllowed)  
107 - { 106 + if (!$typeAllowed) {
108 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')'); 107 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')');
109 } 108 }
110 109
111 // if content stream is required and no content stream is supplied, throw a ConstraintViolationException 110 // if content stream is required and no content stream is supplied, throw a ConstraintViolationException
112 - if (($typeDefinition['attributes']['contentStreamAllowed'] == 'required') && is_null($contentStream))  
113 - { 111 + if (($typeDefinition['attributes']['contentStreamAllowed'] == 'required') && is_null($contentStream)) {
114 throw new ConstraintViolationException('This repository requires a content stream for document creation. ' 112 throw new ConstraintViolationException('This repository requires a content stream for document creation. '
115 . 'Refusing to create an empty document'); 113 . 'Refusing to create an empty document');
116 } 114 }
117 - else if (($typeDefinition['attributes']['contentStreamAllowed'] == 'notAllowed') && !empty($contentStream))  
118 - { 115 + else if (($typeDefinition['attributes']['contentStreamAllowed'] == 'notAllowed') && !empty($contentStream)) {
119 throw new StreamNotSupportedException('Content Streams are not supported'); 116 throw new StreamNotSupportedException('Content Streams are not supported');
120 } 117 }
121 118
122 // if versionable attribute is set to false and versioningState is supplied, throw a ConstraintViolationException 119 // if versionable attribute is set to false and versioningState is supplied, throw a ConstraintViolationException
123 - if (!$typeDefinition['attributes']['versionable'] && !empty($versioningState))  
124 - { 120 + if (!$typeDefinition['attributes']['versionable'] && !empty($versioningState)) {
125 throw new ConstraintViolationException('This repository does not support versioning'); 121 throw new ConstraintViolationException('This repository does not support versioning');
126 } 122 }
127 123
128 // TODO deal with $versioningState when supplied 124 // TODO deal with $versioningState when supplied
129 125
130 // set title and name identical if only one submitted 126 // set title and name identical if only one submitted
131 - if ($properties['title'] == '')  
132 - { 127 + if ($properties['title'] == '') {
133 $properties['title'] = $properties['name']; 128 $properties['title'] = $properties['name'];
134 } 129 }
135 - else if ($properties['name'] == '')  
136 - { 130 + else if ($properties['name'] == '') {
137 $properties['name'] = $properties['title']; 131 $properties['name'] = $properties['title'];
138 } 132 }
139 133
140 // if name is blank throw exception (check type) - using invalidArgument Exception for now 134 // if name is blank throw exception (check type) - using invalidArgument Exception for now
141 - if (trim($properties['name']) == '')  
142 - { 135 + if (trim($properties['name']) == '') {
143 throw new InvalidArgumentException('Refusing to create an un-named document'); 136 throw new InvalidArgumentException('Refusing to create an un-named document');
144 } 137 }
145 138
146 // TODO also set to Default if a non-supported type is submitted 139 // TODO also set to Default if a non-supported type is submitted
147 - if ($properties['type'] == '')  
148 - { 140 + if ($properties['type'] == '') {
149 $properties['type'] = 'Default'; 141 $properties['type'] = 'Default';
150 } 142 }
151 143
@@ -154,17 +146,7 @@ class CMISObjectService { @@ -154,17 +146,7 @@ class CMISObjectService {
154 // this check isn't strictly necessary; however it is needed for a repository which does not support content streams 146 // this check isn't strictly necessary; however it is needed for a repository which does not support content streams
155 if (!is_null($contentStream)) 147 if (!is_null($contentStream))
156 { 148 {
157 - // TODO consider checking whether content is encoded (currently we expect encoded)  
158 - // TODO choose between this and the alternative decode function (see CMISUtil class)  
159 - // this will require some basic benchmarking  
160 - $contentStream = CMISUtil::decodeChunkedContentStream($contentStream);  
161 -  
162 - // NOTE There is a function in CMISUtil to do this, written for the unit tests but since KTUploadManager exists  
163 - // and has more functionality which could come in useful at some point I decided to go with that instead  
164 - // (did not know this existed when I wrote the CMISUtil function)  
165 - $uploadManager = new KTUploadManager();  
166 - // assumes already decoded from base64, should use store_base64_file if not  
167 - $tempfilename = $uploadManager->store_file($contentStream, 'cmis_'); 149 + $tempfilename = CMISUtil::createTemporaryFile($contentStream);
168 150
169 // metadata 151 // metadata
170 $metadata = array(); 152 $metadata = array();
@@ -192,12 +174,10 @@ class CMISObjectService { @@ -192,12 +174,10 @@ class CMISObjectService {
192 ); 174 );
193 } 175 }
194 176
195 - if (!empty($properties['category']))  
196 - { 177 + if (!empty($properties['category'])) {
197 $category = $properties['category']; 178 $category = $properties['category'];
198 } 179 }
199 - else  
200 - { 180 + else {
201 $category = 'Miscellaneous'; 181 $category = 'Miscellaneous';
202 } 182 }
203 183
@@ -231,12 +211,10 @@ class CMISObjectService { @@ -231,12 +211,10 @@ class CMISObjectService {
231 $KTMime = new KTMime(); 211 $KTMime = new KTMime();
232 $mimetype = $KTMime->getMimeTypeFromFile($tempfilename); 212 $mimetype = $KTMime->getMimeTypeFromFile($tempfilename);
233 preg_match('/^([^\/]*)\/([^\/]*)/', $mimetype, $matches); 213 preg_match('/^([^\/]*)\/([^\/]*)/', $mimetype, $matches);
234 - if (($matches[1] == 'text') || ($matches[1] == 'image') || ($matches[1] == 'audio'))  
235 - { 214 + if (($matches[1] == 'text') || ($matches[1] == 'image') || ($matches[1] == 'audio')) {
236 $mediatype = ucwords($matches[1]); 215 $mediatype = ucwords($matches[1]);
237 } 216 }
238 - else if (($matches[2] == 'pdf') || ($matches[2] == 'msword'))  
239 - { 217 + else if (($matches[2] == 'pdf') || ($matches[2] == 'msword')) {
240 $mediatype = 'Text'; 218 $mediatype = 'Text';
241 } 219 }
242 220
@@ -262,12 +240,10 @@ class CMISObjectService { @@ -262,12 +240,10 @@ class CMISObjectService {
262 $response = $this->ktapi->add_document_with_metadata((int)$folderId, $properties['title'], $properties['name'], 240 $response = $this->ktapi->add_document_with_metadata((int)$folderId, $properties['title'], $properties['name'],
263 $properties['type'], $tempfilename, $metadata, $sysdata); 241 $properties['type'], $tempfilename, $metadata, $sysdata);
264 242
265 - if ($response['status_code'] != 0)  
266 - { 243 + if ($response['status_code'] != 0) {
267 throw new StorageException('The repository was unable to create the document. ' . $response['message']); 244 throw new StorageException('The repository was unable to create the document. ' . $response['message']);
268 } 245 }
269 - else  
270 - { 246 + else {
271 $objectId = CMISUtil::encodeObjectId('Document', $response['results']['document_id']); 247 $objectId = CMISUtil::encodeObjectId('Document', $response['results']['document_id']);
272 } 248 }
273 249
@@ -314,13 +290,11 @@ class CMISObjectService { @@ -314,13 +290,11 @@ class CMISObjectService {
314 // exception propogate upward... 290 // exception propogate upward...
315 // Alternatively: throw new exception with original exception message appended 291 // Alternatively: throw new exception with original exception message appended
316 // NOTE The latter method has been adopted for the moment 292 // NOTE The latter method has been adopted for the moment
317 - catch (Exception $e)  
318 - { 293 + catch (Exception $e) {
319 throw new ConstraintViolationException('Object is not of base type folder. ' . $e->getMessage()); 294 throw new ConstraintViolationException('Object is not of base type folder. ' . $e->getMessage());
320 } 295 }
321 296
322 - if ($typeDefinition['attributes']['baseType'] != 'folder')  
323 - { 297 + if ($typeDefinition['attributes']['baseType'] != 'folder') {
324 throw new ConstraintViolationException('Object is not of base type folder'); 298 throw new ConstraintViolationException('Object is not of base type folder');
325 } 299 }
326 300
@@ -333,20 +307,17 @@ class CMISObjectService { @@ -333,20 +307,17 @@ class CMISObjectService {
333 // if parent folder is not allowed to hold this type, throw exception 307 // if parent folder is not allowed to hold this type, throw exception
334 $CMISFolder = new CMISFolderObject($folderId, $this->ktapi); 308 $CMISFolder = new CMISFolderObject($folderId, $this->ktapi);
335 $allowed = $CMISFolder->getProperty('AllowedChildObjectTypeIds'); 309 $allowed = $CMISFolder->getProperty('AllowedChildObjectTypeIds');
336 - if (!is_array($allowed) || !in_array($typeId, $allowed))  
337 - { 310 + if (!is_array($allowed) || !in_array($typeId, $allowed)) {
338 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')'); 311 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')');
339 } 312 }
340 313
341 // TODO if name is blank! throw another exception (check type) - using invalidArgument Exception for now 314 // TODO if name is blank! throw another exception (check type) - using invalidArgument Exception for now
342 - if (trim($properties['name']) == '')  
343 - { 315 + if (trim($properties['name']) == '') {
344 throw new InvalidArgumentException('Refusing to create an un-named folder'); 316 throw new InvalidArgumentException('Refusing to create an un-named folder');
345 } 317 }
346 318
347 $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = ''); 319 $response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = '');
348 - if ($response['status_code'] != 0)  
349 - { 320 + if ($response['status_code'] != 0) {
350 throw new StorageException('The repository was unable to create the folder: ' . $response['message']); 321 throw new StorageException('The repository was unable to create the folder: ' . $response['message']);
351 } 322 }
352 else 323 else
@@ -380,8 +351,7 @@ class CMISObjectService { @@ -380,8 +351,7 @@ class CMISObjectService {
380 351
381 $objectId = CMISUtil::decodeObjectId($objectId, $typeId); 352 $objectId = CMISUtil::decodeObjectId($objectId, $typeId);
382 353
383 - if ($typeId == 'Unknown')  
384 - { 354 + if ($typeId == 'Unknown') {
385 throw new ObjectNotFoundException('The type of the requested object could not be determined'); 355 throw new ObjectNotFoundException('The type of the requested object could not be determined');
386 } 356 }
387 357
@@ -492,8 +462,7 @@ class CMISObjectService { @@ -492,8 +462,7 @@ class CMISObjectService {
492 // check type id of object against allowed child types for destination folder 462 // check type id of object against allowed child types for destination folder
493 $CMISFolder = new CMISFolderObject($targetFolderId, $this->ktapi); 463 $CMISFolder = new CMISFolderObject($targetFolderId, $this->ktapi);
494 $allowed = $CMISFolder->getProperty('AllowedChildObjectTypeIds'); 464 $allowed = $CMISFolder->getProperty('AllowedChildObjectTypeIds');
495 - if (!is_array($allowed) || !in_array($typeId, $allowed))  
496 - { 465 + if (!is_array($allowed) || !in_array($typeId, $allowed)) {
497 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')'); 466 throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')');
498 } 467 }
499 468
@@ -517,8 +486,7 @@ class CMISObjectService { @@ -517,8 +486,7 @@ class CMISObjectService {
517 } 486 }
518 487
519 // if failed, throw StorageException 488 // if failed, throw StorageException
520 - if ($response['status_code'] != 0)  
521 - { 489 + if ($response['status_code'] != 0) {
522 throw new StorageException('The repository was unable to move the object: ' . $response['message']); 490 throw new StorageException('The repository was unable to move the object: ' . $response['message']);
523 } 491 }
524 } 492 }
@@ -541,13 +509,15 @@ class CMISObjectService { @@ -541,13 +509,15 @@ class CMISObjectService {
541 // TODO this should probably be a function, it is now used in two places... 509 // TODO this should probably be a function, it is now used in two places...
542 // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository). 510 // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository).
543 $exists = true; 511 $exists = true;
544 - if ($typeId == 'Folder') { 512 + if ($typeId == 'Folder')
  513 + {
545 $object = $this->ktapi->get_folder_by_id($objectId); 514 $object = $this->ktapi->get_folder_by_id($objectId);
546 if (PEAR::isError($object)) { 515 if (PEAR::isError($object)) {
547 $exists = false; 516 $exists = false;
548 } 517 }
549 } 518 }
550 - else if ($typeId == 'Document') { 519 + else if ($typeId == 'Document')
  520 + {
551 $object = $this->ktapi->get_document_by_id($objectId); 521 $object = $this->ktapi->get_document_by_id($objectId);
552 if (PEAR::isError($object)) { 522 if (PEAR::isError($object)) {
553 $exists = false; 523 $exists = false;
@@ -743,11 +713,7 @@ class CMISObjectService { @@ -743,11 +713,7 @@ class CMISObjectService {
743 throw new ContentAlreadyExistsException('Unable to overwrite existing content stream'); 713 throw new ContentAlreadyExistsException('Unable to overwrite existing content stream');
744 } 714 }
745 715
746 - // NOTE There is a function in CMISUtil to do this but since KTUploadManager exists and has more functionality  
747 - // which could come in useful at some point I decided to go with that instead (did not know it existed when  
748 - // I wrote the CMISUtil function)  
749 - $uploadManager = new KTUploadManager();  
750 - $tempfilename = $uploadManager->store_base64_file($contentStream, 'cmis_'); 716 + $tempfilename = CMISUtil::createTemporaryFile($contentStream);
751 // update the document content from this temporary file as per usual 717 // update the document content from this temporary file as per usual
752 // TODO Use checkin_document_with_metadata instead if metadata content submitted || update metadata separately? 718 // TODO Use checkin_document_with_metadata instead if metadata content submitted || update metadata separately?
753 $response = $this->ktapi->checkin_document($documentId, $csFileName, 'CMIS setContentStream action', $tempfilename, false); 719 $response = $this->ktapi->checkin_document($documentId, $csFileName, 'CMIS setContentStream action', $tempfilename, false);
lib/api/ktcmis/services/CMISVersioningService.inc.php
@@ -3,11 +3,12 @@ @@ -3,11 +3,12 @@
3 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'); 4 require_once(CMIS_DIR . '/exceptions/ConstraintViolationException.inc.php');
5 require_once(CMIS_DIR . '/exceptions/StorageException.inc.php'); 5 require_once(CMIS_DIR . '/exceptions/StorageException.inc.php');
  6 +require_once(CMIS_DIR . '/exceptions/StreamNotSupportedException.inc.php');
6 require_once(CMIS_DIR . '/exceptions/UpdateConflictException.inc.php'); 7 require_once(CMIS_DIR . '/exceptions/UpdateConflictException.inc.php');
7 require_once(CMIS_DIR . '/exceptions/VersioningException.inc.php'); 8 require_once(CMIS_DIR . '/exceptions/VersioningException.inc.php');
8 require_once(CMIS_DIR . '/services/CMISObjectService.inc.php'); 9 require_once(CMIS_DIR . '/services/CMISObjectService.inc.php');
9 require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php'); 10 require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php');
10 -//require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); 11 +require_once(CMIS_DIR . '/util/CMISUtil.inc.php');
11 12
12 class CMISVersioningService { 13 class CMISVersioningService {
13 14
@@ -182,14 +183,8 @@ class CMISVersioningService { @@ -182,14 +183,8 @@ class CMISVersioningService {
182 * @return string $documentId 183 * @return string $documentId
183 */ 184 */
184 // TODO Exceptions: 185 // TODO Exceptions:
185 - // • ConstraintViolationException - SHALL throw if o The Document’s Object-Type definition’s versionable attribute is FALSE.  
186 - // • storageException - MAY throw  
187 - // • streamNotSupportedException - The Repository SHALL throw this exception if the Object-Type definition specified by the typeId  
188 - // parameter’s “contentStreamAllowed” attribute is set to “not allowed” and a contentStream input  
189 - // parameter is provided.  
190 - // • updateConflictException - MAY throw  
191 // • versioningException - The repository MAY throw this exception if the object is a non-current Document Version 186 // • versioningException - The repository MAY throw this exception if the object is a non-current Document Version
192 - public function checkIn($repositoryId, $documentId, $major, $changeToken = '', $properties = array(), $contentStream = null, $checkinComment = '') 187 + public function checkIn($repositoryId, $documentId, $major, $contentStream = null, $changeToken = '', $properties = array(), $checkinComment = '')
193 { 188 {
194 $documentId = CMISUtil::decodeObjectId($documentId, $typeId); 189 $documentId = CMISUtil::decodeObjectId($documentId, $typeId);
195 190
@@ -206,7 +201,35 @@ class CMISVersioningService { @@ -206,7 +201,35 @@ class CMISVersioningService {
206 throw new ConstraintViolationException('This document is not versionable and may not be checked in'); 201 throw new ConstraintViolationException('This document is not versionable and may not be checked in');
207 } 202 }
208 203
209 - return $documentId; 204 + $RepositoryService = new CMISRepositoryService();
  205 + try {
  206 + $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $typeId);
  207 + }
  208 + catch (exception $e) {
  209 + // if we can't get the type definition, then we can't store the content
  210 + throw new StorageException($e->getMessage());
  211 + }
  212 +
  213 + if (($typeDefinition['attributes']['contentStreamAllowed'] == 'notAllowed') && !empty($contentStream)) {
  214 + throw new StreamNotSupportedException('Content Streams are not supported');
  215 + }
  216 +
  217 + // check that this is the latest version
  218 + if ($pwc->getProperty('IsLatestVersion') != true) {
  219 + throw new VersioningException('The document is not the latest version and cannot be checked in');
  220 + }
  221 +
  222 + // now do the checkin
  223 + $tempfilename = CMISUtil::createTemporaryFile($contentStream);
  224 + $response = $this->ktapi->checkin_document($documentId, $pwc->getProperty('ContentStreamFilename'), $reason, $tempfilename, $major,
  225 + $sig_username, $sig_password);
  226 +
  227 + // if there was any error in cancelling the checkout
  228 + if ($response['status_code'] == 1) {
  229 + throw new RuntimeException('There was an error checking in the document: ' . $response['message']);
  230 + }
  231 +
  232 + return CMISUtil::encodeObjectId(DOCUMENT, $documentId);
210 } 233 }
211 234
212 } 235 }
lib/api/ktcmis/util/CMISUtil.inc.php
@@ -406,30 +406,6 @@ class CMISUtil { @@ -406,30 +406,6 @@ class CMISUtil {
406 return (($input === true) ? 'true' : (($input === false) ? 'false' : $input)); 406 return (($input === true) ? 'true' : (($input === false) ? 'false' : $input));
407 } 407 }
408 408
409 - /**  
410 - * Creates a temporary file  
411 - * Cleanup is the responsibility of the calling code  
412 - *  
413 - * @param string|binary $content The content to be written to the file.  
414 - * @param string $uploadDir Optional upload directory. Will use the KnowledgeTree system tmp directory if not supplied.  
415 - * @return string The path to the created file (for reference and cleanup.)  
416 - */  
417 - static public function createTemporaryFile($content, $encoding = null, $uploadDir = null)  
418 - {  
419 - if(is_null($uploadDir))  
420 - {  
421 - $oKTConfig =& KTConfig::getSingleton();  
422 - $uploadDir = $oKTConfig->get('webservice/uploadDirectory');  
423 - }  
424 -  
425 - $temp = tempnam($uploadDir, 'myfile');  
426 - $fp = fopen($temp, 'wb');  
427 - fwrite($fp, ($encoding == 'base64' ? base64_decode($content) : $content));  
428 - fclose($fp);  
429 -  
430 - return $temp;  
431 - }  
432 -  
433 // TODO more robust base64 encoding detection, if possible 409 // TODO more robust base64 encoding detection, if possible
434 410
435 /** 411 /**
@@ -610,6 +586,33 @@ class CMISUtil { @@ -610,6 +586,33 @@ class CMISUtil {
610 586
611 return $exists; 587 return $exists;
612 } 588 }
  589 +
  590 + /**
  591 + * Creates a temporary file
  592 + * Cleanup is the responsibility of the calling code
  593 + *
  594 + * @param string $contentStream The content to be stored (assumed to be base64)
  595 + * @return string The path to the created file (for reference and cleanup.)
  596 + */
  597 + static public function createTemporaryFile($contentStream)
  598 + {
  599 + // if contentStream is empty, cannot create file
  600 + if (empty($contentStream)) return null;
  601 +
  602 + // TODO consider checking whether content is encoded (currently we expect encoded)
  603 + // TODO choose between this and the alternative decode function (see CMISUtil class)
  604 + // this will require some basic benchmarking
  605 + $contentStream = CMISUtil::decodeChunkedContentStream($contentStream);
  606 +
  607 + // NOTE There is a function in CMISUtil to do this, written for the unit tests but since KTUploadManager exists
  608 + // and has more functionality which could come in useful at some point I decided to go with that instead
  609 + // (did not know this existed when I wrote the CMISUtil function)
  610 + $uploadManager = new KTUploadManager();
  611 + // assumes already decoded from base64, should use store_base64_file if not
  612 + $tempfilename = $uploadManager->store_file($contentStream, 'cmis_');
  613 +
  614 + return $tempfilename;
  615 + }
613 616
614 } 617 }
615 618
webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
@@ -101,7 +101,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -101,7 +101,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
101 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $folderId); 101 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $folderId);
102 } 102 }
103 103
104 - //Expose the responseFeed 104 + // Expose the responseFeed
105 $this->responseFeed = $feed; 105 $this->responseFeed = $feed;
106 } 106 }
107 107
@@ -140,7 +140,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -140,7 +140,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
140 $objectId = $this->params[2]; 140 $objectId = $this->params[2];
141 } 141 }
142 142
143 - $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object']); 143 + $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']);
144 144
145 // check for existing object id as property of submitted object data 145 // check for existing object id as property of submitted object data
146 if (!empty($cmisObjectProperties['ObjectId'])) 146 if (!empty($cmisObjectProperties['ObjectId']))
@@ -159,7 +159,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -159,7 +159,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
159 CMISUtil::decodeObjectId($objectId, $typeId); 159 CMISUtil::decodeObjectId($objectId, $typeId);
160 } 160 }
161 161
162 - // now check for content stream 162 + // check for content stream
163 $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content'); 163 $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content');
164 164
165 // TODO this will possibly need to change somewhat once Relationship Objects come into play. 165 // TODO this will possibly need to change somewhat once Relationship Objects come into play.
@@ -207,7 +207,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -207,7 +207,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
207 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $error); 207 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $error);
208 } 208 }
209 209
210 - //Expose the responseFeed 210 + // Expose the responseFeed
211 $this->responseFeed = $feed; 211 $this->responseFeed = $feed;
212 } 212 }
213 213
@@ -236,7 +236,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -236,7 +236,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
236 if (PEAR::isError($response)) 236 if (PEAR::isError($response))
237 { 237 {
238 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage()); 238 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage());
239 - //Expose the responseFeed 239 + // Expose the responseFeed
240 $this->responseFeed = $feed; 240 $this->responseFeed = $feed;
241 return null; 241 return null;
242 } 242 }
@@ -349,7 +349,7 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service { @@ -349,7 +349,7 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service {
349 $type = ((empty($this->params[0])) ? 'all' : $this->params[0]); 349 $type = ((empty($this->params[0])) ? 'all' : $this->params[0]);
350 $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); 350 $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types);
351 351
352 - //Expose the responseFeed 352 + // Expose the responseFeed
353 $this->responseFeed = $feed; 353 $this->responseFeed = $feed;
354 } 354 }
355 355
@@ -385,7 +385,7 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service { @@ -385,7 +385,7 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service {
385 $feed = $this->getTypeChildrenFeed($this->params[1]); 385 $feed = $this->getTypeChildrenFeed($this->params[1]);
386 } 386 }
387 387
388 - //Expose the responseFeed 388 + // Expose the responseFeed
389 $this->responseFeed=$feed; 389 $this->responseFeed=$feed;
390 } 390 }
391 391
@@ -494,7 +494,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { @@ -494,7 +494,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service {
494 // $entry = null; 494 // $entry = null;
495 // $feed->newField('cmis:hasMoreItems', 'false', $entry, true); 495 // $feed->newField('cmis:hasMoreItems', 'false', $entry, true);
496 496
497 - //Expose the responseFeed 497 + // Expose the responseFeed
498 $this->responseFeed = $feed; 498 $this->responseFeed = $feed;
499 } 499 }
500 500
@@ -513,7 +513,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { @@ -513,7 +513,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service {
513 if (empty($cmisObjectProperties['ObjectId'])) 513 if (empty($cmisObjectProperties['ObjectId']))
514 { 514 {
515 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, 'No object was specified for checkout'); 515 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, 'No object was specified for checkout');
516 - //Expose the responseFeed 516 + // Expose the responseFeed
517 $this->responseFeed = $feed; 517 $this->responseFeed = $feed;
518 return null; 518 return null;
519 } 519 }
@@ -523,7 +523,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { @@ -523,7 +523,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service {
523 if (PEAR::isError($response)) 523 if (PEAR::isError($response))
524 { 524 {
525 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, 'No object was specified for checkout'); 525 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, 'No object was specified for checkout');
526 - //Expose the responseFeed 526 + // Expose the responseFeed
527 $this->responseFeed = $feed; 527 $this->responseFeed = $feed;
528 return null; 528 return null;
529 } 529 }
@@ -531,7 +531,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { @@ -531,7 +531,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service {
531 $this->setStatus(self::STATUS_CREATED); 531 $this->setStatus(self::STATUS_CREATED);
532 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['ObjectId'], 'POST'); 532 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['ObjectId'], 'POST');
533 533
534 - //Expose the responseFeed 534 + // Expose the responseFeed
535 $this->responseFeed = $feed; 535 $this->responseFeed = $feed;
536 } 536 }
537 537
@@ -559,13 +559,13 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { @@ -559,13 +559,13 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service {
559 // this depends on $this->params[1] 559 // this depends on $this->params[1]
560 if (!empty($this->params[1])) 560 if (!empty($this->params[1]))
561 { 561 {
562 - $this->getContentStream($ObjectService, $repositoryId); 562 + KT_cmis_atom_service_helper::downloadContentStream($this, $ObjectService, $repositoryId);
563 return null; 563 return null;
564 } 564 }
565 565
566 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]); 566 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]);
567 567
568 - //Expose the responseFeed 568 + // Expose the responseFeed
569 $this->responseFeed = $feed; 569 $this->responseFeed = $feed;
570 } 570 }
571 571
@@ -594,7 +594,7 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { @@ -594,7 +594,7 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service {
594 if (PEAR::isError($response)) 594 if (PEAR::isError($response))
595 { 595 {
596 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage()); 596 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage());
597 - //Expose the responseFeed 597 + // Expose the responseFeed
598 $this->responseFeed = $feed; 598 $this->responseFeed = $feed;
599 return null; 599 return null;
600 } 600 }
@@ -603,46 +603,6 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { @@ -603,46 +603,6 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service {
603 $this->setStatus(self::STATUS_NO_CONTENT); 603 $this->setStatus(self::STATUS_NO_CONTENT);
604 } 604 }
605 605
606 - private function getContentStream(&$ObjectService, $repositoryId)  
607 - {  
608 - $response = $ObjectService->getProperties($repositoryId, $this->params[0], false, false);  
609 - if (PEAR::isError($response)) {  
610 - $feed = KT_cmis_atom_service_helper::getErrorFeed($this, KT_cmis_atom_service::STATUS_SERVER_ERROR, $response->getMessage());  
611 - $this->responseFeed = $feed;  
612 - return null;  
613 - }  
614 -  
615 - // TODO also check If-Modified-Since?  
616 -// $this->headers['If-Modified-Since'] => 2009-07-24 17:16:54  
617 -  
618 - $this->contentDownload = true;  
619 - $eTag = md5($response['properties']['LastModificationDate']['value'] . $response['properties']['ContentStreamLength']['value']);  
620 -  
621 - if ($this->headers['If-None-Match'] == $eTag)  
622 - {  
623 - $this->setStatus(self::STATUS_NOT_MODIFIED);  
624 - $this->contentDownload = false;  
625 - return null;  
626 - }  
627 -  
628 - $contentStream = $ObjectService->getContentStream($repositoryId, $this->params[0]);  
629 -  
630 - // headers specific to output  
631 - $this->setEtag($eTag);  
632 - $this->setHeader('Last-Modified', $response['properties']['LastModificationDate']['value']);  
633 -  
634 - if (!empty($response['properties']['ContentStreamMimeType']['value'])) {  
635 - $this->setHeader('Content-type', $response['properties']['ContentStreamMimeType']['value'] . ';charset=utf-8');  
636 - }  
637 - else {  
638 - $this->setHeader('Content-type', 'text/plain;charset=utf-8');  
639 - }  
640 -  
641 - $this->setHeader('Content-Disposition', 'attachment;filename="' . $response['properties']['ContentStreamFilename']['value'] . '"');  
642 - $this->setHeader('Content-Length', $response['properties']['ContentStreamLength']['value']);  
643 - $this->output = $contentStream;  
644 - }  
645 -  
646 } 606 }
647 607
648 class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { 608 class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
@@ -665,13 +625,13 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { @@ -665,13 +625,13 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
665 // this depends on $this->params[1] 625 // this depends on $this->params[1]
666 if (!empty($this->params[1])) 626 if (!empty($this->params[1]))
667 { 627 {
668 - $this->getContentStream($ObjectService, $repositoryId); 628 + KT_cmis_atom_service_helper::downloadContentStream($this, $ObjectService, $repositoryId);
669 return null; 629 return null;
670 } 630 }
671 631
672 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]); 632 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]);
673 633
674 - //Expose the responseFeed 634 + // Expose the responseFeed
675 $this->responseFeed = $feed; 635 $this->responseFeed = $feed;
676 } 636 }
677 637
@@ -696,7 +656,7 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { @@ -696,7 +656,7 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
696 if (PEAR::isError($response)) 656 if (PEAR::isError($response))
697 { 657 {
698 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage()); 658 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage());
699 - //Expose the responseFeed 659 + // Expose the responseFeed
700 $this->responseFeed = $feed; 660 $this->responseFeed = $feed;
701 return null; 661 return null;
702 } 662 }
@@ -714,18 +674,52 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { @@ -714,18 +674,52 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
714 $repositories = $RepositoryService->getRepositories(); 674 $repositories = $RepositoryService->getRepositories();
715 $repositoryId = $repositories[0]['repositoryId']; 675 $repositoryId = $repositories[0]['repositoryId'];
716 676
717 - $response = $VersioningService->checkIn($repositoryId, $this->params[0]); 677 + // check for content stream
  678 + // NOTE this is a hack! will not work with CMISSpaces at least, probably not with any client except RestTest and similar
  679 + // where we can manually modify the input
  680 + // first we try for an atom content tag
  681 + $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content');
  682 + if (!empty($content)) {
  683 + $contentStream = $content;
  684 + }
  685 + // not found? try for a regular content tag
  686 + else {
  687 + $content = KT_cmis_atom_service_helper::findTag('content', $this->parsedXMLContent['@children'], null, false);
  688 + $contentStream = $content['@value'];
  689 + }
  690 +
  691 + // if we haven't found it now, the real hack begins - retrieve the EXISTING content and submit this as the contentStream
  692 + // this is needed because KnowledgeTree will not accept a checkin without a content stream but CMISSpaces (and possibly
  693 + // other CMIS clients are the same, does not send a content stream on checkin nor does it offer the user a method to choose one)
  694 + // NOTE that if the content is INTENDED to be empty this and all the above checks will FAIL!
  695 + // FIXME this is horrible, terrible, ugly and bad!
  696 + if (empty($contentStream))
  697 + {
  698 + $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt());
  699 + $contentStream = base64_encode(KT_cmis_atom_service_helper::getContentStream($this, $ObjectService, $repositoryId));
  700 + }
  701 +
  702 + // and if we don't have it by now, we give up...but leave the error to be generated by the underlying KnowledgeTree code
  703 +
  704 + // checkin function call
  705 + // TODO dynamically detect version change type - leaving this for now as the CMIS clients tested do not appear to
  706 + // offer the choice to the user - perhaps it will turn out that this will come from somewhere else but for now
  707 + // we assume minor version updates only
  708 + $major = false;
  709 + $response = $VersioningService->checkIn($repositoryId, $this->params[0], $major, $contentStream);
718 710
719 if (PEAR::isError($response)) 711 if (PEAR::isError($response))
720 { 712 {
721 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage()); 713 $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $response->getMessage());
722 - //Expose the responseFeed 714 + // Expose the responseFeed
723 $this->responseFeed = $feed; 715 $this->responseFeed = $feed;
724 return null; 716 return null;
725 } 717 }
726 718
727 - $this->setStatus(self::STATUS_NO_CONTENT);  
728 - $this->responseFeed = null; 719 + $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]);
  720 +
  721 + // Expose the responseFeed
  722 + $this->responseFeed = $feed;
729 } 723 }
730 724
731 } 725 }
webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
@@ -418,7 +418,7 @@ class KT_cmis_atom_service_helper { @@ -418,7 +418,7 @@ class KT_cmis_atom_service_helper {
418 while($start < $numFolders) 418 while($start < $numFolders)
419 { 419 {
420 $name = $path[$numQ-$numFolders+$start]; 420 $name = $path[$numQ-$numFolders+$start];
421 - // hack to fix drupal url encoding issue 421 + // fix for possible url encoding issue
422 $name = str_replace('%2520', '%20', $name); 422 $name = str_replace('%2520', '%20', $name);
423 423
424 $folderName = urldecode($name); 424 $folderName = urldecode($name);
@@ -494,6 +494,71 @@ class KT_cmis_atom_service_helper { @@ -494,6 +494,71 @@ class KT_cmis_atom_service_helper {
494 return date('Y-m-d H:i:s', $time); 494 return date('Y-m-d H:i:s', $time);
495 } 495 }
496 496
  497 + /**
  498 + * Fetches the document content stream for internal use
  499 + *
  500 + * @param object $ObjectService
  501 + * @param string $repositoryId
  502 + * @return null | string $contentStream
  503 + */
  504 + static public function getContentStream(&$service, &$ObjectService, $repositoryId)
  505 + {
  506 + $response = $ObjectService->getProperties($repositoryId, $service->params[0], false, false);
  507 + if (PEAR::isError($response)) {
  508 + return null;
  509 + }
  510 +
  511 + $contentStream = $ObjectService->getContentStream($repositoryId, $service->params[0]);
  512 +
  513 + return $contentStream;
  514 + }
  515 + /**
  516 + * Fetches and prepares the document content stream for download/viewing
  517 + *
  518 + * @param object $ObjectService
  519 + * @param string $repositoryId
  520 + * @return null | nothing
  521 + */
  522 + static public function downloadContentStream(&$service, &$ObjectService, $repositoryId)
  523 + {
  524 + $response = $ObjectService->getProperties($repositoryId, $service->params[0], false, false);
  525 + if (PEAR::isError($response)) {
  526 + $feed = KT_cmis_atom_service_helper::getErrorFeed($service, KT_cmis_atom_service::STATUS_SERVER_ERROR, $response->getMessage());
  527 + $service->responseFeed = $feed;
  528 + return null;
  529 + }
  530 +
  531 + // TODO also check If-Modified-Since?
  532 +// $service->headers['If-Modified-Since'] => 2009-07-24 17:16:54
  533 +
  534 + $service->setContentDownload(true);
  535 + $eTag = md5($response['properties']['LastModificationDate']['value'] . $response['properties']['ContentStreamLength']['value']);
  536 +
  537 + if ($service->headers['If-None-Match'] == $eTag)
  538 + {
  539 + $service->setStatus(KT_cmis_atom_service::STATUS_NOT_MODIFIED);
  540 + $service->setContentDownload(false);
  541 + return null;
  542 + }
  543 +
  544 + $contentStream = $ObjectService->getContentStream($repositoryId, $service->params[0]);
  545 +
  546 + // headers specific to output
  547 + $service->setEtag($eTag);
  548 + $service->setHeader('Last-Modified', $response['properties']['LastModificationDate']['value']);
  549 +
  550 + if (!empty($response['properties']['ContentStreamMimeType']['value'])) {
  551 + $service->setHeader('Content-type', $response['properties']['ContentStreamMimeType']['value'] . ';charset=utf-8');
  552 + }
  553 + else {
  554 + $service->setHeader('Content-type', 'text/plain;charset=utf-8');
  555 + }
  556 +
  557 + $service->setHeader('Content-Disposition', 'attachment;filename="' . $response['properties']['ContentStreamFilename']['value'] . '"');
  558 + $service->setHeader('Content-Length', $response['properties']['ContentStreamLength']['value']);
  559 + $service->setOutput($contentStream);
  560 + }
  561 +
497 //TODO: Add key information to be able to find the same tag in the original struct (MarkH) 562 //TODO: Add key information to be able to find the same tag in the original struct (MarkH)
498 static public function findTag($tagName=NULL,$xml=array(),$tagArray=NULL,$deep=false){ 563 static public function findTag($tagName=NULL,$xml=array(),$tagArray=NULL,$deep=false){
499 $tagArray=is_array($tagArray)?$tagArray:array(); 564 $tagArray=is_array($tagArray)?$tagArray:array();
webservice/classes/atompub/KT_atom_service.inc.php
@@ -147,7 +147,7 @@ class KT_atom_service{ @@ -147,7 +147,7 @@ class KT_atom_service{
147 header("HTTP/1.1 ".$status); 147 header("HTTP/1.1 ".$status);
148 } 148 }
149 149
150 - protected function setEtag($etagValue=NULL){ 150 + public function setEtag($etagValue=NULL){
151 if($etagValue)header('ETag: '.$etagValue); 151 if($etagValue)header('ETag: '.$etagValue);
152 } 152 }
153 153
webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php
@@ -8,7 +8,12 @@ class KT_cmis_atom_service extends KT_atom_service { @@ -8,7 +8,12 @@ class KT_cmis_atom_service extends KT_atom_service {
8 8
9 protected $serviceType = null; 9 protected $serviceType = null;
10 protected $contentDownload = false; 10 protected $contentDownload = false;
11 - 11 +
  12 + public function setContentDownload($contentDownload)
  13 + {
  14 + $this->contentDownload = $contentDownload;
  15 + }
  16 +
12 public public function isContentDownload() 17 public public function isContentDownload()
13 { 18 {
14 return $this->contentDownload; 19 return $this->contentDownload;
@@ -19,6 +24,11 @@ class KT_cmis_atom_service extends KT_atom_service { @@ -19,6 +24,11 @@ class KT_cmis_atom_service extends KT_atom_service {
19 return $this->status == self::STATUS_NOT_MODIFIED; 24 return $this->status == self::STATUS_NOT_MODIFIED;
20 } 25 }
21 26
  27 + public function setoutput($output)
  28 + {
  29 + $this->output = $output;
  30 + }
  31 +
22 public function getOutput() 32 public function getOutput()
23 { 33 {
24 return $this->output; 34 return $this->output;
@@ -29,7 +39,7 @@ class KT_cmis_atom_service extends KT_atom_service { @@ -29,7 +39,7 @@ class KT_cmis_atom_service extends KT_atom_service {
29 return $this->serviceType; 39 return $this->serviceType;
30 } 40 }
31 41
32 - protected function setHeader($header = null, $value = null) 42 + public function setHeader($header = null, $value = null)
33 { 43 {
34 if ($header) header($header . ': ' . $value); 44 if ($header) header($header . ': ' . $value);
35 } 45 }
webservice/classes/atompub/cmis/VersioningService.inc.php
@@ -85,9 +85,9 @@ class VersioningService extends KTVersioningService { @@ -85,9 +85,9 @@ class VersioningService extends KTVersioningService {
85 * @param string $checkinComment [optional] 85 * @param string $checkinComment [optional]
86 * @return string $documentId 86 * @return string $documentId
87 */ 87 */
88 - public function checkIn($repositoryId, $documentId, $major, $changeToken = '', $properties = array(), $contentStream = null, $checkinComment = '') 88 + public function checkIn($repositoryId, $documentId, $major, $contentStream = null, $changeToken = '', $properties = array(), $checkinComment = '')
89 { 89 {
90 - $result = parent::checkIn($repositoryId, $documentId, $major, $changeToken, $properties, $contentStream, $checkinComment); 90 + $result = parent::checkIn($repositoryId, $documentId, $major, $contentStream, $changeToken, $properties, $checkinComment);
91 91
92 if ($result['status_code'] == 0) { 92 if ($result['status_code'] == 0) {
93 return $result['results']; 93 return $result['results'];