diff --git a/lib/api/ktcmis/config/repositories.xml b/lib/api/ktcmis/config/repositories.xml
index 8f65088..71ed7ad 100644
--- a/lib/api/ktcmis/config/repositories.xml
+++ b/lib/api/ktcmis/config/repositories.xml
@@ -13,7 +13,7 @@
http://127.0.0.1/
0ad7de04-7914-41b1-b5ee-be9f0b626437
- KnowledgeTree
+ KnowledgeTree DMS
self
KnowledgeTree Repository
KnowledgeTree
diff --git a/lib/api/ktcmis/ktcmis.inc.php b/lib/api/ktcmis/ktcmis.inc.php
index 1c83cba..88fc291 100644
--- a/lib/api/ktcmis/ktcmis.inc.php
+++ b/lib/api/ktcmis/ktcmis.inc.php
@@ -62,27 +62,42 @@ require_once(CMIS_DIR . '/util/CMISUtil.inc.php');
*/
class KTCMISBase {
- /**
- * KnowledgeTree API instance
- *
- * @var object
- */
- protected $ktapi;
- /**
- * KnowledgeTree API Session Identifier
- *
- * @var object
- */
- protected $session;
+ // we want all child classes to share the ktapi and session instances, no matter where they are set from,
+ // so we declare them as static
+ static protected $ktapi;
+ static protected $session;
+ // TODO try to pick up existing session if possible, i.e. if the $session value is not empty
public function startSession($username, $password)
{
- $this->session = null;
+// echo $username." :: ".$password."
";
+ // attempt to recover session if one exists
+ if (!is_null(self::$session) && !PEAR::isError(self::$session))
+ {
+// echo "ATTEMPT TO RECOVER SESSION: ".print_r(self::$session, true)."
\n";
+ self::$session =& self::$ktapi->get_active_session(self::$session->get_sessionid());
+ }
+
+ // start new session if no existing session or problem getting existing session (expired, etc...)
+ if (is_null(self::$session) || PEAR::isError(self::$session))
+ {
+// echo "ATTEMPT TO START NEW SESSION
\n";
+ self::$ktapi = new KTAPI();
+ self::$session =& self::$ktapi->start_session($username, $password);
+ }
+
+// print_r(self::$ktapi);
+ return self::$session;
+ }
- $this->ktapi = new KTAPI();
- $this->session =& $this->ktapi->start_session($username, $password);
+ public function getInterface()
+ {
+ return self::$ktapi;
+ }
- return $this->session;
+ public function getSession()
+ {
+ return self::$session;
}
// TODO what about destroying sessions? only on logout (which is not offered by the CMIS clients tested so far)
@@ -244,7 +259,13 @@ class KTNavigationService extends KTCMISBase {
public function startSession($username, $password)
{
parent::startSession($username, $password);
- $this->NavigationService->setInterface($this->ktapi);
+ $this->setInterface();
+ return self::$session;
+ }
+
+ public function setInterface()
+ {
+ $this->NavigationService->setInterface(self::$ktapi);
}
/**
@@ -426,11 +447,17 @@ class KTObjectService extends KTCMISBase {
// instantiate underlying CMIS service
$this->ObjectService = new CMISObjectService();
}
-
+
public function startSession($username, $password)
{
parent::startSession($username, $password);
- $this->ObjectService->setInterface($this->ktapi);
+ $this->setInterface();
+ return self::$session;
+ }
+
+ public function setInterface()
+ {
+ $this->ObjectService->setInterface(self::$ktapi);
}
/**
diff --git a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
index cd9024e..6307e30 100644
--- a/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
+++ b/lib/api/ktcmis/objecttypes/CMISDocumentObject.inc.php
@@ -110,6 +110,7 @@ class CMISDocumentObject extends CMISBaseObject {
}
$objectProperties = $object->get_detail();
+// print_r($objectProperties);
$this->_setPropertyInternal('ObjectId', CMISUtil::encodeObjectId($this->typeId, $objectProperties['document_id']));
// prevent doubled '/' chars
@@ -131,6 +132,7 @@ class CMISDocumentObject extends CMISBaseObject {
$this->_setPropertyInternal('LastModificationDate', $objectProperties['modified_date']);
$this->_setPropertyInternal('ChangeToken', null);
$this->_setPropertyInternal('Name', $objectProperties['title']);
+ $this->_setPropertyInternal('ParentId', $objectProperties['folder_id']);
$this->_setPropertyInternal('IsImmutable', $objectProperties['is_immutable']);
// NOTE if access to older versions is allowed, this will need to be checked, else just set to yes
// see ktapi::get_document_version_history
diff --git a/lib/api/ktcmis/services/CMISObjectService.inc.php b/lib/api/ktcmis/services/CMISObjectService.inc.php
index 0a7f0e3..0ddab6f 100644
--- a/lib/api/ktcmis/services/CMISObjectService.inc.php
+++ b/lib/api/ktcmis/services/CMISObjectService.inc.php
@@ -262,6 +262,12 @@ class CMISObjectService {
throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')');
}
+ // TODO if name is blank! throw another exception (check type) - using RuntimeException for now
+ if (trim($properties['name']) == '')
+ {
+ throw new RuntimeException('Refusing to create an un-named folder');
+ }
+
$response = $this->ktapi->create_folder((int)$folderId, $properties['name'], $sig_username = '', $sig_password = '', $reason = '');
if ($response['status_code'] != 0)
{
diff --git a/lib/api/ktcmis/util/CMISUtil.inc.php b/lib/api/ktcmis/util/CMISUtil.inc.php
index 8740f84..8506d54 100644
--- a/lib/api/ktcmis/util/CMISUtil.inc.php
+++ b/lib/api/ktcmis/util/CMISUtil.inc.php
@@ -86,6 +86,12 @@ class CMISUtil {
*/
static public function decodeObjectId($objectId, &$typeId = null)
{
+ if (!is_string($objectId))
+ {
+ $typeId = 'Unknown';
+ return null;
+ }
+
$typeId = null;
preg_match('/(\D)(\d*)/', $objectId, $matches);
@@ -240,14 +246,11 @@ class CMISUtil {
'value' => $properties->getValue('Name'));
$object['Author'] = array('value' => $properties->getValue('Author'));
- if (strtolower($properties->getValue('ObjectTypeId')) == 'folder')
- {
- $object['properties']['ParentId'] = array('type' => $properties->getFieldType('ParentId'),
- 'value' => CMISUtil::encodeObjectId('Folder',
- $properties->getValue('ParentId')));
- }
+ $object['properties']['ParentId'] = array('type' => $properties->getFieldType('ParentId'),
+ 'value' => CMISUtil::encodeObjectId('Folder',
+ $properties->getValue('ParentId')));
// TODO should check for content stream data before filling these in
- else //if ()
+ if (strtolower($properties->getValue('ObjectTypeId')) == 'document')
{
$object['properties']['ContentStreamLength'] = array('type' => $properties->getFieldType('ContentStreamLength'),
'value' => $properties->getValue('ContentStreamLength'));
diff --git a/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
new file mode 100644
index 0000000..dbbacf7
--- /dev/null
+++ b/webservice/atompub/cmis/KT_cmis_atom_server.services.inc.php
@@ -0,0 +1,886 @@
+startSession(self::$authData['username'], self::$authData['password']);
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ // TODO implement full path/node separation as with Alfresco - i.e. path requests come in on path/ and node requests come in on node/
+ // path request e.g.: Root Folder/DroppedDocuments
+ // node request e.g.: F1/children
+ // node request e.g.: F2
+ if (urldecode($this->params[0]) == 'Root Folder')
+ {
+ $folderId = CMISUtil::encodeObjectId('Folder', 1);
+ $folderName = urldecode($this->params[0]);
+ }
+ // this is a bit of a hack, but then it's to accomodate a bit of a hack to work with the knowledgetree/drupal cmis modules...
+ else if ($this->params[0] == 'path')
+ {
+ $ktapi =& $RepositoryService->getInterface();
+ $folderId = KT_cmis_atom_service_helper::getFolderId($this->params, $ktapi);
+ }
+ else
+ {
+ $folderId = $this->params[0];
+ $ObjectService = new ObjectService();
+ $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
+ $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false);
+ $folderName = $cmisEntry['properties']['Name']['value'];
+// $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $newObjectId, $cmisEntry['properties']['Name']['value']);
+ }
+
+ if (!empty($this->params[1]) && (($this->params[1] == 'children') || ($this->params[1] == 'descendants')))
+ {
+ $NavigationService = new NavigationService();
+ $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
+
+ $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $this->params[1]);
+ }
+ else
+ {
+ $ObjectService = new ObjectService();
+ $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
+
+ $feed = $this->getFolderFeed($ObjectService, $repositoryId, $folderId);
+ }
+
+ //Expose the responseFeed
+ $this->responseFeed = $feed;
+ }
+
+ public function POST_action()
+ {
+// $username = $password = 'admin';
+ $RepositoryService = new RepositoryService();
+ $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ $folderId = $this->params[0];
+ $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title');
+ $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary');
+
+ $properties = array('name' => $title, 'summary' => $summary);
+
+ // determine whether this is a folder or a document create
+ // document create will have a content tag or containing base64 encoding of the document
+ $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content');
+ if (is_null($content))
+ $type = 'folder';
+ else
+ $type = 'document';
+
+ // TODO what if mime-type is incorrect? CMISSpaces appears to be sending text/plain on an executable file.
+ // perhaps because the content is text/plain once base64 encoded?
+ // How to determine the actual content type?
+ /*
+ *
+ * setup.txt
+ * setup.txt
+ * dGhpcyBiZSBzb21lIHRlc3QgY29udGVudCBmb3IgYSBkb2N1bWVudCwgeWVzPw==
+ *
+ *
+ * document
+ *
+ *
+ *
+ */
+
+ $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object']
+ [0]['@children']['cmis:properties']
+ [0]['@children']);
+
+ $ObjectService = new ObjectService();
+ $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
+ if ($type == 'folder')
+ $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId);
+ else
+ $newObjectId = $ObjectService->createDocument($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId, $content);
+
+ // check if returned Object Id is a valid CMIS Object Id
+ $dummy = CMISUtil::decodeObjectId($newObjectId, $typeId);
+ if ($typeId != 'Unknown')
+ {
+ $this->setStatus(self::STATUS_CREATED);
+ if ($type == 'folder')
+ {
+ $feed = $this->getFolderFeed($ObjectService, $repositoryId, $newObjectId);
+ }
+ else
+ {
+ $NavigationService = new NavigationService();
+ $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
+ $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false);
+ $feed = $this->getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $cmisEntry['properties']['Name']['value']);
+ }
+ }
+ else
+ {
+ $this->setStatus(self::STATUS_SERVER_ERROR);
+ $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Error: ' . self::STATUS_SERVER_ERROR);
+ $entry = $feed->newEntry();
+ $feed->newField('error', $newObjectId['message'], $entry);
+ }
+
+ //Expose the responseFeed
+ $this->responseFeed = $feed;
+ }
+
+ /**
+ * Retrieves children/descendants of the specified folder
+ * TODO this currently only works in children mode, add descendants
+ *
+ * @param string $repositoryId
+ * @param string $folderId folder id for which children/descendants are requested
+ * @param string $feedType children or descendants
+ * @return string CMIS AtomPub feed
+ */
+ private function getFolderChildrenFeed($NavigationService, $repositoryId, $folderId, $folderName, $feedType = 'children')
+ {
+ if ($feedType == 'children')
+ {
+ $entries = $NavigationService->getChildren($repositoryId, $folderId, false, false);
+ }
+ else if ($feedType == 'descendants')
+ {
+ $entries = $NavigationService->getDescendants($repositoryId, $folderId, false, false);
+ }
+ else
+ {
+ // error, we shouldn't be here, if we are then the wrong service/function was called
+ }
+
+ // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL
+ $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $folderName . ' ' . ucwords($feedType), null, null, null,
+ 'urn:uuid:' . $folderName . '-' . $feedType);
+
+ foreach($entries as $cmisEntry)
+ {
+ KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $folderName);
+ }
+
+ // false
+
+ // global $childrenFeed
+ // $output = $childrenFeed[0];
+ // $output = $childrenFeed[1];
+
+ return $feed;
+ }
+
+ /**
+ * Retrieves data about a specific folder
+ *
+ * @param object $ObjectService The CMIS service
+ * @param string $repositoryId
+ * @param string $folderId
+ * @return string CMIS AtomPub feed
+ */
+ private function getFolderFeed($ObjectService, $repositoryId, $folderId)
+ {
+ $cmisEntry = $ObjectService->getProperties($repositoryId, $folderId, false, false);
+
+ $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null,
+ 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']);
+
+ KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $folderName);
+// // false
+// // global $folderFeed;
+// // $outputs =
+
+ return $feed;
+ }
+}
+
+/**
+ * AtomPub Service: types
+ *
+ * Returns a list of supported object types
+ *
+ */
+class KT_cmis_atom_service_types extends KT_cmis_atom_service
+{
+ public function GET_action()
+ {
+// $username = $password = 'admin';
+ $RepositoryService = new RepositoryService();
+ // technically do not need to log in to access this information
+ // TODO consider requiring authentication even to access basic repository information
+ $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
+
+ // fetch repository id
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ $types = $RepositoryService->getTypes($repositoryId);
+ $type = ((empty($this->params[0])) ? 'all' : $this->params[0]);
+ $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types);
+
+ //Expose the responseFeed
+ $this->responseFeed = $feed;
+ }
+}
+
+/**
+ * AtomPub Service: type
+ *
+ * Returns the type defintion for the selected type
+ *
+ */
+class KT_cmis_atom_service_type extends KT_cmis_atom_service
+{
+ public function GET_action()
+ {
+// $username = $password = 'admin';
+ $RepositoryService = new RepositoryService();
+ // technically do not need to log in to access this information
+ // TODO consider requiring authentication even to access basic repository information
+ $RepositoryService->startSession(self::$authData['username'], self::$authData['password']);
+
+ // fetch repository id
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ if (!isset($this->params[1]))
+ {
+ // For easier return in the wanted format, we call getTypes instead of getTypeDefinition.
+ // Calling this with a single type specified returns an array containing the definition of
+ // just the requested type.
+ // NOTE could maybe be more efficient to call getTypeDefinition direct and then place in
+ // an array on this side? or directly expose the individual entry response code and
+ // call directly from here rather than via getTypeFeed.
+ $type = ucwords($this->params[0]);
+ $types = $RepositoryService->getTypes($repositoryId, $type);
+ $feed = KT_cmis_atom_service_helper::getTypeFeed($type, $types);
+ }
+ else
+ {
+ // TODO dynamic dates, as needed everywhere
+ // NOTE children of types not yet implemented and we don't support any non-basic types at this time
+ $feed = $this->getTypeChildrenFeed($this->params[1]);
+ }
+
+ //Expose the responseFeed
+ $this->responseFeed=$feed;
+ }
+ /**
+ * Retrieves a list of child types for the supplied type
+ *
+ * NOTE this currently returns a hard coded empty list, since we do not currently support child types
+ * TODO make dynamic if/when we support checking for child types (we don't actually need to support child types themselves)
+ *
+ * @param string $type
+ * @return string CMIS AtomPub feed
+ */
+ private function getTypeChildrenFeed()
+ {
+ //Create a new response feed
+ // $baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL
+ $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Child Types of ' . ucwords($this->params[0]), null, null, null,
+ $this->params[0] . '-children');
+
+ // TODO actually fetch child types - to be implemented when we support child types in the API
+
+ // id
+
+ // links
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','first'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1] . '?pageNo=1&pageSize=0'));
+ $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed'));
+
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','last'));
+ // TODO set page number correctly - to be done when we support paging the the API
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . 'type/' . $this->params[0] . '/' . $this->params[1] . '?pageNo=1&pageSize=0'));
+ $link->appendChild($feed->newAttr('type', 'application/atom+xml;type=feed'));
+
+ // TODO actual dynamic listing, currently we have no objects with which to test
+
+ // TODO
+// 2009-06-23T13:40:32.786+02:00
+// false
+/*
+ // TODO need to create this dynamically now, will no longer work with static output
+ $output = '
+
+ urn:uuid:type-' . $type . '-children
+
+
+
+ Child types of ' . $type . '
+ 2009-06-23T13:40:32.786+02:00
+ false
+ ';
+*/
+ return $feed;
+ }
+
+}
+
+/**
+ * AtomPub Service: checkedout
+ *
+ * Returns a list of checked out documents for the logged in user
+ *
+ */
+// NOTE this is always an empty document, underlying API code still to be implemented
+class KT_cmis_atom_service_checkedout extends KT_cmis_atom_service
+{
+ public function GET_action()
+ {
+// $username = $password = 'admin';
+ $RepositoryService = new RepositoryService();
+ $NavigationService = new NavigationService();
+
+ $NavigationService->startSession(self::$authData['username'], self::$authData['password']);
+
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ $checkedout = $NavigationService->getCheckedoutDocs($repositoryId);
+
+ //Create a new response feed
+ $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, 'Checked out Documents', null, null, null, 'urn:uuid:checkedout');
+
+ foreach($checkedout as $document)
+ {
+ $entry = $feed->newEntry();
+ $objectElement = $feed->newElement('cmis:object');
+ $propertiesElement = $feed->newElement('cmis:properties');
+
+ foreach($cmisEntry['properties'] as $propertyName => $property)
+ {
+ $propElement = $feed->newElement('cmis:' . $property['type']);
+ $propElement->appendChild($feed->newAttr('cmis:name', $propertyName));
+ $feed->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement);
+ $propertiesElement->appendChild($propElement);
+ }
+
+ $objectElement->appendChild($propertiesElement);
+ $entry->appendChild($objectElement);
+ }
+
+ $entry = null;
+ $feed->newField('hasMoreItems', 'false', $entry, true);
+
+ //Expose the responseFeed
+ $this->responseFeed = $feed;
+ }
+
+}
+
+/**
+ * AtomPub Service: document
+ *
+ * Returns detail on a particular document
+ *
+ */
+class KT_cmis_atom_service_document extends KT_cmis_atom_service
+{
+ public function GET_action()
+ {
+// $username = $password = 'admin';
+ $RepositoryService = new RepositoryService();
+
+ $ObjectService = new ObjectService();
+ $ObjectService->startSession(self::$authData['username'], self::$authData['password']);
+
+ $repositories = $RepositoryService->getRepositories();
+ $repositoryId = $repositories[0]['repositoryId'];
+
+ $cmisEntry = $ObjectService->getProperties($repositoryId, $this->params[0], false, false);
+
+ //Create a new response feed
+ $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $cmisEntry['properties']['ObjectTypeId']['value'], null, null, null,
+ 'urn:uuid:' . $cmisEntry['properties']['ObjectId']['value']);
+
+ KT_cmis_atom_service_helper::createObjectEntry($feed, $cmisEntry, $cmisEntry['properties']['ParentId']['value']);
+
+ // false
+
+// global $docFeed;
+// $output = $docFeed;
+
+ //Expose the responseFeed
+ $this->responseFeed=$feed;
+ }
+}
+
+$childrenFeed[] = '
+
+ urn:uuid:28537649-8af2-4c74-aa92-5d8bbecac9ce-children
+
+ Root Folder Children
+
+ urn:uuid:86224486-b7ae-4074-a793-82cd259b0026-folder
+
+
+
+
+
+ DroppedDocuments
+ DroppedDocuments
+
+
+
+
+ F2
+
+
+ Folder
+
+
+ DroppedDocuments
+
+
+
+
+
+
+ urn:uuid:86224486-b7ae-4074-a793-82cd259b0026-folder
+
+
+
+
+
+ Test KT Folder
+ Test KT Folder
+
+
+
+ F4
+
+
+
+ Folder
+
+
+ Test KT Folder
+
+
+
+
+
+
+ admin
+ urn:uuid:2df9d676-f173-47bb-8ec1-41fa1186b66d
+
+
+
+
+
+
+
+
+
+ 2009-06-23T09:40:47.889+02:00
+
+ h4555-cmis-so.pdf
+ 2009-06-23T09:40:58.524+02:00
+
+
+
+ workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d
+ document
+ document
+ admin
+
+ 2009-06-23T09:40:47.889+02:00
+ admin
+ 2009-06-23T09:40:58.524+02:00
+ h4555-cmis-so.pdf
+ false
+
+ true
+ false
+ false
+
+ workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d
+
+ false
+
+
+
+ 343084
+ application/pdf
+ h4555-cmis-so.pdf
+
+ http://10.33.4.34:8080/alfresco/service/api/node/workspace/SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d/content.h4555-cmis-so.pdf
+
+
+
+
+
+ ';
+
+ $childrenFeed[] = '
+
+System
+Alfresco (Labs)
+http://10.33.4.34:8080/alfresco/images/logo/AlfrescoLogo16.ico
+urn:uuid:28537649-8af2-4c74-aa92-5d8bbecac9ce-children
+
+
+
+
+
+Company Home Children
+2009-06-18T10:20:29.937+02:00
+
+System
+e98319fa-76e4-478f-8ce8-a3a0fd683e2c
+urn:uuid:e98319fa-76e4-478f-8ce8-a3a0fd683e2c
+
+
+
+
+
+
+
+
+
+
+
+2009-06-18T10:20:37.788+02:00
+Site Collaboration Spaces
+Sites
+2009-06-18T10:20:37.874+02:00
+
+
+
+workspace://SpacesStore/e98319fa-76e4-478f-8ce8-a3a0fd683e2c
+folder
+F/st_sites
+System
+
+2009-06-18T10:20:37.788+02:00
+System
+2009-06-18T10:20:37.874+02:00
+Sites
+workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce
+
+
+
+
+2009-06-18T10:20:37.874+02:00
+http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif
+
+
+System
+8c80a0f7-74b4-4bd8-bb76-a2464e4b2d10
+urn:uuid:8c80a0f7-74b4-4bd8-bb76-a2464e4b2d10
+
+
+
+
+
+
+
+
+
+
+
+2009-06-18T10:20:29.939+02:00
+User managed definitions
+Data Dictionary
+2009-06-18T10:20:30.004+02:00
+
+
+
+workspace://SpacesStore/8c80a0f7-74b4-4bd8-bb76-a2464e4b2d10
+folder
+folder
+System
+
+2009-06-18T10:20:29.939+02:00
+System
+2009-06-18T10:20:30.004+02:00
+Data Dictionary
+workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce
+
+
+
+
+2009-06-18T10:20:30.004+02:00
+http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif
+
+
+System
+ba2524ef-7f3d-4ed4-84a0-8d99b6524737
+urn:uuid:ba2524ef-7f3d-4ed4-84a0-8d99b6524737
+
+
+
+
+
+
+
+
+
+
+
+2009-06-18T10:20:30.312+02:00
+The guest root space
+Guest Home
+
+2009-06-18T10:20:30.400+02:00
+
+
+workspace://SpacesStore/ba2524ef-7f3d-4ed4-84a0-8d99b6524737
+folder
+folder
+System
+
+2009-06-18T10:20:30.312+02:00
+System
+2009-06-18T10:20:30.400+02:00
+Guest Home
+workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce
+
+
+
+
+2009-06-18T10:20:30.400+02:00
+http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif
+
+
+System
+86224486-b7ae-4074-a793-82cd259b0026
+urn:uuid:86224486-b7ae-4074-a793-82cd259b0026
+
+
+
+
+
+
+
+
+
+
+
+2009-06-18T10:20:30.402+02:00
+User Homes
+User Homes
+2009-06-18T10:20:30.428+02:00
+
+
+
+workspace://SpacesStore/86224486-b7ae-4074-a793-82cd259b0026
+folder
+folder
+System
+
+2009-06-18T10:20:30.402+02:00
+System
+2009-06-18T10:20:30.428+02:00
+User Homes
+workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce
+
+
+
+
+2009-06-18T10:20:30.428+02:00
+http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif
+
+
+System
+0df9087f-e334-4890-a467-b60e3d6be92c
+urn:uuid:0df9087f-e334-4890-a467-b60e3d6be92c
+
+
+
+
+
+
+
+
+
+
+
+2009-06-18T10:20:45.115+02:00
+Web Content Management Spaces
+Web Projects
+2009-06-18T10:20:45.137+02:00
+
+
+
+workspace://SpacesStore/0df9087f-e334-4890-a467-b60e3d6be92c
+folder
+folder
+System
+
+2009-06-18T10:20:45.115+02:00
+System
+2009-06-18T10:20:45.137+02:00
+Web Projects
+workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce
+
+
+
+
+2009-06-18T10:20:45.137+02:00
+http://10.33.4.34:8080/alfresco/images/icons/space-icon-default-16.gif
+
+
+admin
+urn:uuid:2df9d676-f173-47bb-8ec1-41fa1186b66d
+
+
+
+
+
+
+
+
+
+2009-06-23T09:40:47.889+02:00
+
+h4555-cmis-so.pdf
+2009-06-23T09:40:58.524+02:00
+
+
+
+workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d
+document
+document
+admin
+
+2009-06-23T09:40:47.889+02:00
+admin
+2009-06-23T09:40:58.524+02:00
+h4555-cmis-so.pdf
+false
+
+true
+false
+false
+
+workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d
+
+false
+
+
+
+343084
+application/pdf
+h4555-cmis-so.pdf
+
+http://10.33.4.34:8080/alfresco/service/api/node/workspace/SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d/content.h4555-cmis-so.pdf
+
+
+
+2009-06-23T09:40:58.524+02:00
+http://10.33.4.34:8080/alfresco/images/filetypes/pdf.gif
+
+false
+6
+0
+
+0
+';
+
+$folderFeed = '
+
+
+System
+28537649-8af2-4c74-aa92-5d8bbecac9ce
+urn:uuid:28537649-8af2-4c74-aa92-5d8bbecac9ce
+
+
+
+
+
+
+
+
+2009-06-18T10:20:29.871+02:00
+The company root space
+Company Home
+2009-06-18T10:20:29.937+02:00
+
+
+workspace://SpacesStore/28537649-8af2-4c74-aa92-5d8bbecac9ce
+folder
+folder
+System
+2009-06-18T10:20:29.871+02:00
+System
+2009-06-18T10:20:29.937+02:00
+Company Home
+
+
+
+
+2009-06-18T10:20:29.937+02:00
+http://127.0.0.1:8080/alfresco/images/icons/space-icon-default-16.gif
+
+';
+
+$docFeed = '
+
+
+admin
+urn:uuid:2df9d676-f173-47bb-8ec1-41fa1186b66d
+
+
+
+
+
+
+
+
+2009-06-23T09:40:47.889+02:00
+
+h4555-cmis-so.pdf
+2009-06-23T09:40:58.524+02:00
+
+
+workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d
+document
+document
+admin
+2009-06-23T09:40:47.889+02:00
+admin
+2009-06-23T09:40:58.524+02:00
+h4555-cmis-so.pdf
+false
+true
+false
+false
+
+workspace://SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d
+false
+
+
+
+343084
+application/pdf
+h4555-cmis-so.pdf
+http://127.0.0.1:8080/alfresco/service/api/node/workspace/SpacesStore/2df9d676-f173-47bb-8ec1-41fa1186b66d/content.h4555-cmis-so.pdf
+
+
+
+2009-06-23T09:40:58.524+02:00
+http://127.0.0.1:8080/alfresco/images/filetypes/pdf.gif
+
+';
+?>
\ No newline at end of file
diff --git a/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
new file mode 100644
index 0000000..aa8655d
--- /dev/null
+++ b/webservice/atompub/cmis/KT_cmis_atom_service_helper.inc.php
@@ -0,0 +1,219 @@
+newId('urn:uuid:' . $cmisEntry['properties']['Name']['value'] . '-'
+// . strtolower($cmisEntry['properties']['ObjectTypeId']['value']), $entry);
+
+// echo $_SERVER['QUERY_STRING']."
\n";
+// preg_match('/^\/?[^\/]*\/folder\/(.*)\/[^\/]*\/?$/', trim($_SERVER['QUERY_STRING'], '/'), $matches);
+// $path = $matches[1];
+// $parent = preg_replace('/\/[^\/]*$/', '', $path);
+// // TODO fix path to work on old method, after fixing drupal module to not require extended path
+//
+// $path = '';
+
+ $id = $cmisEntry['properties']['ObjectId']['value'];
+ $entry = $feed->newEntry();
+ $feed->newField('id', 'urn:uuid:' . $id, $entry);
+// print_r($cmisEntry);
+ // links
+ // TODO check parent link is correct, fix if needed
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-parent'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $cmisEntry['properties']['ParentId']['value']));
+ $entry->appendChild($link);
+
+ if (strtolower($cmisEntry['properties']['ObjectTypeId']['value']) == 'folder')
+ {
+ // TODO check parent link is correct, fix if needed
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-folderparent'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/folder/' . $cmisEntry['properties']['ParentId']['value']));
+ $entry->appendChild($link);
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-children'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/'
+ . strtolower($cmisEntry['properties']['ObjectTypeId']['value'])
+ . '/' . $cmisEntry['properties']['ObjectId']['value']
+ . '/children'));
+ $entry->appendChild($link);
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-descendants'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/'
+ . strtolower($cmisEntry['properties']['ObjectTypeId']['value'])
+ . '/' . $cmisEntry['properties']['ObjectId']['value']
+ . '/descendants'));
+ $entry->appendChild($link);
+ }
+
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-type'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($cmisEntry['properties']['ObjectTypeId']['value'])));
+ $entry->appendChild($link);
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-repository'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/servicedocument'));
+ $entry->appendChild($link);
+ // end links
+
+ $entry->appendChild($feed->newElement('summary', $cmisEntry['properties']['Name']['value']));
+ $entry->appendChild($feed->newElement('title', $cmisEntry['properties']['Name']['value']));
+
+ // main CMIS entry
+ $objectElement = $feed->newElement('cmis:object');
+ $propertiesElement = $feed->newElement('cmis:properties');
+
+ foreach($cmisEntry['properties'] as $propertyName => $property)
+ {
+ $propElement = $feed->newElement('cmis:' . $property['type']);
+ $propElement->appendChild($feed->newAttr('cmis:name', $propertyName));
+ $feed->newField('cmis:value', CMISUtil::boolToString($property['value']), $propElement);
+ $propertiesElement->appendChild($propElement);
+ }
+
+ $objectElement->appendChild($propertiesElement);
+ $entry->appendChild($objectElement);
+ }
+
+ /**
+ * Retrieves the list of types|type definition as a CMIS AtomPub feed
+ *
+ * @param string $typeDef Type requested - 'All Types' indicates a listing, else only a specific type
+ * @param array $types The types found
+ * @return string CMIS AtomPub feed
+ */
+ static public function getTypeFeed($typeDef, $types)
+ {
+ $typesString = '';
+ $typesHeading = '';
+ switch($typeDef)
+ {
+ case 'all':
+ case 'children':
+ case 'descendants':
+ $typesString = 'types-' . $typeDef;
+ $typesHeading = 'All Types';
+ break;
+ default:
+ $typesString = 'type-' . $typeDef;
+ $typesHeading = $typeDef;
+ break;
+ }
+
+ //Create a new response feed
+ $feed = new KT_cmis_atom_responseFeed(CMIS_APP_BASE_URI, $typesHeading, null, null, null, 'urn:uuid:' . $typesString);
+
+ foreach($types as $type)
+ {
+ $entry = $feed->newEntry();
+ $feed->newId('urn:uuid:type-' . strtolower($type['typeId']), $entry);
+
+ // links
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','self'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId'])));
+ $entry->appendChild($link);
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-type'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId'])));
+ $entry->appendChild($link);
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-children'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId']) . '/children'));
+ $entry->appendChild($link);
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-descendants'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/type/' . strtolower($type['typeId']) . '/descendants'));
+ $entry->appendChild($link);
+ $link = $feed->newElement('link');
+ $link->appendChild($feed->newAttr('rel','cmis-repository'));
+ $link->appendChild($feed->newAttr('href', CMIS_APP_BASE_URI . $feed->workspace . '/servicedocument'));
+ $entry->appendChild($link);
+
+ $entry->appendChild($feed->newElement('summary', $type['typeId'] . ' Type'));
+ $entry->appendChild($feed->newElement('title', $type['typeId']));
+
+ // main CMIS entry
+ $feedElement = $feed->newElement('cmis:' . strtolower($type['typeId']) . 'Type');
+ foreach($type as $property => $value)
+ {
+ $feed->newField($property, CMISUtil::boolToString($value), $feedElement);
+ }
+
+ $entry->appendChild($feedElement);
+ }
+
+ return $feed;
+ }
+
+ /**
+ * Fetches the CMIS objectId based on the path
+ *
+ * @param array $path
+ * @param object $ktapi KTAPI instance
+ */
+ // TODO make this much more efficient than this messy method
+ static public function getFolderId($path, &$ktapi)
+ {
+ // lose first item
+ array_shift($path);
+
+ $numQ = count($path);
+ $numFolders = $numQ;
+ $folderId = 1;
+
+ $start = 0;
+ while($start < $numFolders)
+ {
+ $name = $path[$numQ-$numFolders+$start];
+ // hack to fix drupal url encoding issue
+ $name = str_replace('%2520', '%20', $name);
+
+ $folderName = urldecode($name);
+ $folder = $ktapi->get_folder_by_name($folderName, $folderId);
+ $folderId = $folder->get_folderid();
+ ++$start;
+ }
+
+ return CMISUtil::encodeObjectId('Folder', $folderId);
+ }
+
+ static public function getCmisProperties($xmlArray)
+ {
+ $properties = array();
+
+ foreach($xmlArray as $cmisPropertyDefinition)
+ {
+ foreach($cmisPropertyDefinition as $propertyType => $propertyDefinition)
+ {
+ $properties[$propertyDefinition['@attributes']['cmis:name']] = $propertyDefinition['@children']['cmis:value'][0]['@value'];
+ }
+ }
+
+ return $properties;
+ }
+
+ static public function getAtomValues($xmlArray, $tag)
+ {
+ if (!is_null($xmlArray['atom:'.$tag]))
+ return $xmlArray['atom:'.$tag][0]['@value'];
+ else if (!is_null($xmlArray[$tag]))
+ return $xmlArray[$tag][0]['@value'];
+
+ return null;
+ }
+
+}
+
+?>
diff --git a/webservice/atompub/cmis/index.php b/webservice/atompub/cmis/index.php
new file mode 100644
index 0000000..b6c9570
--- /dev/null
+++ b/webservice/atompub/cmis/index.php
@@ -0,0 +1,117 @@
+.
+ *
+ * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
+ * California 94120-7775, or email info@knowledgetree.com.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "Powered by
+ * KnowledgeTree" logo and retain the original copyright notice. If the display of the
+ * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+ * must display the words "Powered by KnowledgeTree" and retain the original
+ * copyright notice.
+ * Contributor( s):
+ * Mark Holtzhausen
+ * Paul Barrett
+ *
+ */
+
+require_once('../../../config/dmsDefaults.php');
+
+define('KT_APP_BASE_URI', "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/?/');
+define('KT_APP_SYSTEM_URI', "http://".$_SERVER['HTTP_HOST']);
+define('KT_ATOM_LIB_FOLDER', '../../classes/atompub/');
+
+// should make the "dms" part dynamic but right now this is needed fast
+define('CMIS_APP_BASE_URI', trim(KT_APP_BASE_URI, '/'));
+define('CMIS_APP_SYSTEM_URI', KT_APP_SYSTEM_URI);
+define('CMIS_ATOM_LIB_FOLDER', trim(KT_ATOM_LIB_FOLDER, '/') . '/cmis/');
+
+// fetch username and password for auth; note that this apparently only works when PHP is run as an apache module
+// TODO method to fetch username and password when running PHP as CGI, if possible
+// HTTP Basic Auth:
+$username = $_SERVER['PHP_AUTH_USER'];
+$password = $_SERVER['PHP_AUTH_PW'];
+
+/**
+ * Includes
+ */
+include_once(KT_ATOM_LIB_FOLDER.'XMLns2array.inc.php');
+include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_server.inc.php');
+include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_baseDoc.inc.php');
+include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_responseFeed.inc.php'); //Containing the response feed class allowing easy atom feed generation
+include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_serviceDoc.inc.php'); //Containing the servicedoc class allowing easy ServiceDocument generation
+include_once(CMIS_ATOM_LIB_FOLDER.'KT_cmis_atom_service.inc.php'); //Containing the servicedoc class allowing easy ServiceDocument generation
+
+include_once('KT_cmis_atom_server.services.inc.php');
+//Start the AtomPubProtocol Routing Engine
+$APP = new KT_cmis_atom_server();
+
+// FIXME HACK! this should not happen every time, ONLY on a service doc request
+// CMIS service document setup
+$APP->initServiceDocument();
+// FIXME HACK! this should not happen every time, ONLY on a service doc request
+// User defined title tag
+$APP->addWorkspaceTag('dms','atom:title',$APP->repositoryInfo['repositoryName']);
+
+/**
+ * Register Services
+ *
+ * Registered services are classes extended from KT_atom_service
+ * The registration process takes the following parameters
+ * Workspace :The workspace within which the service collection will be grouped
+ * ServiceName :This is the name by which the service/collection is exposed
+ * ServiceClass :This is the class name of the class to be instantiated when this service is accessed
+ * Title :This is the title given to the service/collection in the servicedocument
+ * http://ktatompub/index.php?/service/param1/param2
+ * http://ktatompub/?/folder/children/whatfoldertolookat
+ * http://ktatompub/{folder/folder2/folder3/}service/param1/param2
+*/
+// TODO consider a registerServices function which will, dependant on what is requested, register the appropriate services, keep the logic out of the index file
+$APP->registerService('dms', 'folder', 'KT_cmis_atom_service_folder', 'Root Folder Children Collection',
+ array(rawurlencode($APP->repositoryInfo['rootFolderId']), 'children'), 'root-children');
+$APP->registerService('dms', 'folder', 'KT_cmis_atom_service_folder', 'Root Folder Children Collection',
+ array(rawurlencode($APP->repositoryInfo['rootFolderId']), 'descendants'), 'root-descendants');
+$APP->registerService('dms', 'checkedout', 'KT_cmis_atom_service_checkedout', 'Checked Out Document Collection', null, 'checkedout');
+$APP->registerService('dms', 'types', 'KT_cmis_atom_service_types', 'Object Type Collection', null, 'types-children');
+$APP->registerService('dms', 'types', 'KT_cmis_atom_service_types', 'Object Type Collection', null, 'types-descendants');
+
+// FIXME HACK! this should not happen every time, ONLY on a specific request, should NOT appear in service document as this is not definable at that time;
+// SHOULD be appearing in types listing feed
+// NOTE $requestParams is meaningless if not actually requesting this service, so not a good way to register the service really
+$queryArray=split('/',trim($_SERVER['QUERY_STRING'],'/'));
+$requestParams=array_slice($queryArray,2);
+$APP->registerService('dms', 'type', 'KT_cmis_atom_service_type', 'Object Type Collection', explode('/', $requestParams), 'types-descendants');
+// FIXME HACK! see above, this one for documents
+$APP->registerService('dms', 'document', 'KT_cmis_atom_service_document', 'Object Type Collection', explode('/', $requestParams), 'types-descendants');
+
+//Execute the current url/header request
+$APP->execute();
+
+//Render the resulting feed response
+$APP->render();
+
+?>
diff --git a/webservice/classes/atompub/KT_atom_responseFeed.inc.php b/webservice/classes/atompub/KT_atom_responseFeed.inc.php
index d78ac00..98ccb0d 100644
--- a/webservice/classes/atompub/KT_atom_responseFeed.inc.php
+++ b/webservice/classes/atompub/KT_atom_responseFeed.inc.php
@@ -4,11 +4,10 @@ class KT_atom_responseFeed extends KT_atom_baseDoc {
protected $baseURI=NULL;
protected $feed=NULL;
-
- public function __construct($baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL){
+ public function __construct($baseURI=NULL,$title=NULL,$link=NULL,$updated=NULL,$author=NULL,$id=NULL, $workspace = null){
parent::__construct();
+ $this->baseURI = $baseURI;
$this->constructHeader();
- $this->baseURI=$baseURI;
}
protected function constructHeader(){
diff --git a/webservice/classes/atompub/KT_atom_server.inc.php b/webservice/classes/atompub/KT_atom_server.inc.php
index 3a3e9d6..91bb1ca 100644
--- a/webservice/classes/atompub/KT_atom_server.inc.php
+++ b/webservice/classes/atompub/KT_atom_server.inc.php
@@ -3,7 +3,7 @@ class KT_atom_server{
protected $services=array();
protected $workspaceDetail=array();
protected $errors=array();
- protected $output='';
+ public $output='';
protected $queryArray=array();
protected $serviceName='';
protected $method='';
@@ -13,6 +13,9 @@ class KT_atom_server{
public function __construct(){
}
+ protected function hook_beforeDocCreate($doc){return true;}
+ protected function hook_beforeDocRender($doc){return true;}
+
/**
* Run the server switchboard - find the correct service class to instantiate, execute & render that class with the passed parameteres
*
@@ -22,23 +25,23 @@ class KT_atom_server{
$queryArray=split('/',trim($_SERVER['QUERY_STRING'],'/'));
$rawRequest=@file_get_contents('php://input');
- $workspace=strtolower(trim($queryArray[0]));
+ $workspace=strtolower(trim($queryArray[0]));
$serviceName=strtolower(trim($queryArray[1]));
$requestParams=array_slice($queryArray,2);
$this->queryArray=$queryArray;
- $this->serviceName=$service;
+ $this->serviceName=$serviceName;
$this->method=$reqMethod;
$this->workspace=$workspace;
-
- if($workspace=='servicedocument'){
+
+ if($workspace=='servicedocument'){
$this->serviceDocument();
return;
}
-
+
$service=$this->getRegisteredService($workspace,$serviceName);
if(is_array($service)){
$serviceClass=$service['serviceClass'];
- echo 'made it';
+// echo 'made it';
$serviceObject=new $serviceClass($reqMethod,$requestParams,$rawRequest);
$this->output=$serviceObject->render();
}else{
@@ -46,9 +49,10 @@ class KT_atom_server{
// return;
$serviceObject=new KT_atom_service($requestParams,$rawRequest);
$serviceObject->setStatus(KT_atom_service::STATUS_NOT_FOUND);
- $this->output=$serviceObject->render();
+ if($this->hook_beforeDocRender($serviceObject)) $this->output=$serviceObject->render();
}
$this->serviceObject=$serviceObject;
+ return $serviceObject;
}
diff --git a/webservice/classes/atompub/KT_atom_service.inc.php b/webservice/classes/atompub/KT_atom_service.inc.php
index 0e46afe..d59818c 100644
--- a/webservice/classes/atompub/KT_atom_service.inc.php
+++ b/webservice/classes/atompub/KT_atom_service.inc.php
@@ -1,13 +1,15 @@
responseFeed->render();
}
- protected function xml2array($xml){
- if(class_exists('')){
+ protected function xml2array($xml)
+ {
+ if (trim($xml) == '') return array();
+
+ if(class_exists('XMLns2array'))
+ {
$array=XMLns2array::parse($xml);
- }else{
- $array=json_decode(json_encode(@simplexml_load_string($xml)),true);
+ }
+ else
+ {
+ $array=json_decode(json_encode(@simplexml_load_string($xml)), true);
}
return $array;
}
diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_baseDoc.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_baseDoc.inc.php
new file mode 100644
index 0000000..fc24e21
--- /dev/null
+++ b/webservice/classes/atompub/cmis/KT_cmis_atom_baseDoc.inc.php
@@ -0,0 +1,53 @@
+.
+ *
+ * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
+ * California 94120-7775, or email info@knowledgetree.com.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "Powered by
+ * KnowledgeTree" logo and retain the original copyright notice. If the display of the
+ * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+ * must display the words "Powered by KnowledgeTree" and retain the original
+ * copyright notice.
+ * Contributor( s):
+ * Mark Holtzhausen
+ * Paul Barrett
+ *
+ */
+
+/**
+ * Includes
+ */
+
+include_once(KT_ATOM_LIB_FOLDER.'KT_atom_baseDoc.inc.php'); //Containing the parent class allowing easy XML manipulation
+
+class KT_cmis_atom_baseDoc extends KT_atom_baseDoc {
+
+ // override and extend as needed
+
+}
+
+?>
\ No newline at end of file
diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_responseFeed.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_responseFeed.inc.php
new file mode 100644
index 0000000..1aa8902
--- /dev/null
+++ b/webservice/classes/atompub/cmis/KT_cmis_atom_responseFeed.inc.php
@@ -0,0 +1,112 @@
+workspace = strtolower(trim($queryArray[0]));
+ $this->id = $id;
+ $this->title = $title;
+
+ parent::__construct($baseURI, $title, $link, $updated, $author, $id);
+ }
+
+ protected function constructHeader()
+ {
+ $feed = $this->newElement('feed');
+// $feed->appendChild($this->newAttr('xmlns','http://www.w3.org/2007/app'));
+// $feed->appendChild($this->newAttr('xmlns:atom','http://www.w3.org/2005/Atom'));
+ $feed->appendChild($this->newAttr('xmlns','http://www.w3.org/2005/Atom'));
+ $feed->appendChild($this->newAttr('xmlns:cmis','http://www.cmis.org/2008/05'));
+ $this->feed = &$feed;
+
+ if (!is_null($this->id))
+ {
+ $this->newId($this->id, $this->feed);
+ }
+
+ $link = $this->newElement('link');
+ $link->appendChild($this->newAttr('rel','self'));
+ $link->appendChild($this->newAttr('href', $this->baseURI . trim($_SERVER['QUERY_STRING'], '/')));
+ $feed->appendChild($link);
+
+ if (!is_null($this->title))
+ {
+ $this->feed->appendChild($this->newElement('title', $this->title));
+ }
+
+ $this->DOM->appendChild($this->feed);
+ }
+
+ public function &newId($id, $entry = null)
+ {
+ $id = $this->newElement('id', $id);
+ if(isset($entry))$entry->appendChild($id);
+ return $id;
+ }
+
+// public function &newField($name = NULL, $value = NULL, &$entry = NULL)
+// {
+// $append = false;
+//
+// if(func_num_args() > 3)
+// {
+// $append = ((func_get_arg(3) === true) ? true : false);
+// }
+//
+// $field = $this->newElement('cmis:' . $name, $value);
+//
+// if (isset($entry)) $entry->appendChild($field);
+// else if ($append) $this->feed->appendChild($field);
+//
+// return $field;
+// }
+
+ /*
+ public function &newEntry()
+ {
+ $entry = $this->newElement('entry');
+ $this->feed->appendChild($entry);
+ return $entry;
+ }
+
+ public function &newId($id, $entry = null)
+ {
+ $id = $this->newElement('id', $id);
+ if(isset($entry))$entry->appendChild($id);
+ return $id;
+ }
+
+ public function &newField($name = NULL, $value = NULL, &$entry = NULL)
+ {
+ $append = false;
+
+ if(func_num_args() > 3)
+ {
+ $append = ((func_get_arg(3) === true) ? true : false);
+ }
+
+ $field = $this->newElement('cmis:' . $name,$value);
+
+ if (isset($entry)) $entry->appendChild($field);
+ else if ($append) $this->feed->appendChild($field);
+
+ return $field;
+ }
+ */
+
+}
+
+class KT_cmis_atom_ResponseFeed_GET extends KT_cmis_atom_responseFeed{}
+class KT_cmis_atom_ResponseFeed_PUT extends KT_cmis_atom_responseFeed{}
+class KT_cmis_atom_ResponseFeed_POST extends KT_cmis_atom_responseFeed{}
+class KT_cmis_atom_ResponseFeed_DELETE extends KT_cmis_atom_responseFeed{}
+
+?>
\ No newline at end of file
diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php
new file mode 100644
index 0000000..4b1f460
--- /dev/null
+++ b/webservice/classes/atompub/cmis/KT_cmis_atom_server.inc.php
@@ -0,0 +1,124 @@
+getRepositories();
+ // fetch for default first repo; NOTE that this will probably have to change at some point, quick and dirty for now
+ $this->repositoryInfo = $RepositoryService->getRepositoryInfo($repositories[0]['repositoryId']);
+ }
+ }
+
+ public function serviceDocument()
+ {
+ $service = new KT_cmis_atom_serviceDoc(KT_APP_BASE_URI);
+
+ foreach($this->services as $workspace => $collection)
+ {
+ //Creating the Default Workspace for use with standard atomPub Clients
+ $ws = $service->newWorkspace();
+
+ $hadDetail=false;
+ if(isset($this->workspaceDetail[$workspace]))
+ {
+ if(is_array($this->workspaceDetail[$workspace]))
+ {
+ foreach ($this->workspaceDetail[$workspace] as $wsTag=>$wsValue)
+ {
+ $ws->appendChild($service->newElement($wsTag,$wsValue));
+ $hadDetail=true;
+ }
+ }
+ }
+
+ if(!$hadDetail) {
+ $ws->appendChild($service->newElement('atom:title',$workspace));
+ }
+
+ $ws->appendChild($service->newAttr('cmis:repositoryRelationship', $this->repositoryInfo['repositoryRelationship']));
+
+ // repository information
+ $element = $service->newElement('cmis:repositoryInfo');
+ foreach($this->repositoryInfo as $key => $repoData)
+ {
+ if ($key == 'rootFolderId')
+ {
+ $repoData = CMIS_APP_BASE_URI . $workspace . '/folder/' . rawurlencode($repoData);
+ }
+
+ if (!is_array($repoData))
+ {
+ $element->appendChild($service->newElement('cmis:' . $key, $repoData));
+ }
+ else
+ {
+ $elementSub = $service->newElement('cmis:' . $key);
+ foreach($repoData as $key2 => $data)
+ {
+ $elementSub->appendChild($service->newElement('cmis:' . $key2, CMISUtil::boolToString($data)));
+ }
+ $element->appendChild($elementSub);
+ }
+ }
+ $ws->appendChild($element);
+
+ foreach($collection as $serviceName => $serviceInstance)
+ {
+ foreach($serviceInstance as $instance)
+ {
+ $collectionStr = CMIS_APP_BASE_URI . $workspace . '/' . $serviceName . '/'
+ . (is_array($instance['parameters']) ? implode('/', $instance['parameters']).'/' : '');
+ $col = $service->newCollection($collectionStr, $instance['title'], $instance['collectionType'], $ws);
+ }
+ }
+ }
+
+ $this->output = $service->getAPPdoc();
+ }
+
+ public function registerService($workspace = NULL, $serviceName = NULL, $serviceClass = NULL, $title = NULL,
+ $serviceParameters = NULL, $collectionType = NULL)
+ {
+ $workspace = strtolower(trim($workspace));
+ $serviceName = strtolower(trim($serviceName));
+
+ $serviceRecord = array(
+ 'fileName' => $fileName,
+ 'serviceClass' => $serviceClass,
+ 'title' => $title,
+ 'parameters' => $serviceParameters,
+ 'collectionType' => $collectionType
+ );
+
+ $this->services[$workspace][$serviceName][] = $serviceRecord;
+ }
+
+ public function getRegisteredService($workspace, $serviceName = NULL)
+ {
+ $serviceName = strtolower(trim($serviceName));
+ if(isset($this->services[$workspace][$serviceName]))
+ {
+ return $this->services[$workspace][$serviceName][0];
+ }
+
+ return false;
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php
new file mode 100644
index 0000000..f136f3d
--- /dev/null
+++ b/webservice/classes/atompub/cmis/KT_cmis_atom_service.inc.php
@@ -0,0 +1,36 @@
+headers);
+// print_r($_SERVER);
+ // attempt to fetch auth info from supplied headers
+ if (!empty($this->headers['Authorization']))
+ {
+ $auth = base64_decode(preg_replace('/Basic */', '', $this->headers['Authorization']));
+ $authData = explode(':', $auth);
+// print_r($authData);
+ self::$authData['username'] = $authData[0];
+ self::$authData['password'] = $authData[1];
+ }
+ // if failed, attempt to fetch from $_SERVER array instead
+ else if (isset($_SERVER['PHP_AUTH_USER']))
+ {
+ self::$authData['username'] = $_SERVER['PHP_AUTH_USER'];
+ self::$authData['password'] = $_SERVER['PHP_AUTH_PW'];
+ }
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php b/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php
new file mode 100644
index 0000000..082535e
--- /dev/null
+++ b/webservice/classes/atompub/cmis/KT_cmis_atom_serviceDoc.inc.php
@@ -0,0 +1,125 @@
+.
+ *
+ * You can contact KnowledgeTree Inc., PO Box 7775 #87847, San Francisco,
+ * California 94120-7775, or email info@knowledgetree.com.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "Powered by
+ * KnowledgeTree" logo and retain the original copyright notice. If the display of the
+ * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
+ * must display the words "Powered by KnowledgeTree" and retain the original
+ * copyright notice.
+ * Contributor( s):
+ * Mark Holtzhausen
+ * Paul Barrett
+ *
+ */
+
+
+/**
+ * Includes
+ */
+include_once(KT_ATOM_LIB_FOLDER.'KT_atom_serviceDoc.inc.php');
+//include_once('KT_atom_baseDoc.inc.php');
+
+class KT_cmis_atom_serviceDoc extends KT_atom_serviceDoc {
+
+ // override and extend as needed
+
+ public $repositoryInfo = array();
+
+ public function __construct($baseURI = NULL)
+ {
+ parent::__construct();
+
+ // get repositoryInfo
+ // NOTE currently we only support one repository, which will be the first one found in the repositories.xml config
+ // TODO multiple repositories as individual workspaces
+
+ include 'services/cmis/RepositoryService.inc.php';
+ $RepositoryService = new RepositoryService();
+
+ // fetch data for response
+ $repositories = $RepositoryService->getRepositories();
+ // fetch for default first repo; NOTE that this will probably have to change at some point, quick and dirty for now
+ $this->repositoryInfo = $RepositoryService->getRepositoryInfo($repositories[0]['repositoryId']);
+ }
+
+ protected function constructServiceDocumentHeaders()
+ {
+ $service = $this->newElement('service');
+ $service->appendChild($this->newAttr('xmlns', 'http://www.w3.org/2007/app'));
+ $service->appendChild($this->newAttr('xmlns:atom', 'http://www.w3.org/2005/Atom'));
+ $service->appendChild($this->newAttr('xmlns:cmis', 'http://www.cmis.org/2008/05'));
+ $this->service =& $service;
+ $this->DOM->appendChild($this->service);
+ }
+
+ public function &newCollection($url = NULL, $title = NULL, $cmisCollectionType = NULL, &$ws = NULL)
+ {
+ $collection=$this->newElement('collection');
+ $collection->appendChild($this->newAttr('href', $url));
+ $collection->appendChild($this->newAttr('cmis:collectionType', $cmisCollectionType));
+ $collection->appendChild($this->newElement('atom:title', $title));
+ if(isset($ws))$ws->appendChild($collection);
+ return $collection;
+ }
+
+}
+
+/**
+
+
+
+ Main Site
+
+ My Blog Entries
+
+
+
+ Pictures
+ image/png
+ image/jpeg
+ image/gif
+
+
+
+ Sidebar Blog
+
+ Remaindered Links
+ application/atom+xml;type=entry
+
+
+
+
+
+
+
+
+ */
+
+
+?>
\ No newline at end of file
diff --git a/webservice/classes/atompub/cmis/NavigationService.inc.php b/webservice/classes/atompub/cmis/NavigationService.inc.php
new file mode 100644
index 0000000..fe47e18
--- /dev/null
+++ b/webservice/classes/atompub/cmis/NavigationService.inc.php
@@ -0,0 +1,124 @@
+
diff --git a/webservice/classes/atompub/cmis/ObjectService.inc.php b/webservice/classes/atompub/cmis/ObjectService.inc.php
new file mode 100644
index 0000000..90171e6
--- /dev/null
+++ b/webservice/classes/atompub/cmis/ObjectService.inc.php
@@ -0,0 +1,90 @@
+
diff --git a/webservice/classes/atompub/cmis/RepositoryService.inc.php b/webservice/classes/atompub/cmis/RepositoryService.inc.php
new file mode 100644
index 0000000..55a3a80
--- /dev/null
+++ b/webservice/classes/atompub/cmis/RepositoryService.inc.php
@@ -0,0 +1,85 @@
+