Commit 57920963051e21c7196ec6d1319e7fa89e67aac3

Authored by Charl Joseph Mert
2 parents 1f695900 94118e55

Merge branch 'edge' of github.com:ktgit/knowledgetree into edge

webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
... ... @@ -2,7 +2,8 @@
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 MUST 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,
  6 + it MUST be the current time.
6 7 2. Author/name will be the CMIS property createdBy
7 8 3. Title will be the CMIS property name
8 9 4. App:edited will be the CMIS property lastModifiedDate
... ... @@ -10,7 +11,8 @@
10 11 */
11 12  
12 13 /**
13   - * At any point where an Atom document of type Entry is sent or returned, it must be a valid Atom Entry document and conform to the guidelines below:
  14 + * At any point where an Atom document of type Entry is sent or returned, it must be a valid Atom Entry document and conform to
  15 + * the guidelines below:
14 16 1. Atom:Title will be best efforts by the repository. The repository should chose a property closest to Title.
15 17 2. App:edited will be CMIS:lastModifiedDate
16 18 3. Link with relation self will be the URI that returns the Atom Entry document
... ... @@ -19,16 +21,19 @@
19 21 6. For content tags
20 22 7. Documents with content
21 23 a. Leverage the src attribute to point to the same link as stream
22   -b. The repository SHOULD populate the summary tag with text that at best efforts represents the documents. For example, an HTML table containing the properties and their values for simple feed readers
23   -i. Other (Content-less document, Folder, Relationship, Type, etc) – best efforts at generating HTML text that represents the object. That text would normally go into the summary tag, but since there is no content, goes in the content tag.
  24 +b. The repository SHOULD populate the summary tag with text that at best efforts represents the documents.
  25 + For example, an HTML table containing the properties and their values for simple feed readers
  26 +i. Other (Content-less document, Folder, Relationship, Type, etc) – best efforts at generating HTML text that represents the object.
  27 + That text would normally go into the summary tag, but since there is no content, goes in the content tag.
24 28 8. If content src is specified, the summary SHOULD contain a text or html representation of the object.
25 29 9. Links will be used to provide URIs to CMIS functionality
26 30 10. Link relations may be omitted if the function is not allowed and that function would not show up on getAllowableActions.
27 31 11. Links may be omitted if the repository does not support that capability
28 32 12. All CMIS properties will be exposed in CMIS properties tag even if they are duplicated in an atom element
29 33  
30   -When POSTing an Atom Document, the atom fields take precedence over the CMIS property field for writeable properties. For example, atom:title will overwrite cmis:name
31   - */
  34 +When POSTing an Atom Document, the atom fields take precedence over the CMIS property field for writeable properties.
  35 +For example, atom:title will overwrite cmis:name
  36 +*/
32 37  
33 38 // load all available CMIS services
34 39 include_once CMIS_API . '/ktRepositoryService.inc.php';
... ... @@ -51,11 +56,11 @@ class KT_cmis_atom_service_objectbyid extends KT_cmis_atom_service {
51 56 $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService);
52 57 $objectId = $this->params[0];
53 58 $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt());
  59 +
  60 + // set Content-Type header
  61 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
54 62  
55   - $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId);
56   -
57   - // Expose the responseFeed
58   - $this->responseFeed = $feed;
  63 + $this->responseFeed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId);
59 64 }
60 65  
61 66 }
... ... @@ -71,11 +76,11 @@ class KT_cmis_atom_service_objectbypath extends KT_cmis_atom_service {
71 76 $ktapi =& KT_cmis_atom_service_helper::getKt();
72 77 $objectId = KT_cmis_atom_service_helper::getObjectId(explode('/', urldecode($this->params[0])), $ktapi, false);
73 78 $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt());
  79 +
  80 + // set Content-Type header
  81 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
74 82  
75   - $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId);
76   -
77   - // Expose the responseFeed
78   - $this->responseFeed = $feed;
  83 + $this->responseFeed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId);
79 84 }
80 85  
81 86 }
... ... @@ -151,10 +156,11 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
151 156 $feed = $this->getFolderChildrenFeed($NavigationService, $ObjectService, $repositoryId, $folderId, $folderName, $this->params[1]);
152 157 }
153 158 else {
  159 + // set Content-Type header
  160 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
154 161 $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $folderId);
155 162 }
156 163  
157   - // Expose the responseFeed
158 164 $this->responseFeed = $feed;
159 165 }
160 166  
... ... @@ -212,10 +218,10 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
212 218 $content = KT_cmis_atom_service_helper::getCmisContent($this->rawContent);
213 219 // NOTE not sure about the text type, will need testing, most content will be base64
214 220 $cmisContent = (isset($content['cmisra:base64'])
215   - ? $content['cmisra:base64']
216   - : ((isset($content['cmisra:text']))
217   - ? $content['cmisra:text']
218   - : null));
  221 + ? $content['cmisra:base64']
  222 + : ((isset($content['cmisra:text']))
  223 + ? $content['cmisra:text']
  224 + : null));
219 225  
220 226 $ObjectService = new KTObjectService(KT_cmis_atom_service_helper::getKt());
221 227  
... ... @@ -267,6 +273,9 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
267 273 $typeId = ucwords($cmisObjectProperties['cmis:objectTypeId']);
268 274 }
269 275  
  276 + // set Content-Type header
  277 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
  278 +
270 279 $this->setStatus(($action == 'create') ? self::STATUS_CREATED : self::STATUS_UPDATED);
271 280 $this->responseFeed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $newObjectId, 'POST');
272 281 }
... ... @@ -303,7 +312,9 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
303 312 $this->setStatus(self::STATUS_SERVER_ERROR);
304 313  
305 314 $feed = new KT_cmis_atom_responseFeed_GET(CMIS_APP_BASE_URI);
306   - // FIXME? this should perhaps use a different status code?
  315 + // FIXME? this should perhaps use a different status code? probably a 200 OK - see below
  316 + // however it should be 500 Internal Server Error if NO folders were deleted, which
  317 + // matches how the folder deletion currently works within KnowledgeTree
307 318 $feed->newField('title', 'Error: Failed to delete all objects in tree: ' . self::STATUS_SERVER_ERROR, $feed);
308 319  
309 320 foreach($response as $failed)
... ... @@ -323,6 +334,16 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
323 334 return null;
324 335 }
325 336  
  337 + /*
  338 + TODO ensure that status codes are returned as specified in section 3.9.3.2:
  339 +
  340 + • 200 OK if successful. Body contains entity describing the status 7900
  341 + • 202 Accepted, if accepted but deletion not yet taking place 7901
  342 + • 204 No Content, if successful with no content 7902
  343 + • 403 Forbidden, if permission is denied 7903
  344 + • 401 Unauthorized, if not authenticated 7904
  345 + • 500 Internal Server Error. The body SHOULD contain an entity describing the status
  346 + */
326 347 // success
327 348 $this->setStatus(self::STATUS_NO_CONTENT);
328 349 }
... ... @@ -395,7 +416,7 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
395 416 else if ($rootProperties['properties']['creationDate']['value'] != '0000-00-00 00:00:00') {
396 417 $updated = $rootProperties['properties']['creationDate']['value'];
397 418 }
398   -
  419 +
399 420 $feed->newField('updated', KT_cmis_atom_service_helper::formatDatestamp($updated), $feed);
400 421  
401 422 $link = $feed->newElement('link');
... ... @@ -419,6 +440,9 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
419 440 KT_cmis_atom_service_helper::createObjectFeed($feed, $entries, $folderName);
420 441  
421 442 $feed->newField('cmis:hasMoreItems', 'false', $feed);
  443 +
  444 + // set Content-Type header
  445 + $this->setHeader('Content-Type', 'application/atom+xml;type=feed');
422 446  
423 447 return $feed;
424 448 }
... ... @@ -468,10 +492,10 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service {
468 492 return null;
469 493 }
470 494  
471   - $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId);
472   -
473   - // Expose the responseFeed
474   - $this->responseFeed = $feed;
  495 + // set Content-Type header
  496 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
  497 +
  498 + $this->responseFeed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $objectId);
475 499 }
476 500  
477 501 /**
... ... @@ -525,10 +549,10 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
525 549 return null;
526 550 }
527 551  
528   - $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]);
529   -
530   - // Expose the responseFeed
531   - $this->responseFeed = $feed;
  552 + // set Content-Type header
  553 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
  554 +
  555 + $this->responseFeed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]);
532 556 }
533 557  
534 558 /**
... ... @@ -541,7 +565,6 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
541 565 public function DELETE_action()
542 566 {
543 567 // call the cancel checkout function
544   -
545 568 $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService);
546 569 $VersioningService = new KTVersioningService(KT_cmis_atom_service_helper::getKt());
547 570  
... ... @@ -554,7 +577,6 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
554 577 }
555 578  
556 579 $this->setStatus(self::STATUS_NO_CONTENT);
557   - $this->responseFeed = null;
558 580 }
559 581  
560 582 public function PUT_action()
... ... @@ -570,10 +592,10 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
570 592 $content = KT_cmis_atom_service_helper::getCmisContent($this->rawContent);
571 593 // NOTE not sure about the text type, will need testing, most content will be base64
572 594 $cmisContent = (isset($content['cmisra:base64'])
573   - ? $content['cmisra:base64']
574   - : ((isset($content['cmisra:text']))
575   - ? $content['cmisra:text']
576   - : null));
  595 + ? $content['cmisra:base64']
  596 + : ((isset($content['cmisra:text']))
  597 + ? $content['cmisra:text']
  598 + : null));
577 599  
578 600 // if we haven't found it now, the hack begins - retrieve the EXISTING content and submit this as the contentStream
579 601 // this is needed because KnowledgeTree will not accept a checkin without a content stream but CMISSpaces (and possibly
... ... @@ -598,11 +620,11 @@ class KT_cmis_atom_service_pwc extends KT_cmis_atom_service {
598 620 $this->responseFeed = KT_cmis_atom_service_helper::getErrorFeed($this, $this->getStatusCode($e), $e->getMessage());
599 621 return null;
600 622 }
601   -
602   - $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]);
603   -
604   - // Expose the responseFeed
605   - $this->responseFeed = $feed;
  623 +
  624 + // set Content-Type header
  625 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
  626 +
  627 + $this->responseFeed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $this->params[0]);
606 628 }
607 629  
608 630 }
... ... @@ -669,7 +691,9 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service {
669 691  
670 692 $feed->newField('cmis:hasMoreItems', 'false', $feed);
671 693  
672   - // Expose the responseFeed
  694 + // set Content-Type header
  695 + $this->setHeader('Content-Type', 'application/atom+xml;type=feed');
  696 +
673 697 $this->responseFeed = $feed;
674 698 }
675 699  
... ... @@ -701,11 +725,11 @@ class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service {
701 725 return null;
702 726 }
703 727  
  728 + // set Content-Type header
  729 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
  730 +
704 731 $this->setStatus(self::STATUS_CREATED);
705   - $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['cmis:objectId'], 'POST');
706   -
707   - // Expose the responseFeed
708   - $this->responseFeed = $feed;
  732 + $this->responseFeed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $cmisObjectProperties['cmis:objectId'], 'POST');
709 733 }
710 734  
711 735 }
... ... @@ -728,11 +752,11 @@ class KT_cmis_atom_service_types extends KT_cmis_atom_service {
728 752 return null;
729 753 }
730 754  
731   - $type = ((empty($this->params[0])) ? 'all' : $this->params[0]);
732   - $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types);
  755 + // set Content-Type header
  756 + $this->setHeader('Content-Type', 'application/atom+xml;type=feed');
733 757  
734   - // Expose the responseFeed
735   - $this->responseFeed = $feed;
  758 + $type = ((empty($this->params[0])) ? 'all' : $this->params[0]);
  759 + $this->responseFeed = KT_cmis_atom_service_helper::getTypeFeed($type, $types);
736 760 }
737 761  
738 762 }
... ... @@ -756,10 +780,12 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service {
756 780 return null;
757 781 }
758 782  
759   - $feed = KT_cmis_atom_service_helper::getTypeFeed($type, array($typeDefinition['attributes']));
760   -
761   - // Expose the responseFeed
762   - $this->responseFeed=$feed;
  783 + // NOTE will need to choose feed/entry for type appropriately when this function supports the defaults of getting base types
  784 + // or child types when no type specified
  785 + // set Content-Type header
  786 + $this->setHeader('Content-Type', 'application/atom+xml;type=entry');
  787 +
  788 + $this->responseFeed = KT_cmis_atom_service_helper::getTypeFeed($type, array($typeDefinition['attributes']));
763 789 }
764 790  
765 791 /**
... ... @@ -784,19 +810,24 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service {
784 810 // links
785 811 $link = $feed->newElement('link');
786 812 $link->appendChild($feed->newAttr('rel','first'));
787   - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1] . '?pageNo=1&pageSize=0'));
  813 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1]
  814 + . '?pageNo=1&pageSize=0'));
788 815 $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed'));
789 816  
790 817 $link = $feed->newElement('link');
791 818 $link->appendChild($feed->newAttr('rel','last'));
792 819 // TODO set page number correctly - to be done when we support paging the the API
793   - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1] . '?pageNo=1&pageSize=0'));
  820 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1]
  821 + . '?pageNo=1&pageSize=0'));
794 822 $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed'));
795 823  
796 824 // Since types do not have associated dates, we don't know the time last updated, so we use current
797 825 $feed->newField('updated', KT_cmis_atom_service_helper::formatDatestamp(), $feed);
798 826 $feed->newField('cmis:hasMoreItems', 'false', $feed);
799   -
  827 +
  828 + // set Content-Type header
  829 + $this->setHeader('Content-Type', 'application/atom+xml;type=feed');
  830 +
800 831 return $feed;
801 832 }
802 833  
... ...
webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
... ... @@ -774,8 +774,7 @@ class KT_cmis_atom_service_helper {
774 774 $response = $ObjectService->getProperties($repositoryId, $service->params[0], false, false);
775 775 }
776 776 catch (Exception $e) {
777   - $feed = KT_cmis_atom_service_helper::getErrorFeed($service, $service->getStatusCode($e), $e->getMessage());
778   - $service->responseFeed = $feed;
  777 + $service->responseFeed = KT_cmis_atom_service_helper::getErrorFeed($service, $service->getStatusCode($e), $e->getMessage());
779 778 return null;
780 779 }
781 780  
... ...
webservice/classes/atompub/cmis/KT_cmis_atom_response.inc.php
... ... @@ -19,21 +19,6 @@ 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   - }
37 22  
38 23 // TODO try to get rid of this function
39 24 function appendChild($element)
... ...
webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php
... ... @@ -9,6 +9,13 @@ class KT_cmis_atom_server extends KT_atom_server {
9 9 public $repositoryInfo;
10 10 public $headersSet = false;
11 11  
  12 + /**
  13 + * Performs actions which must take place before the response document is rendered
  14 + * What is done here will determine certain aspects of how the document is rendered
  15 + *
  16 + * @param service $doc
  17 + * @return boolean
  18 + */
12 19 protected function hook_beforeDocRender($doc)
13 20 {
14 21 if ($doc->isContentDownload())
... ... @@ -35,6 +42,9 @@ class KT_cmis_atom_server extends KT_atom_server {
35 42  
36 43 return false;
37 44 }
  45 + else {
  46 + $this->headersSet = $doc->checkHeaders();
  47 + }
38 48  
39 49 return true;
40 50 }
... ... @@ -60,7 +70,7 @@ class KT_cmis_atom_server extends KT_atom_server {
60 70 $service = new KT_cmis_atom_serviceDoc(KT_APP_BASE_URI);
61 71  
62 72 header('Content-Type: application/atomsvc+xml;charset=UTF-8');
63   - header('Content-Disposition', 'attachment;filename="knowledgetree_cmis"');
  73 + header('Content-Disposition: attachment;filename="knowledgetree_cmis"');
64 74 $this->headersSet = true;
65 75  
66 76 foreach($this->services as $workspace => $collection)
... ...
webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php
... ... @@ -8,6 +8,7 @@ class KT_cmis_atom_service extends KT_atom_service {
8 8  
9 9 protected $serviceType = null;
10 10 protected $contentDownload = false;
  11 + protected $responseHeaders = false;
11 12 // status code mapping is for mapping exceptions thrown by the API to their appropriate
12 13 // HTTP error status codes (see section 3.2.4.1)
13 14 static protected $statusCodeMapping = array('InvalidArgumentException' => self::STATUS_BAD_REQUEST,
... ... @@ -71,6 +72,17 @@ class KT_cmis_atom_service extends KT_atom_service {
71 72 if (!empty($header)) {
72 73 header($header . ': ' . $value);
73 74 }
  75 +
  76 + $this->responseHeaders = true;
  77 + }
  78 +
  79 + /**
  80 + * Checks whether the service has set its own headers
  81 + *
  82 + * TODO we may want to rather use setHeader to collect the headers and then we return them here and save some code
  83 + */
  84 + public function checkHeaders() {
  85 + return $this->responseHeaders;
74 86 }
75 87  
76 88 public function getStatusCode($exception)
... ...