Commit f3438102dd2a8d7b0796e0cfdee57224bab544a3
1 parent
c8de4448
Beginnings of link media types and complete atom node data
Story ID:2713417. CMIS working with PHP client Committed by: Paul Barrett
Showing
4 changed files
with
122 additions
and
45 deletions
webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | /** |
| 4 | 4 | * Any feed must be a valid atom Feed document and conform to the guidelines below: |
| 5 | -1. Updated will be the latest time the folder or its contents was updated. If unknown by the underlying repository, it should be the current time. | |
| 5 | +1. Updated will be the latest time the folder or its contents was updated. If unknown by the underlying repository, it MUST be the current time. | |
| 6 | 6 | 2. Author/name will be the CMIS property createdBy |
| 7 | 7 | 3. Title will be the CMIS property name |
| 8 | 8 | 4. App:edited will be the CMIS property lastModifiedDate |
| ... | ... | @@ -145,14 +145,12 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { |
| 145 | 145 | $folderId = $this->params[0]; |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | - if (!empty($this->params[1]) && (($this->params[1] == 'children') || ($this->params[1] == 'descendants'))) | |
| 149 | - { | |
| 148 | + $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); | |
| 149 | + if (!empty($this->params[1]) && (($this->params[1] == 'children') || ($this->params[1] == 'descendants'))) { | |
| 150 | 150 | $NavigationService = new KTNavigationService(KT_cmis_atom_service_helper::getKt()); |
| 151 | - $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $this->params[1]); | |
| 151 | + $feed = $this->getFolderChildrenFeed($NavigationService, $ObjectService, $repositoryId, $folderId, $folderName, $this->params[1]); | |
| 152 | 152 | } |
| 153 | - else | |
| 154 | - { | |
| 155 | - $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt()); | |
| 153 | + else { | |
| 156 | 154 | $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $folderId); |
| 157 | 155 | } |
| 158 | 156 | |
| ... | ... | @@ -305,6 +303,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { |
| 305 | 303 | $this->setStatus(self::STATUS_SERVER_ERROR); |
| 306 | 304 | |
| 307 | 305 | $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI); |
| 306 | + // FIXME? this should perhaps use a different status code? | |
| 308 | 307 | $feed->newField('title', 'Error: Failed to delete all objects in tree: ' . self::STATUS_SERVER_ERROR, $feed); |
| 309 | 308 | |
| 310 | 309 | foreach($response as $failed) |
| ... | ... | @@ -337,8 +336,17 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { |
| 337 | 336 | * @param string $feedType children or descendants |
| 338 | 337 | * @return string CMIS AtomPub feed |
| 339 | 338 | */ |
| 340 | - private function getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $feedType = 'children') | |
| 339 | + private function getFolderChildrenFeed(&$NavigationService, &$ObjectService, $repositoryId, $folderId, $folderName, $feedType = 'children') | |
| 341 | 340 | { |
| 341 | + // fetch properties of parent folder for which children/descendants are being retrieved | |
| 342 | + try { | |
| 343 | + $rootProperties = $ObjectService->getProperties($repositoryId, $folderId); | |
| 344 | + } | |
| 345 | + catch (Exception $e) { | |
| 346 | + $this->responseFeed = KT_cmis_atom_service_helper::getErrorFeed($this, $this->getStatusCode($e), $e->getMessage()); | |
| 347 | + return null; | |
| 348 | + } | |
| 349 | + | |
| 342 | 350 | if ($feedType == 'children') { |
| 343 | 351 | try { |
| 344 | 352 | $entries = $NavigationService->getChildren($repositoryId, $folderId, false, false); |
| ... | ... | @@ -373,30 +381,39 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { |
| 373 | 381 | |
| 374 | 382 | $feed->newField('title', $folderName . ' ' . ucwords($feedType), $feed); |
| 375 | 383 | |
| 376 | - // TODO dynamic? | |
| 377 | 384 | $feedElement = $feed->newField('author'); |
| 378 | - $element = $feed->newField('name', 'System', $feedElement); | |
| 385 | + $element = $feed->newField('name', $rootProperties['properties']['createdBy']['value'], $feedElement); | |
| 379 | 386 | $feed->appendChild($feedElement); |
| 380 | 387 | |
| 381 | 388 | // id |
| 382 | 389 | $feed->newField('id', 'urn:uuid:' . $folderId . '-' . $feedType, $feed); |
| 383 | 390 | |
| 384 | - // TODO get actual most recent update time, only use current if no other available | |
| 385 | - $feed->newField('updated', KT_cmis_atom_service_helper::formatDatestamp(), $feed); | |
| 391 | + $updated = null; | |
| 392 | + if ($rootProperties['properties']['lastModificationDate']['value'] != '0000-00-00 00:00:00') { | |
| 393 | + $updated = $rootProperties['properties']['lastModificationDate']['value']; | |
| 394 | + } | |
| 395 | + else if ($rootProperties['properties']['creationDate']['value'] != '0000-00-00 00:00:00') { | |
| 396 | + $updated = $rootProperties['properties']['creationDate']['value']; | |
| 397 | + } | |
| 398 | + | |
| 399 | + $feed->newField('updated', KT_cmis_atom_service_helper::formatDatestamp($updated), $feed); | |
| 386 | 400 | |
| 387 | 401 | $link = $feed->newElement('link'); |
| 388 | 402 | $link->appendChild($feed->newAttr('rel', 'self')); |
| 389 | 403 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/' . $folderId . '/' . $feedType)); |
| 390 | 404 | $feed->appendChild($link); |
| 391 | 405 | |
| 406 | + // TODO this link must specify the workspace | |
| 392 | 407 | $link = $feed->newElement('link'); |
| 393 | 408 | $link->appendChild($feed->newAttr('rel', 'service')); |
| 394 | 409 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'servicedocument')); |
| 410 | + $link->appendChild($feed->newAttr('type', 'application/atomsvc+xml')); | |
| 395 | 411 | $feed->appendChild($link); |
| 396 | 412 | |
| 397 | 413 | $link = $feed->newElement('link'); |
| 398 | 414 | $link->appendChild($feed->newAttr('rel', 'via')); |
| 399 | 415 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/' . $folderId)); |
| 416 | + $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=entry')); | |
| 400 | 417 | $feed->appendChild($link); |
| 401 | 418 | |
| 402 | 419 | KT_cmis_atom_service_helper::createObjectFeed($feed, $entries, $folderName); |
| ... | ... | @@ -553,10 +570,10 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service { |
| 553 | 570 | $content = KT_cmis_atom_service_helper::getCmisContent($this->rawContent); |
| 554 | 571 | // NOTE not sure about the text type, will need testing, most content will be base64 |
| 555 | 572 | $cmisContent = (isset($content['cmisra:base64']) |
| 556 | - ? $content['cmisra:base64'] | |
| 557 | - : ((isset($content['cmisra:text'])) | |
| 558 | - ? $content['cmisra:text'] | |
| 559 | - : null)); | |
| 573 | + ? $content['cmisra:base64'] | |
| 574 | + : ((isset($content['cmisra:text'])) | |
| 575 | + ? $content['cmisra:text'] | |
| 576 | + : null)); | |
| 560 | 577 | |
| 561 | 578 | // if we haven't found it now, the hack begins - retrieve the EXISTING content and submit this as the contentStream |
| 562 | 579 | // this is needed because KnowledgeTree will not accept a checkin without a content stream but CMISSpaces (and possibly |
| ... | ... | @@ -618,14 +635,14 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { |
| 618 | 635 | |
| 619 | 636 | $feed->newField('title', 'Checked out Documents', $feed); |
| 620 | 637 | |
| 621 | - // TODO dynamic? | |
| 638 | + // Since checked out documents do not necessarily share the same creator, we use a default value | |
| 622 | 639 | $feedElement = $feed->newField('author'); |
| 623 | - $element = $feed->newField('name', 'admin', $feedElement); | |
| 640 | + $element = $feed->newField('name', 'Administrator', $feedElement); | |
| 624 | 641 | $feed->appendChild($feedElement); |
| 625 | 642 | |
| 626 | 643 | $feed->appendChild($feed->newElement('id', 'urn:uuid:checkedout')); |
| 627 | 644 | |
| 628 | - // TODO get actual most recent update time, only use current if no other available | |
| 645 | + // Since checked out documents are not necessarily from a single folder, we don't know the time last updated, so we use current | |
| 629 | 646 | $feed->appendChild($feed->newElement('updated', KT_cmis_atom_service_helper::formatDatestamp())); |
| 630 | 647 | |
| 631 | 648 | $link = $feed->newElement('link'); |
| ... | ... | @@ -671,8 +688,8 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { |
| 671 | 688 | // in the helper code, but I don't feel that throwing an exception is necessary or always wanted; |
| 672 | 689 | // alternative is to send the name of the Exception but not an instance, and do an is_a check on the other side, |
| 673 | 690 | // but since it will only be needed to this and similar calls, it seems wasteful to do that for every other case |
| 674 | - $this->responseFeed = KT_cmis_atom_service_helper::getErrorFeed($this, $this->getStatusCode(new InvalidArgumentException()), | |
| 675 | - 'No object was specified for checkout'); | |
| 691 | + $this->responseFeed = KT_cmis_atom_service_helper::getErrorFeed($this, $this->getStatusCode(new InvalidArgumentException()), | |
| 692 | + 'No object was specified for checkout'); | |
| 676 | 693 | return null; |
| 677 | 694 | } |
| 678 | 695 | |
| ... | ... | @@ -683,7 +700,7 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service { |
| 683 | 700 | $this->responseFeed = KT_cmis_atom_service_helper::getErrorFeed($this, $this->getStatusCode($e), $e->getMessage()); |
| 684 | 701 | return null; |
| 685 | 702 | } |
| 686 | - | |
| 703 | + | |
| 687 | 704 | $this->setStatus(self::STATUS_CREATED); |
| 688 | 705 | $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['cmis:objectId'], 'POST'); |
| 689 | 706 | |
| ... | ... | @@ -776,6 +793,7 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service { |
| 776 | 793 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1] . '?pageNo=1&pageSize=0')); |
| 777 | 794 | $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed')); |
| 778 | 795 | |
| 796 | + // Since types do not have associated dates, we don't know the time last updated, so we use current | |
| 779 | 797 | $feed->newField('updated', KT_cmis_atom_service_helper::formatDatestamp(), $feed); |
| 780 | 798 | $feed->newField('cmis:hasMoreItems', 'false', $feed); |
| 781 | 799 | ... | ... |
webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
| ... | ... | @@ -54,6 +54,7 @@ class KT_cmis_atom_service_helper { |
| 54 | 54 | * @return string CMIS AtomPub feed |
| 55 | 55 | */ |
| 56 | 56 | // TODO enable this to work on an existing set of object properties if submitted |
| 57 | + // TODO this might be better as an entry rather than a feed - see Alfresco example | |
| 57 | 58 | static public function getObjectFeed(&$service, $ObjectService, $repositoryId, $objectId, $method = 'GET') |
| 58 | 59 | { |
| 59 | 60 | self::$repositoryId = $repositoryId; |
| ... | ... | @@ -173,9 +174,8 @@ class KT_cmis_atom_service_helper { |
| 173 | 174 | { |
| 174 | 175 | $type = $cmisEntry['properties']['objectTypeId']['value']; |
| 175 | 176 | |
| 176 | - // TODO dynamic actual creator name | |
| 177 | 177 | $responseElement = $feed->newField('author'); |
| 178 | - $element = $feed->newField('name', 'admin', $responseElement); | |
| 178 | + $element = $feed->newField('name', $cmisEntry['properties']['createdBy']['value'], $responseElement); | |
| 179 | 179 | $entry->appendChild($responseElement); |
| 180 | 180 | |
| 181 | 181 | $typeString = str_replace('cmis:', '', $type); |
| ... | ... | @@ -206,6 +206,7 @@ class KT_cmis_atom_service_helper { |
| 206 | 206 | $link->appendChild($feed->newAttr('rel', 'edit')); |
| 207 | 207 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString |
| 208 | 208 | . '/' . $cmisEntry['properties']['objectId']['value'])); |
| 209 | + $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=entry')); | |
| 209 | 210 | $entry->appendChild($link); |
| 210 | 211 | |
| 211 | 212 | if ((strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:document') |
| ... | ... | @@ -218,14 +219,6 @@ class KT_cmis_atom_service_helper { |
| 218 | 219 | . '/' . $cmisEntry['properties']['objectId']['value'] |
| 219 | 220 | . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); |
| 220 | 221 | $entry->appendChild($link); |
| 221 | - | |
| 222 | - $link = $feed->newElement('link'); | |
| 223 | - $link->appendChild($feed->newAttr('rel', 'enclosure')); | |
| 224 | - $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value'])); | |
| 225 | - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString | |
| 226 | - . '/' . $cmisEntry['properties']['objectId']['value'] | |
| 227 | - . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); | |
| 228 | - $entry->appendChild($link); | |
| 229 | 222 | } |
| 230 | 223 | |
| 231 | 224 | // according to spec this MUST be present, but spec says that links for function which are not supported |
| ... | ... | @@ -255,6 +248,7 @@ class KT_cmis_atom_service_helper { |
| 255 | 248 | $link->appendChild($feed->newAttr('rel', 'up')); |
| 256 | 249 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/' |
| 257 | 250 | . $cmisEntry['properties']['parentId']['value'])); |
| 251 | + $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=entry')); | |
| 258 | 252 | $entry->appendChild($link); |
| 259 | 253 | } |
| 260 | 254 | |
| ... | ... | @@ -267,13 +261,16 @@ class KT_cmis_atom_service_helper { |
| 267 | 261 | . $typeString |
| 268 | 262 | . '/' . $cmisEntry['properties']['objectId']['value'] |
| 269 | 263 | . '/children')); |
| 264 | + $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed')); | |
| 270 | 265 | $entry->appendChild($link); |
| 266 | + | |
| 271 | 267 | $link = $feed->newElement('link'); |
| 272 | 268 | $link->appendChild($feed->newAttr('rel', 'down')); |
| 273 | 269 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' |
| 274 | 270 | . $typeString |
| 275 | 271 | . '/' . $cmisEntry['properties']['objectId']['value'] |
| 276 | 272 | . '/descendants')); |
| 273 | + $link->appendChild($feed->newAttr('type', 'application/cmistree+xml')); | |
| 277 | 274 | $entry->appendChild($link); |
| 278 | 275 | |
| 279 | 276 | // TODO add folder tree link when we have folder tree implemented |
| ... | ... | @@ -323,18 +320,33 @@ class KT_cmis_atom_service_helper { |
| 323 | 320 | $link = $feed->newElement('link'); |
| 324 | 321 | $link->appendChild($feed->newAttr('rel', 'describedby')); |
| 325 | 322 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . $type)); |
| 323 | + $link->appendChild($feed->newAttr('type', 'application/atomsvc+xml')); | |
| 326 | 324 | $entry->appendChild($link); |
| 327 | 325 | |
| 326 | + // TODO this link must specify the workspace | |
| 328 | 327 | $link = $feed->newElement('link'); |
| 329 | 328 | $link->appendChild($feed->newAttr('rel', 'service')); |
| 330 | 329 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument')); |
| 330 | + $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=entry')); | |
| 331 | 331 | $entry->appendChild($link); |
| 332 | 332 | |
| 333 | - // TODO proper date | |
| 334 | - $entry->appendChild($feed->newField('published', self::formatDatestamp())); | |
| 333 | + $updated = null; | |
| 334 | + $published = null; | |
| 335 | + if ($cmisEntry['properties']['lastModificationDate']['value'] != '0000-00-00 00:00:00') { | |
| 336 | + $updated = $cmisEntry['properties']['lastModificationDate']['value']; | |
| 337 | + } | |
| 338 | + else if ($cmisEntry['properties']['creationDate']['value'] != '0000-00-00 00:00:00') { | |
| 339 | + $updated = $cmisEntry['properties']['creationDate']['value']; | |
| 340 | + } | |
| 341 | + | |
| 342 | + if ($cmisEntry['properties']['creationDate']['value'] != '0000-00-00 00:00:00') { | |
| 343 | + $published = $cmisEntry['properties']['creationDate']['value']; | |
| 344 | + } | |
| 345 | + | |
| 346 | + $entry->appendChild($feed->newField('published', self::formatDatestamp($published))); | |
| 335 | 347 | $entry->appendChild($feed->newElement('summary', $cmisEntry['properties']['name']['value'])); |
| 336 | 348 | $entry->appendChild($feed->newElement('title', $cmisEntry['properties']['name']['value'])); |
| 337 | - $entry->appendChild($feed->newField('updated', self::formatDatestamp())); | |
| 349 | + $entry->appendChild($feed->newField('updated', self::formatDatestamp($updated))); | |
| 338 | 350 | |
| 339 | 351 | // main CMIS entry |
| 340 | 352 | $objectElement = $feed->newElement('cmisra:object'); |
| ... | ... | @@ -343,7 +355,14 @@ class KT_cmis_atom_service_helper { |
| 343 | 355 | |
| 344 | 356 | // TODO check determination of when to add app:edited tag |
| 345 | 357 | // if ($method == 'POST') { |
| 346 | - $entry->appendChild($feed->newElement('app:edited', self::formatDatestamp())); | |
| 358 | + $edited = null; | |
| 359 | + if ($cmisEntry['properties']['lastModificationDate']['value'] != '0000-00-00 00:00:00') { | |
| 360 | + $edited = $cmisEntry['properties']['lastModificationDate']['value']; | |
| 361 | + } | |
| 362 | + else if ($cmisEntry['properties']['creationDate']['value'] != '0000-00-00 00:00:00') { | |
| 363 | + $edited = $cmisEntry['properties']['creationDate']['value']; | |
| 364 | + } | |
| 365 | + $entry->appendChild($feed->newElement('app:edited', self::formatDatestamp($edited))); | |
| 347 | 366 | // } |
| 348 | 367 | |
| 349 | 368 | // TODO pathSegment entry |
| ... | ... | @@ -424,17 +443,20 @@ class KT_cmis_atom_service_helper { |
| 424 | 443 | // TODO set page number correctly - to be done when we support paging the the API |
| 425 | 444 | |
| 426 | 445 | // author |
| 427 | - // TODO generate this dynamically (based on???)\ | |
| 446 | + // since types are/should be always created by system admin, we use a default value - this may be set later but for now is unset | |
| 447 | + // for a type which is not an instantiated object | |
| 428 | 448 | $feedElement = $feed->newField('author'); |
| 429 | - $element = $feed->newField('name', 'admin', $feedElement); | |
| 449 | + $element = $feed->newField('name', 'Administrator', $feedElement); | |
| 430 | 450 | $feed->appendChild($feedElement); |
| 431 | 451 | |
| 432 | 452 | foreach($types as $type) |
| 433 | 453 | { |
| 434 | 454 | $entry = $feed->newEntry(); |
| 435 | 455 | |
| 456 | + // since types are/should be always created by system admin, we use a default value - this may be set later but for now is unset | |
| 457 | + // for a type which is not an instantiated object | |
| 436 | 458 | $feedElement = $feed->newField('author'); |
| 437 | - $element = $feed->newField('name', 'admin', $feedElement); | |
| 459 | + $element = $feed->newField('name', 'Administrator', $feedElement); | |
| 438 | 460 | $entry->appendChild($feedElement); |
| 439 | 461 | $feedElement = $feed->newField('content', 'Type definition for ' . $type['baseId']); |
| 440 | 462 | $entry->appendChild($feedElement); |
| ... | ... | @@ -449,17 +471,20 @@ class KT_cmis_atom_service_helper { |
| 449 | 471 | // TODO type link MUST point to base type |
| 450 | 472 | // KnowledgeTree currently only supports base types so this is not important |
| 451 | 473 | // at the present time as it will always point at the base type. |
| 474 | + | |
| 452 | 475 | $link = $feed->newElement('link'); |
| 453 | 476 | $link->appendChild($feed->newAttr('rel','type')); |
| 454 | 477 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['baseId']))); |
| 455 | 478 | $entry->appendChild($link); |
| 479 | + | |
| 456 | 480 | $link = $feed->newElement('link'); |
| 457 | 481 | $link->appendChild($feed->newAttr('rel','repository')); |
| 458 | 482 | $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument')); |
| 459 | 483 | $entry->appendChild($link); |
| 460 | 484 | |
| 461 | - $entry->appendChild($feed->newElement('summary', 'Summary for ' . $type['baseId'] . ' type')); | |
| 462 | - $entry->appendChild($feed->newElement('title', $type['baseId'])); | |
| 485 | + $entry->appendChild($feed->newElement('summary', 'Summary for ' . $type['displayName'] . ' type')); | |
| 486 | + $entry->appendChild($feed->newElement('title', $type['displayName'])); | |
| 487 | + // Since types do not have associated dates, we don't know the time last updated, so we use current | |
| 463 | 488 | $entry->appendChild($feed->newElement('updated', self::formatDatestamp())); |
| 464 | 489 | |
| 465 | 490 | $objectElement = $feed->newElement('cmisra:type'); |
| ... | ... | @@ -479,13 +504,14 @@ class KT_cmis_atom_service_helper { |
| 479 | 504 | // appear to be seen by browser based clients (I am not sure of non-browser clients) |
| 480 | 505 | // NOTE just added a check and only send back the header containing 404, no text, and this works, we get a 404 header |
| 481 | 506 | // plus a readable AtomPub response |
| 507 | + // THEORY is that Apache is generating the html response when given a '404 Not Found' header, overriding the desired output | |
| 482 | 508 | if (!strstr($status, '404')) { |
| 483 | 509 | $service->setStatus($status); |
| 484 | 510 | } |
| 485 | 511 | else { |
| 486 | 512 | $service->setStatus('404'); |
| 487 | 513 | } |
| 488 | - | |
| 514 | + | |
| 489 | 515 | $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI); |
| 490 | 516 | |
| 491 | 517 | $feed->newField('title', 'Error: ' . $status, $feed); |
| ... | ... | @@ -697,13 +723,21 @@ class KT_cmis_atom_service_helper { |
| 697 | 723 | } |
| 698 | 724 | } |
| 699 | 725 | } |
| 726 | + | |
| 700 | 727 | return self::$ktapi; |
| 701 | 728 | } |
| 702 | 729 | |
| 703 | 730 | // TODO adjust for time zones? |
| 704 | 731 | static public function formatDatestamp($time = null) |
| 705 | 732 | { |
| 706 | - if (is_null($time)) $time = time(); | |
| 733 | + if (is_null($time)) { | |
| 734 | + $time = time(); | |
| 735 | + } | |
| 736 | + else { | |
| 737 | + // assumes format is 'yyyy-mm-dd hh:mm:ss' or some other string representation, and not a unix timestamp | |
| 738 | + $time = strtotime($time); | |
| 739 | + } | |
| 740 | + | |
| 707 | 741 | return date('Y-m-d H:i:s', $time); |
| 708 | 742 | } |
| 709 | 743 | |
| ... | ... | @@ -768,6 +802,7 @@ class KT_cmis_atom_service_helper { |
| 768 | 802 | $service->setHeader('Content-type', $response['properties']['contentStreamMimeType']['value'] . ';charset=utf-8'); |
| 769 | 803 | } |
| 770 | 804 | else { |
| 805 | + // FIXME what should the default type be? application/unknown? | |
| 771 | 806 | $service->setHeader('Content-type', 'text/plain;charset=utf-8'); |
| 772 | 807 | } |
| 773 | 808 | ... | ... |
webservice/classes/atompub/cmis/KT_cmis_atom_response.inc.php
| ... | ... | @@ -19,6 +19,21 @@ class KT_cmis_atom_response extends KT_atom_response { |
| 19 | 19 | { |
| 20 | 20 | return $this->workspace; |
| 21 | 21 | } |
| 22 | + | |
| 23 | + protected function constructFeedHeader(){ | |
| 24 | + $feed = $this->newElement('feed'); | |
| 25 | + $feed->appendChild($this->newAttr('xmlns','http://www.w3.org/2005/Atom')); | |
| 26 | + $this->feed = &$feed; | |
| 27 | + $this->DOM->appendChild($this->feed); | |
| 28 | + } | |
| 29 | + | |
| 30 | + public function &newEntry() | |
| 31 | + { | |
| 32 | + $entry = $this->newElement('atom:entry'); | |
| 33 | + $this->feed->appendChild($entry); | |
| 34 | + | |
| 35 | + return $entry; | |
| 36 | + } | |
| 22 | 37 | |
| 23 | 38 | // TODO try to get rid of this function |
| 24 | 39 | function appendChild($element) | ... | ... |
webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php
| ... | ... | @@ -22,14 +22,14 @@ class KT_cmis_atom_server extends KT_atom_server { |
| 22 | 22 | header('Expires:'); |
| 23 | 23 | header('Pragma:'); |
| 24 | 24 | |
| 25 | - // prevent output of standard text/xml header | |
| 25 | + // prevent output of regular headers for AtomPub responses | |
| 26 | 26 | $this->headersSet = true; |
| 27 | 27 | |
| 28 | 28 | return false; |
| 29 | 29 | } |
| 30 | 30 | else if ($doc->notModified()) |
| 31 | 31 | { |
| 32 | - // prevent output of standard text/xml header | |
| 32 | + // prevent output of regular headers for AtomPub responses | |
| 33 | 33 | $this->headersSet = true; |
| 34 | 34 | $this->setNoContent(true); |
| 35 | 35 | |
| ... | ... | @@ -114,6 +114,15 @@ class KT_cmis_atom_server extends KT_atom_server { |
| 114 | 114 | } |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | + // TODO add other links once their services are supported | |
| 118 | + // links | |
| 119 | + $link = $service->newElement('atom:link'); | |
| 120 | + $link->appendChild($service->newAttr('title', 'root descendants')); | |
| 121 | + $link->appendChild($service->newAttr('type', 'application/cmistree+xml')); | |
| 122 | + $link->appendChild($service->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/rootdescendants')); | |
| 123 | + $link->appendChild($service->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/Root%20Folder/descendants')); | |
| 124 | + $ws->appendChild($link); | |
| 125 | + | |
| 117 | 126 | // uri templates - getObjectById, getObjectByPath, getTypeById |
| 118 | 127 | $ws->appendChild($service->uriTemplate('objectbyid', $workspace)); |
| 119 | 128 | $ws->appendChild($service->uriTemplate('objectbypath', $workspace)); | ... | ... |