Commit 9fa9c1c979ebca7cc657786aa3de0424b4962a8f

Authored by Paul Barrett
1 parent 8c4b9b73

Update getTypeDefinition

Story ID:2295472. Update KT CMIS implementation to 1.0 compliance

Committed by: Paul Barrett
lib/api/ktcmis/classes/CMISObject.inc.php
@@ -78,6 +78,9 @@ abstract class CMISObject { @@ -78,6 +78,9 @@ abstract class CMISObject {
78 78
79 public function __construct() 79 public function __construct()
80 { 80 {
  81 + // set properties shared by all objects of this type
  82 + $this->_setSharedProperties();
  83 +
81 // $propertyDef = new PropertyDefinition(); 84 // $propertyDef = new PropertyDefinition();
82 // $this->properties[] = $propertyDef; 85 // $this->properties[] = $propertyDef;
83 } 86 }
@@ -159,6 +162,16 @@ abstract class CMISObject { @@ -159,6 +162,16 @@ abstract class CMISObject {
159 { 162 {
160 // override in child classes 163 // override in child classes
161 } 164 }
  165 +
  166 + /**
  167 + * Sets properties which are shared between all objects of this type
  168 + */
  169 + protected function _setSharedProperties()
  170 + {
  171 + $this->_setPropertyInternal('objectTypeId', strtolower($this->getAttribute('id')));
  172 + // Needed to distinguish type
  173 + $this->_setPropertyInternal('baseTypeId', strtolower($this->getAttribute('id')));
  174 + }
162 175
163 } 176 }
164 177
lib/api/ktcmis/ktRepositoryService.inc.php
@@ -165,25 +165,14 @@ class KTRepositoryService extends KTCMISBase { @@ -165,25 +165,14 @@ class KTRepositoryService extends KTCMISBase {
165 public function getTypeDefinition($repositoryId, $typeId) 165 public function getTypeDefinition($repositoryId, $typeId)
166 { 166 {
167 try { 167 try {
168 - $typeDefinitionResult = $this->RepositoryService->getTypeDefinition($repositoryId, $typeId); 168 + $typeDefinition = $this->RepositoryService->getTypeDefinition($repositoryId, $typeId);
169 } 169 }
170 - catch (Exception $e)  
171 - {  
172 - return array(  
173 - "status_code" => 1,  
174 - "message" => $e->getMessage()  
175 - ); 170 + catch (Exception $e) {
  171 + // propogate upward
  172 + throw $e;
176 } 173 }
177 -  
178 - // format as array style output  
179 - // NOTE only concerned with attributes at this time  
180 - // TODO add support for properties  
181 - $typeDefinition = $typeDefinitionResult['attributes'];  
182 -  
183 - return array (  
184 - "status_code" => 0,  
185 - "results" => $typeDefinition  
186 - ); 174 +
  175 + return $typeDefinition;
187 } 176 }
188 177
189 } 178 }
lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
@@ -98,7 +98,7 @@ class CMISDocumentObject extends CMISObject { @@ -98,7 +98,7 @@ class CMISDocumentObject extends CMISObject {
98 } 98 }
99 } 99 }
100 100
101 - // TODO throw exception if unable to create? 101 + parent::__construct();
102 } 102 }
103 103
104 // TODO abstract shared stuff to base class where possible 104 // TODO abstract shared stuff to base class where possible
@@ -124,10 +124,6 @@ class CMISDocumentObject extends CMISObject { @@ -124,10 +124,6 @@ class CMISDocumentObject extends CMISObject {
124 // also ktapidocument::get_download_url 124 // also ktapidocument::get_download_url
125 // $this->_setPropertyInternal('uri', $uri); 125 // $this->_setPropertyInternal('uri', $uri);
126 $this->_setPropertyInternal('uri', ''); 126 $this->_setPropertyInternal('uri', '');
127 - // TODO what is this? Assuming it is the object type id, and not OUR document type?  
128 - $this->_setPropertyInternal('objectTypeId', strtolower($this->getAttribute('id')));  
129 - // Needed to distinguish type  
130 - $this->_setPropertyInternal('baseTypeId', strtolower($this->getAttribute('id')));  
131 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']); 127 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']);
132 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']); 128 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']);
133 $this->_setPropertyInternal('lastModifiedBy', $objectProperties['modified_by']); 129 $this->_setPropertyInternal('lastModifiedBy', $objectProperties['modified_by']);
lib/api/ktcmis/objecttypes/CMISFolderObject.inc.php
@@ -85,6 +85,8 @@ class CMISFolderObject extends CMISObject { @@ -85,6 +85,8 @@ class CMISFolderObject extends CMISObject {
85 throw new ObjectNotFoundException($e->getMessage()); 85 throw new ObjectNotFoundException($e->getMessage());
86 } 86 }
87 } 87 }
  88 +
  89 + parent::__construct();
88 } 90 }
89 91
90 // TODO abstract shared stuff to base class where possible 92 // TODO abstract shared stuff to base class where possible
@@ -111,10 +113,6 @@ class CMISFolderObject extends CMISObject { @@ -111,10 +113,6 @@ class CMISFolderObject extends CMISObject {
111 // TODO this url is probably incorrect...needs to be checked 113 // TODO this url is probably incorrect...needs to be checked
112 // $this->_setPropertyInternal('uri', $uri); 114 // $this->_setPropertyInternal('uri', $uri);
113 $this->_setPropertyInternal('uri', ''); 115 $this->_setPropertyInternal('uri', '');
114 - // TODO what is this? Assuming it is the object type id, and not OUR document type?  
115 - $this->_setPropertyInternal('objectTypeId', strtolower($this->getAttribute('id')));  
116 - // Needed to distinguish type  
117 - $this->_setPropertyInternal('baseTypeId', strtolower($this->getAttribute('id')));  
118 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']); 116 $this->_setPropertyInternal('createdBy', $objectProperties['created_by']);
119 // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by 117 // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by
120 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']); 118 $this->_setPropertyInternal('creationDate', $objectProperties['created_date']);
@@ -125,9 +123,17 @@ class CMISFolderObject extends CMISObject { @@ -125,9 +123,17 @@ class CMISFolderObject extends CMISObject {
125 $this->_setPropertyInternal('changeToken', null); 123 $this->_setPropertyInternal('changeToken', null);
126 $this->_setPropertyInternal('name', $objectProperties['folder_name']); 124 $this->_setPropertyInternal('name', $objectProperties['folder_name']);
127 $this->_setPropertyInternal('parentId', CMISUtil::encodeObjectId(FOLDER, $objectProperties['parent_id'])); 125 $this->_setPropertyInternal('parentId', CMISUtil::encodeObjectId(FOLDER, $objectProperties['parent_id']));
128 - $this->_setPropertyInternal('allowedChildObjectTypeIds', array('cmis:document', 'cmis:folder'));  
129 $this->_setPropertyInternal('author', $objectProperties['created_by']); 126 $this->_setPropertyInternal('author', $objectProperties['created_by']);
130 } 127 }
  128 +
  129 + /**
  130 + * Sets properties shared between all objects of this type
  131 + */
  132 + protected function _setSharedProperties()
  133 + {
  134 + parent::_setSharedProperties();
  135 + $this->_setPropertyInternal('allowedChildObjectTypeIds', array('cmis:document', 'cmis:folder'));
  136 + }
131 137
132 } 138 }
133 139
lib/api/ktcmis/services/CMISRepositoryService.inc.php
@@ -160,13 +160,15 @@ class CMISRepositoryService { @@ -160,13 +160,15 @@ class CMISRepositoryService {
160 // NOTE this code may fit better in the Repository Class 160 // NOTE this code may fit better in the Repository Class
161 function getTypeDefinition($repositoryId, $typeId) 161 function getTypeDefinition($repositoryId, $typeId)
162 { 162 {
  163 + global $default;
  164 + $default->log->debug();
  165 + $default->log->info(str_replace('cmis:', '', $typeId));
163 $typeId = ucwords(str_replace('cmis:', '', $typeId)); 166 $typeId = ucwords(str_replace('cmis:', '', $typeId));
164 $object = 'CMIS' . $typeId . 'Object'; 167 $object = 'CMIS' . $typeId . 'Object';
165 168
166 // check whether the object type exists, return error if not 169 // check whether the object type exists, return error if not
167 // consider throwing an exception instead (see General Exceptions) 170 // consider throwing an exception instead (see General Exceptions)
168 - if (!file_exists(CMIS_DIR . '/objecttypes/' . $object . '.inc.php'))  
169 - { 171 + if (!file_exists(CMIS_DIR . '/objecttypes/' . $object . '.inc.php')) {
170 throw new InvalidArgumentException('Type ' . $typeId . ' is not supported'); 172 throw new InvalidArgumentException('Type ' . $typeId . ' is not supported');
171 } 173 }
172 174
@@ -174,8 +176,11 @@ class CMISRepositoryService { @@ -174,8 +176,11 @@ class CMISRepositoryService {
174 176
175 require_once(CMIS_DIR . '/objecttypes/' . $object . '.inc.php'); 177 require_once(CMIS_DIR . '/objecttypes/' . $object . '.inc.php');
176 $cmisObject = new $object; 178 $cmisObject = new $object;
177 - $typeDefinition['attributes'] = $cmisObject->getAttributes();  
178 - $typeDefinition['properties'] = $cmisObject->getProperties(); 179 +
  180 + // NOTE The specification is ambigous here: it states that this function must return the type properties, but
  181 + // the atompub example shows the type attributes, not properties; since most properties are only populated
  182 + // on creation of an instance of an object-type, we choose to go with the attributes and not the properties
  183 + $typeDefinition = $cmisObject->getAttributes();
179 184
180 return $typeDefinition; 185 return $typeDefinition;
181 } 186 }
lib/api/ktcmis/util/CMISUtil.inc.php
@@ -283,7 +283,7 @@ class CMISUtil { @@ -283,7 +283,7 @@ class CMISUtil {
283 283
284 foreach(CMISPropertyCollection::$propertyTypes as $property => $type) 284 foreach(CMISPropertyCollection::$propertyTypes as $property => $type)
285 { 285 {
286 - // hack for Author property 286 + // author property does not work the same as the others
287 if ($property == 'author') { 287 if ($property == 'author') {
288 $object[$property] = array('value' => $properties->getValue($property)); 288 $object[$property] = array('value' => $properties->getValue($property));
289 } 289 }
webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
@@ -91,8 +91,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service { @@ -91,8 +91,6 @@ class KT_cmis_atom_service_folder extends KT_cmis_atom_service {
91 // TODO this only returns one parent, need to implement returnToRoot also 91 // TODO this only returns one parent, need to implement returnToRoot also
92 else if ($this->params[1] == 'parent') 92 else if ($this->params[1] == 'parent')
93 { 93 {
94 - // abstract this to be used also by the document service (and the PWC service?) ???  
95 - // alternatively use getFolderParent here makes sense and use getObjectParents when document service?  
96 $folderId = $this->params[0]; 94 $folderId = $this->params[0];
97 $NavigationService = new KTNavigationService(KT_cmis_atom_service_helper::getKt()); 95 $NavigationService = new KTNavigationService(KT_cmis_atom_service_helper::getKt());
98 $response = $NavigationService->getFolderParent($repositoryId, $folderId, false, false, false); 96 $response = $NavigationService->getFolderParent($repositoryId, $folderId, false, false, false);
@@ -403,8 +401,6 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service { @@ -403,8 +401,6 @@ class KT_cmis_atom_service_document extends KT_cmis_atom_service {
403 // update accordingly when updating to newer specification 401 // update accordingly when updating to newer specification
404 if ($this->params[1] == 'parent') 402 if ($this->params[1] == 'parent')
405 { 403 {
406 - // abstract this to be used also by the document service (and the PWC service?) ???  
407 - // alternatively use getFolderParent here makes sense and use getObjectParents when document service?  
408 $NavigationService = new NavigationService(KT_cmis_atom_service_helper::getKt()); 404 $NavigationService = new NavigationService(KT_cmis_atom_service_helper::getKt());
409 $response = $NavigationService->getObjectParents($repositoryId, $objectId, false, false); 405 $response = $NavigationService->getObjectParents($repositoryId, $objectId, false, false);
410 406
@@ -701,28 +697,20 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service { @@ -701,28 +697,20 @@ class KT_cmis_atom_service_type extends KT_cmis_atom_service {
701 { 697 {
702 $RepositoryService = new KTRepositoryService(); 698 $RepositoryService = new KTRepositoryService();
703 $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService); 699 $repositoryId = KT_cmis_atom_service_helper::getRepositoryId($RepositoryService);
  700 + $type = $this->params[0];
704 701
705 - if (!isset($this->params[1])) {  
706 - // For easier return in the wanted format, we call getTypes instead of getTypeDefinition.  
707 - // Calling this with a single type specified returns an array containing the definition of  
708 - // just the requested type.  
709 - // NOTE could maybe be more efficient to call getTypeDefinition direct and then place in  
710 - // an array on this side? or directly expose the individual entry response code and  
711 - // call directly from here rather than via getTypeFeed.  
712 - $type = ucwords($this->params[0]);  
713 - $types = $RepositoryService->getTypes($repositoryId, $type);  
714 -  
715 - // hack for removing one level of access  
716 - $types = $types['results'];  
717 -  
718 - $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types); 702 + try {
  703 + $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $type);
719 } 704 }
720 - else {  
721 - // TODO dynamic dates, as needed everywhere  
722 - // NOTE children of types not yet implemented and we don't support any non-basic types at this time  
723 - $feed = $this->getTypeChildrenFeed($this->params[1]); 705 + catch (Exception $e) {
  706 + $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $e->getMessage());
  707 + // Expose the responseFeed
  708 + $this->responseFeed = $feed;
  709 + return null;
724 } 710 }
725 711
  712 + $feed = KT_cmis_atom_service_helper::getTypeFeed($type, array($typeDefinition));
  713 +
726 // Expose the responseFeed 714 // Expose the responseFeed
727 $this->responseFeed=$feed; 715 $this->responseFeed=$feed;
728 } 716 }
webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
@@ -107,25 +107,25 @@ class KT_cmis_atom_service_helper { @@ -107,25 +107,25 @@ class KT_cmis_atom_service_helper {
107 * @param boolean $pwc Whether this is a PWC object 107 * @param boolean $pwc Whether this is a PWC object
108 * @param $method The request method used (POST/GET/...) 108 * @param $method The request method used (POST/GET/...)
109 */ 109 */
110 - static public function createObjectEntry(&$response, $cmisEntry, $parent, $pwc = false, $method = 'GET') 110 + static public function createObjectEntry(&$feed, $cmisEntry, $parent, $pwc = false, $method = 'GET')
111 { 111 {
112 - $workspace = $response->getWorkspace(); 112 + $workspace = $feed->getWorkspace();
113 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']); 113 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']);
114 114
115 // create entry 115 // create entry
116 - $entry = $response->newEntry(); 116 + $entry = $feed->newEntry();
117 117
118 // When request is a POST we will be returning only an object entry, not a full feed, and so this belongs here 118 // When request is a POST we will be returning only an object entry, not a full feed, and so this belongs here
119 if (($method == 'POST') || $pwc) 119 if (($method == 'POST') || $pwc)
120 { 120 {
121 // append attributes 121 // append attributes
122 - $entry->appendChild($response->newAttr('xmlns', 'http://www.w3.org/2005/Atom'));  
123 - $entry->appendChild($response->newAttr('xmlns:app', 'http://www.w3.org/2007/app'));  
124 - $entry->appendChild($response->newAttr('xmlns:cmis', 'http://docs.oasis-open.org/ns/cmis/core/200908/'));  
125 - $entry->appendChild($response->newAttr('xmlns:cmisra', 'http://docs.oasis-open.org/ns/cmis/restatom/200908/')); 122 + $entry->appendChild($feed->newAttr('xmlns', 'http://www.w3.org/2005/Atom'));
  123 + $entry->appendChild($feed->newAttr('xmlns:app', 'http://www.w3.org/2007/app'));
  124 + $entry->appendChild($feed->newAttr('xmlns:cmis', 'http://docs.oasis-open.org/ns/cmis/core/200908/'));
  125 + $entry->appendChild($feed->newAttr('xmlns:cmisra', 'http://docs.oasis-open.org/ns/cmis/restatom/200908/'));
126 } 126 }
127 127
128 - self::createObjectEntryContent($entry, $response, $cmisEntry, $parent, $pwc, $method); 128 + self::createObjectEntryContent($entry, $feed, $cmisEntry, $parent, $pwc, $method);
129 } 129 }
130 130
131 /** 131 /**
@@ -151,13 +151,13 @@ class KT_cmis_atom_service_helper { @@ -151,13 +151,13 @@ class KT_cmis_atom_service_helper {
151 // NOTE this approach appears to be necessary due to the structure of the underlying atompub code and specification, 151 // NOTE this approach appears to be necessary due to the structure of the underlying atompub code and specification,
152 // which does not directly support nesting - attempting to create a new feed and append it within the outer 152 // which does not directly support nesting - attempting to create a new feed and append it within the outer
153 // feed resulted in an empty cmisra:children node, so this approach was substituted 153 // feed resulted in an empty cmisra:children node, so this approach was substituted
154 - static public function createChildObjectEntry(&$childrenFeed, $cmisEntry, $workspace, $response, $folderNam) 154 + static public function createChildObjectEntry(&$childrenFeed, $cmisEntry, $workspace, $feed, $folderNam)
155 { 155 {
156 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']); 156 $type = strtolower($cmisEntry['properties']['objectTypeId']['value']);
157 157
158 // create entry 158 // create entry
159 - $entry = $response->newElement('entry');  
160 - self::createObjectEntryContent($entry, $response, $cmisEntry);//, $parent, $pwc, $method); 159 + $entry = $feed->newElement('entry');
  160 + self::createObjectEntryContent($entry, $feed, $cmisEntry);//, $parent, $pwc, $method);
161 $childrenFeed->appendChild($entry); 161 $childrenFeed->appendChild($entry);
162 } 162 }
163 163
@@ -165,26 +165,26 @@ class KT_cmis_atom_service_helper { @@ -165,26 +165,26 @@ class KT_cmis_atom_service_helper {
165 * Creates the actual object entry: this is shared between other functions which require this content 165 * Creates the actual object entry: this is shared between other functions which require this content
166 * 166 *
167 * @param object $entry The entry object 167 * @param object $entry The entry object
168 - * @param object $response The response feed 168 + * @param object $feed The response feed
169 * @param array $cmisEntry The CMIS object content 169 * @param array $cmisEntry The CMIS object content
170 * @param string $parent The parent folder name 170 * @param string $parent The parent folder name
171 * @param boolean $pwc Whether this is a PWC object (will be returned slightly differently) 171 * @param boolean $pwc Whether this is a PWC object (will be returned slightly differently)
172 * @param string $method The calling method (slightly affects the output) 172 * @param string $method The calling method (slightly affects the output)
173 */ 173 */
174 - static public function createObjectEntryContent($entry, &$response, $cmisEntry, $parent = '', $pwc = false, $method = 'GET') 174 + static public function createObjectEntryContent($entry, &$feed, $cmisEntry, $parent = '', $pwc = false, $method = 'GET')
175 { 175 {
176 // TODO dynamic actual creator name 176 // TODO dynamic actual creator name
177 - $responseElement = $response->newField('author');  
178 - $element = $response->newField('name', 'admin', $responseElement); 177 + $responseElement = $feed->newField('author');
  178 + $element = $feed->newField('name', 'admin', $responseElement);
179 $entry->appendChild($responseElement); 179 $entry->appendChild($responseElement);
180 180
181 $typeString = str_replace('cmis:', '', $type); 181 $typeString = str_replace('cmis:', '', $type);
182 182
183 if (!empty($cmisEntry['properties']['contentStreamLength']['value'])) 183 if (!empty($cmisEntry['properties']['contentStreamLength']['value']))
184 { 184 {
185 - $field = $response->newElement('content');  
186 - $field->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
187 - $field->appendChild($response->newAttr('src', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 185 + $field = $feed->newElement('content');
  186 + $field->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));
  187 + $field->appendChild($feed->newAttr('src', CMIS_APP_BASE_URI . $workspace . '/' . $typeString
188 . '/' . $cmisEntry['properties']['objectId']['value'] 188 . '/' . $cmisEntry['properties']['objectId']['value']
189 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 189 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
190 $entry->appendChild($field); 190 $entry->appendChild($field);
@@ -192,37 +192,37 @@ class KT_cmis_atom_service_helper { @@ -192,37 +192,37 @@ class KT_cmis_atom_service_helper {
192 192
193 // content & id tags 193 // content & id tags
194 $id = $cmisEntry['properties']['objectId']['value']; 194 $id = $cmisEntry['properties']['objectId']['value'];
195 - $response->newField('id', 'urn:uuid:' . $id, $entry); 195 + $feed->newField('id', 'urn:uuid:' . $id, $entry);
196 196
197 // links 197 // links
198 - $link = $response->newElement('link');  
199 - $link->appendChild($response->newAttr('rel', 'self'));  
200 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' 198 + $link = $feed->newElement('link');
  199 + $link->appendChild($feed->newAttr('rel', 'self'));
  200 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/'
201 . (!$pwc ? $typeString : 'pwc') . '/' 201 . (!$pwc ? $typeString : 'pwc') . '/'
202 . $cmisEntry['properties']['objectId']['value'])); 202 . $cmisEntry['properties']['objectId']['value']));
203 $entry->appendChild($link); 203 $entry->appendChild($link);
204 204
205 - $link = $response->newElement('link');  
206 - $link->appendChild($response->newAttr('rel', 'edit'));  
207 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 205 + $link = $feed->newElement('link');
  206 + $link->appendChild($feed->newAttr('rel', 'edit'));
  207 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString
208 . '/' . $cmisEntry['properties']['objectId']['value'])); 208 . '/' . $cmisEntry['properties']['objectId']['value']));
209 $entry->appendChild($link); 209 $entry->appendChild($link);
210 210
211 if ((strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:document') 211 if ((strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:document')
212 && (!empty($cmisEntry['properties']['contentStreamLength']['value']))) 212 && (!empty($cmisEntry['properties']['contentStreamLength']['value'])))
213 { 213 {
214 - $link = $response->newElement('link');  
215 - $link->appendChild($response->newAttr('rel', 'edit-media'));  
216 - $link->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
217 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 214 + $link = $feed->newElement('link');
  215 + $link->appendChild($feed->newAttr('rel', 'edit-media'));
  216 + $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));
  217 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString
218 . '/' . $cmisEntry['properties']['objectId']['value'] 218 . '/' . $cmisEntry['properties']['objectId']['value']
219 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 219 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
220 $entry->appendChild($link); 220 $entry->appendChild($link);
221 221
222 - $link = $response->newElement('link');  
223 - $link->appendChild($response->newAttr('rel', 'enclosure'));  
224 - $link->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
225 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString 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'] 226 . '/' . $cmisEntry['properties']['objectId']['value']
227 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 227 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
228 $entry->appendChild($link); 228 $entry->appendChild($link);
@@ -230,17 +230,17 @@ class KT_cmis_atom_service_helper { @@ -230,17 +230,17 @@ class KT_cmis_atom_service_helper {
230 230
231 // according to spec this MUST be present, but spec says that links for function which are not supported 231 // according to spec this MUST be present, but spec says that links for function which are not supported
232 // do not need to be present, so unsure for the moment 232 // do not need to be present, so unsure for the moment
233 - $link = $response->newElement('link');  
234 - $link->appendChild($response->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions'));  
235 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/' 233 + $link = $feed->newElement('link');
  234 + $link->appendChild($feed->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/allowableactions'));
  235 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/'
236 . $cmisEntry['properties']['objectId']['value'] . '/allowableactions')); 236 . $cmisEntry['properties']['objectId']['value'] . '/allowableactions'));
237 $entry->appendChild($link); 237 $entry->appendChild($link);
238 238
239 // according to spec this MUST be present, but spec says that links for function which are not supported 239 // according to spec this MUST be present, but spec says that links for function which are not supported
240 // do not need to be present, so unsure for the moment 240 // do not need to be present, so unsure for the moment
241 - $link = $response->newElement('link');  
242 - $link->appendChild($response->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/relationships'));  
243 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/' 241 + $link = $feed->newElement('link');
  242 + $link->appendChild($feed->newAttr('rel', 'http://docs.oasis-open.org/ns/cmis/link/200908/relationships'));
  243 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $typeString . '/'
244 . $cmisEntry['properties']['objectId']['value'] . '/rels')); 244 . $cmisEntry['properties']['objectId']['value'] . '/rels'));
245 $entry->appendChild($link); 245 $entry->appendChild($link);
246 246
@@ -251,9 +251,9 @@ class KT_cmis_atom_service_helper { @@ -251,9 +251,9 @@ class KT_cmis_atom_service_helper {
251 if (!CMISUtil::isRootFolder(self::$repositoryId, $cmisEntry['properties']['objectId']['value'], self::$ktapi)) 251 if (!CMISUtil::isRootFolder(self::$repositoryId, $cmisEntry['properties']['objectId']['value'], self::$ktapi))
252 { 252 {
253 // TODO check parent link is correct, fix if needed 253 // TODO check parent link is correct, fix if needed
254 - $link = $response->newElement('link');  
255 - $link->appendChild($response->newAttr('rel', 'up'));  
256 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/' 254 + $link = $feed->newElement('link');
  255 + $link->appendChild($feed->newAttr('rel', 'up'));
  256 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/folder/'
257 . $cmisEntry['properties']['parentId']['value'])); 257 . $cmisEntry['properties']['parentId']['value']));
258 $entry->appendChild($link); 258 $entry->appendChild($link);
259 } 259 }
@@ -261,16 +261,16 @@ class KT_cmis_atom_service_helper { @@ -261,16 +261,16 @@ class KT_cmis_atom_service_helper {
261 // Folder/Document specific links 261 // Folder/Document specific links
262 if (strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:folder') 262 if (strtolower($cmisEntry['properties']['objectTypeId']['value']) == 'cmis:folder')
263 { 263 {
264 - $link = $response->newElement('link');  
265 - $link->appendChild($response->newAttr('rel', 'down'));  
266 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' 264 + $link = $feed->newElement('link');
  265 + $link->appendChild($feed->newAttr('rel', 'down'));
  266 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/'
267 . $typeString 267 . $typeString
268 . '/' . $cmisEntry['properties']['objectId']['value'] 268 . '/' . $cmisEntry['properties']['objectId']['value']
269 . '/children')); 269 . '/children'));
270 $entry->appendChild($link); 270 $entry->appendChild($link);
271 - $link = $response->newElement('link');  
272 - $link->appendChild($response->newAttr('rel', 'down'));  
273 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' 271 + $link = $feed->newElement('link');
  272 + $link->appendChild($feed->newAttr('rel', 'down'));
  273 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/'
274 . $typeString 274 . $typeString
275 . '/' . $cmisEntry['properties']['objectId']['value'] 275 . '/' . $cmisEntry['properties']['objectId']['value']
276 . '/descendants')); 276 . '/descendants'));
@@ -285,10 +285,10 @@ class KT_cmis_atom_service_helper { @@ -285,10 +285,10 @@ class KT_cmis_atom_service_helper {
285 // not sure yet where it must point... 285 // not sure yet where it must point...
286 if (!empty($cmisEntry['properties']['contentStreamLength']['value'])) 286 if (!empty($cmisEntry['properties']['contentStreamLength']['value']))
287 { 287 {
288 - $link = $response->newElement('link');  
289 - $link->appendChild($response->newAttr('rel', 'stream'));  
290 - $link->appendChild($response->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));  
291 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 288 + $link = $feed->newElement('link');
  289 + $link->appendChild($feed->newAttr('rel', 'stream'));
  290 + $link->appendChild($feed->newAttr('type', $cmisEntry['properties']['contentStreamMimeType']['value']));
  291 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
292 . '/' . $cmisEntry['properties']['objectId']['value'] 292 . '/' . $cmisEntry['properties']['objectId']['value']
293 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 293 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
294 $entry->appendChild($link); 294 $entry->appendChild($link);
@@ -299,68 +299,51 @@ class KT_cmis_atom_service_helper { @@ -299,68 +299,51 @@ class KT_cmis_atom_service_helper {
299 // TODO separated code for PWC and actual document object 299 // TODO separated code for PWC and actual document object
300 if (!empty($cmisEntry['properties']['versionSeriesCheckedOutId']['value'])) 300 if (!empty($cmisEntry['properties']['versionSeriesCheckedOutId']['value']))
301 { 301 {
302 - $link = $response->newElement('link');  
303 - $link->appendChild($response->newAttr('rel', 'pwc'));  
304 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 302 + $link = $feed->newElement('link');
  303 + $link->appendChild($feed->newAttr('rel', 'pwc'));
  304 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
305 . '/' . $cmisEntry['properties']['objectId']['value'] 305 . '/' . $cmisEntry['properties']['objectId']['value']
306 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 306 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
307 $entry->appendChild($link); 307 $entry->appendChild($link);
308 - $link = $response->newElement('link');  
309 - $link->appendChild($response->newAttr('rel', 'source'));  
310 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 308 + $link = $feed->newElement('link');
  309 + $link->appendChild($feed->newAttr('rel', 'source'));
  310 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
311 . '/' . $cmisEntry['properties']['objectId']['value'] 311 . '/' . $cmisEntry['properties']['objectId']['value']
312 . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 312 . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
313 $entry->appendChild($link); 313 $entry->appendChild($link);
314 } 314 }
315 315
316 -// $link = $response->newElement('link');  
317 -// $link->appendChild($response->newAttr('rel', 'stream'));  
318 -// $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type 316 +// $link = $feed->newElement('link');
  317 +// $link->appendChild($feed->newAttr('rel', 'stream'));
  318 +// $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/' . $type
319 // . '/' . $cmisEntry['properties']['objectId']['value'] 319 // . '/' . $cmisEntry['properties']['objectId']['value']
320 // . '/' . $cmisEntry['properties']['contentStreamFilename']['value'])); 320 // . '/' . $cmisEntry['properties']['contentStreamFilename']['value']));
321 } 321 }
322 322
323 - $link = $response->newElement('link');  
324 - $link->appendChild($response->newAttr('rel', 'describedby'));  
325 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . $type)); 323 + $link = $feed->newElement('link');
  324 + $link->appendChild($feed->newAttr('rel', 'describedby'));
  325 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . $type));
326 $entry->appendChild($link); 326 $entry->appendChild($link);
327 327
328 - $link = $response->newElement('link');  
329 - $link->appendChild($response->newAttr('rel', 'service'));  
330 - $link->appendChild($response->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument')); 328 + $link = $feed->newElement('link');
  329 + $link->appendChild($feed->newAttr('rel', 'service'));
  330 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument'));
331 $entry->appendChild($link); 331 $entry->appendChild($link);
332 332
333 // TODO proper date 333 // TODO proper date
334 - $entry->appendChild($response->newField('published', self::formatDatestamp()));  
335 - $entry->appendChild($response->newElement('summary', $cmisEntry['properties']['name']['value']));  
336 - $entry->appendChild($response->newElement('title', $cmisEntry['properties']['name']['value']));  
337 - $entry->appendChild($response->newField('updated', self::formatDatestamp())); 334 + $entry->appendChild($feed->newField('published', self::formatDatestamp()));
  335 + $entry->appendChild($feed->newElement('summary', $cmisEntry['properties']['name']['value']));
  336 + $entry->appendChild($feed->newElement('title', $cmisEntry['properties']['name']['value']));
  337 + $entry->appendChild($feed->newField('updated', self::formatDatestamp()));
338 338
339 // main CMIS entry 339 // main CMIS entry
340 - $objectElement = $response->newElement('cmisra:object');  
341 - $propertiesElement = $response->newElement('cmis:properties');  
342 -  
343 - foreach($cmisEntry['properties'] as $propertyName => $property)  
344 - {  
345 - $propElement = $response->newElement('cmis:' . $property['type']);  
346 -// $propElement->appendChild($response->newAttr('localName', 'rep-cmis:' . $propertyName));  
347 - $propElement->appendChild($response->newAttr('propertyDefinitionId', 'cmis:' . $propertyName));  
348 - if (!empty($property['value']))  
349 - {  
350 - if ($propertyName == 'contentStreamUri') {  
351 - $property['value'] = CMIS_APP_BASE_URI . $workspace . '/' . $type . '/' .$property['value'];  
352 - }  
353 - $response->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement);  
354 - }  
355 - $propertiesElement->appendChild($propElement);  
356 - }  
357 -  
358 - $objectElement->appendChild($propertiesElement); 340 + $objectElement = $feed->newElement('cmisra:object');
  341 + $objectElement->appendChild(self::createEntryPropertiesElement($feed, $cmisEntry['properties']));
359 $entry->appendChild($objectElement); 342 $entry->appendChild($objectElement);
360 343
361 // TODO check determination of when to add app:edited tag 344 // TODO check determination of when to add app:edited tag
362 // if ($method == 'POST') { 345 // if ($method == 'POST') {
363 - $entry->appendChild($response->newElement('app:edited', self::formatDatestamp())); 346 + $entry->appendChild($feed->newElement('app:edited', self::formatDatestamp()));
364 // } 347 // }
365 348
366 // TODO pathSegment entry 349 // TODO pathSegment entry
@@ -368,14 +351,43 @@ class KT_cmis_atom_service_helper { @@ -368,14 +351,43 @@ class KT_cmis_atom_service_helper {
368 // deal with child objects 351 // deal with child objects
369 if (isset($cmisEntry['children'])) { 352 if (isset($cmisEntry['children'])) {
370 // add children node and fill with child entries 353 // add children node and fill with child entries
371 - $childrenFeed = $response->newElement('feed');  
372 - self::createObjectChildrenFeed($childrenFeed, $cmisEntry['children'], $workspace, $response, '' /*folderName not passed through*/); 354 + $childrenFeed = $feed->newElement('feed');
  355 + self::createObjectChildrenFeed($childrenFeed, $cmisEntry['children'], $workspace, $feed, '' /*folderName not passed through*/);
373 356
374 - $childrenElement = $response->newElement('cmisra:children'); 357 + $childrenElement = $feed->newElement('cmisra:children');
375 $childrenElement->appendChild($childrenFeed); 358 $childrenElement->appendChild($childrenFeed);
376 $entry->appendChild($childrenElement); 359 $entry->appendChild($childrenElement);
377 } 360 }
378 } 361 }
  362 +
  363 + /**
  364 + * Shared function for creating an object properties node
  365 + *
  366 + * @param object $feed AtomPub response feed
  367 + * @param array $properties CMIS object properties
  368 + * @return object $propertiesElement AtomPub node
  369 + */
  370 + // TODO leave out unset properties?
  371 + static public function createEntryPropertiesElement(&$feed, $properties)
  372 + {
  373 + $propertiesElement = $feed->newElement('cmis:properties');
  374 + foreach($properties as $propertyName => $property)
  375 + {
  376 + $propElement = $feed->newElement('cmis:' . $property['type']);
  377 +// $propElement->appendChild($feed->newAttr('localName', 'rep-cmis:' . $propertyName));
  378 + $propElement->appendChild($feed->newAttr('propertyDefinitionId', 'cmis:' . $propertyName));
  379 + if (!empty($property['value']))
  380 + {
  381 + if ($propertyName == 'contentStreamUri') {
  382 + $property['value'] = CMIS_APP_BASE_URI . $workspace . '/' . $type . '/' .$property['value'];
  383 + }
  384 + $feed->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement);
  385 + }
  386 + $propertiesElement->appendChild($propElement);
  387 + }
  388 +
  389 + return $propertiesElement;
  390 + }
379 391
380 /** 392 /**
381 * Retrieves the list of types|type definition as a CMIS AtomPub feed 393 * Retrieves the list of types|type definition as a CMIS AtomPub feed
@@ -386,6 +398,10 @@ class KT_cmis_atom_service_helper { @@ -386,6 +398,10 @@ class KT_cmis_atom_service_helper {
386 */ 398 */
387 static public function getTypeFeed($typeDef, $types) 399 static public function getTypeFeed($typeDef, $types)
388 { 400 {
  401 + global $default;
  402 +// $default->log->info(print_r($types));
  403 +// $default->log->info(print_r($types, true));
  404 + $default->log->info($typeDef);
389 $typesString = ''; 405 $typesString = '';
390 $typesHeading = ''; 406 $typesHeading = '';
391 switch($typeDef) 407 switch($typeDef)
@@ -417,21 +433,6 @@ class KT_cmis_atom_service_helper { @@ -417,21 +433,6 @@ class KT_cmis_atom_service_helper {
417 $element = $feed->newField('name', 'admin', $feedElement); 433 $element = $feed->newField('name', 'admin', $feedElement);
418 $feed->appendChild($feedElement); 434 $feed->appendChild($feedElement);
419 435
420 - // NOTE spec says this link MUST be present but is vague on where it points  
421 - // as of 0.61c:  
422 - // "The source link relation points to the underlying CMIS Type Definition as Atom Entry"  
423 - // so what is the underlying CMIS Type Definition for a collection of base types?  
424 - // suspect that it only applies when not listing all types, i.e. a base type is asked for  
425 - /*  
426 - $link = $feed->newElement('link');  
427 - $link->appendChild($feed->newAttr('rel','source'));  
428 - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['typeId'])));  
429 - $feed->appendChild($link);  
430 - */  
431 -  
432 - // current time: format = 2009-07-13T14:49:27.659+02:00  
433 - $feed->appendChild($feed->newElement('updated', self::formatDatestamp()));  
434 -  
435 foreach($types as $type) 436 foreach($types as $type)
436 { 437 {
437 $entry = $feed->newEntry(); 438 $entry = $feed->newEntry();
@@ -439,48 +440,37 @@ class KT_cmis_atom_service_helper { @@ -439,48 +440,37 @@ class KT_cmis_atom_service_helper {
439 $feedElement = $feed->newField('author'); 440 $feedElement = $feed->newField('author');
440 $element = $feed->newField('name', 'admin', $feedElement); 441 $element = $feed->newField('name', 'admin', $feedElement);
441 $entry->appendChild($feedElement); 442 $entry->appendChild($feedElement);
442 - $feedElement = $feed->newField('content', $type['typeId']); 443 + $feedElement = $feed->newField('content', 'Type definition for ' . $type['baseId']);
443 $entry->appendChild($feedElement); 444 $entry->appendChild($feedElement);
444 445
445 - $feed->newField('id', 'urn:uuid:type-' . $type['typeId'], $feed);  
446 -  
447 - // TODO add parents link when not selecting a base type.  
448 - // TODO add children link when type has children  
449 - // TODO add descendants link when type has children  
450 - // NOTE KnowledgeTree currently only supports base types so these are not important at the present time.  
451 - 446 + $feed->newField('id', 'urn:uuid:type-' . $type['baseId'], $feed);
  447 +
452 // links 448 // links
453 $link = $feed->newElement('link'); 449 $link = $feed->newElement('link');
454 $link->appendChild($feed->newAttr('rel','self')); 450 $link->appendChild($feed->newAttr('rel','self'));
455 - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['typeId']))); 451 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['baseId'])));
456 $entry->appendChild($link); 452 $entry->appendChild($link);
457 // TODO type link MUST point to base type 453 // TODO type link MUST point to base type
458 // KnowledgeTree currently only supports base types so this is not important 454 // KnowledgeTree currently only supports base types so this is not important
459 // at the present time as it will always point at the base type. 455 // at the present time as it will always point at the base type.
460 $link = $feed->newElement('link'); 456 $link = $feed->newElement('link');
461 $link->appendChild($feed->newAttr('rel','type')); 457 $link->appendChild($feed->newAttr('rel','type'));
462 - $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['typeId']))); 458 + $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $workspace . '/type/' . strtolower($type['baseId'])));
463 $entry->appendChild($link); 459 $entry->appendChild($link);
464 $link = $feed->newElement('link'); 460 $link = $feed->newElement('link');
465 $link->appendChild($feed->newAttr('rel','repository')); 461 $link->appendChild($feed->newAttr('rel','repository'));
466 $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument')); 462 $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . '/servicedocument'));
467 $entry->appendChild($link); 463 $entry->appendChild($link);
468 -  
469 - $entry->appendChild($feed->newElement('summary', $type['typeId'] . ' Type'));  
470 - $entry->appendChild($feed->newElement('title', $type['typeId'])); 464 +
  465 + $entry->appendChild($feed->newElement('summary', 'Summary for ' . $type['baseId'] . ' type'));
  466 + $entry->appendChild($feed->newElement('title', $type['baseId']));
471 $entry->appendChild($feed->newElement('updated', self::formatDatestamp())); 467 $entry->appendChild($feed->newElement('updated', self::formatDatestamp()));
472 -  
473 - // main CMIS entry  
474 - $feedElement = $feed->newElement('cmis:' . strtolower($type['typeId']) . 'Type');  
475 - foreach($type as $property => $value)  
476 - {  
477 - $feed->newField('cmis:' . $property, CMISUtil::boolToString($value), $feedElement);  
478 - }  
479 -  
480 - $entry->appendChild($feedElement);  
481 468
482 - // after every entry, append a cmis:terminator tag  
483 -// $entry->appendChild($feed->newElement('cmis:terminator')); 469 + $objectElement = $feed->newElement('cmisra:type');
  470 + foreach($type as $property => $value) {
  471 + $feed->newField('cmis:' . $property, CMISUtil::boolToString($value), $objectElement);
  472 + }
  473 + $entry->appendChild($objectElement);
484 } 474 }
485 475
486 return $feed; 476 return $feed;