From 0ed9c71e71cc1b97022b96ce1529b0565df7bc5f Mon Sep 17 00:00:00 2001 From: Paul Barrett Date: Thu, 4 Jun 2009 13:43:36 +0200 Subject: [PATCH] Story ID: 702240. Created base CMIS repository service helpers and underlying CMIS classes required for read only access. Created ktcmis interface for utilising these service helpers and classes. Created classes required for consumption of interface output by web services (soap only) --- ktcmis/classes/CMISBaseObject.inc.php | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISDocumentPropertyCollection.inc.php | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISFolderPropertyCollection.inc.php | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISObject.inc.php | 305 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISObjectTypes.inc.php | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISPropertyCollection.inc.php | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISRepository.inc.php | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISRepositoryCapabilities.inc.php | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/classes/CMISRepositoryInfo.inc.php | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/config/repositories.xml | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/ktcmis.inc.php | 459 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/objecttypes/CMISDocumentObject.inc.php | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/objecttypes/CMISFolderObject.inc.php | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/services/CMISNavigationService.inc.php | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/services/CMISObjectService.inc.php | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/services/CMISRepositoryService.inc.php | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktcmis/util/CMISUtil.inc.php | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/runtests.php | 19 +++++++++++-------- webservice/classes/soap/config.php | 49 +++++++++++++++++++++++++++---------------------- webservice/classes/soap/model/CMISObjectPropertiesType.class.php | 18 ++++++++++++++++++ webservice/classes/soap/model/CMISObjectType.class.php | 18 ++++++++++++++++++ webservice/classes/soap/model/CMISPropertiesType.class.php | 21 +++++++++++++++++++++ webservice/classes/soap/model/CMISProperty.class.php | 15 +++++++++++++++ webservice/classes/soap/model/CMISPropertyCollectionType.class.php | 36 ++++++++++++++++++++++++++++++++++++ webservice/classes/soap/model/CMISPropertyDefinitionType.class.php | 13 +++++++++++++ webservice/classes/soap/model/CMISRepositoryCapabilitiesType.class.php | 36 ++++++++++++++++++++++++++++++++++++ webservice/classes/soap/model/CMISRepositoryEntryType.class.php | 18 ++++++++++++++++++ webservice/classes/soap/model/CMISRepositoryInfoType.class.php | 42 ++++++++++++++++++++++++++++++++++++++++++ webservice/classes/soap/model/CMISService.class.php | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ webservice/classes/soap/model/CMISTypeDefinitionType.class.php | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ webservice/tests/webservice.php | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- 31 files changed, 3521 insertions(+), 46 deletions(-) create mode 100644 ktcmis/classes/CMISBaseObject.inc.php create mode 100644 ktcmis/classes/CMISDocumentPropertyCollection.inc.php create mode 100644 ktcmis/classes/CMISFolderPropertyCollection.inc.php create mode 100644 ktcmis/classes/CMISObject.inc.php create mode 100644 ktcmis/classes/CMISObjectTypes.inc.php create mode 100644 ktcmis/classes/CMISPropertyCollection.inc.php create mode 100644 ktcmis/classes/CMISRepository.inc.php create mode 100644 ktcmis/classes/CMISRepositoryCapabilities.inc.php create mode 100644 ktcmis/classes/CMISRepositoryInfo.inc.php create mode 100644 ktcmis/config/repositories.xml create mode 100644 ktcmis/ktcmis.inc.php create mode 100644 ktcmis/objecttypes/CMISDocumentObject.inc.php create mode 100644 ktcmis/objecttypes/CMISFolderObject.inc.php create mode 100644 ktcmis/services/CMISNavigationService.inc.php create mode 100644 ktcmis/services/CMISObjectService.inc.php create mode 100644 ktcmis/services/CMISRepositoryService.inc.php create mode 100644 ktcmis/util/CMISUtil.inc.php create mode 100644 webservice/classes/soap/model/CMISObjectPropertiesType.class.php create mode 100644 webservice/classes/soap/model/CMISObjectType.class.php create mode 100644 webservice/classes/soap/model/CMISPropertiesType.class.php create mode 100644 webservice/classes/soap/model/CMISProperty.class.php create mode 100644 webservice/classes/soap/model/CMISPropertyCollectionType.class.php create mode 100644 webservice/classes/soap/model/CMISPropertyDefinitionType.class.php create mode 100644 webservice/classes/soap/model/CMISRepositoryCapabilitiesType.class.php create mode 100644 webservice/classes/soap/model/CMISRepositoryEntryType.class.php create mode 100644 webservice/classes/soap/model/CMISRepositoryInfoType.class.php create mode 100644 webservice/classes/soap/model/CMISService.class.php create mode 100644 webservice/classes/soap/model/CMISTypeDefinitionType.class.php diff --git a/ktcmis/classes/CMISBaseObject.inc.php b/ktcmis/classes/CMISBaseObject.inc.php new file mode 100644 index 0000000..f0f636a --- /dev/null +++ b/ktcmis/classes/CMISBaseObject.inc.php @@ -0,0 +1,134 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +require_once(CMIS_DIR . '/classes/CMISObject.inc.php'); + +// NOTE chemistry class was abstract but this has gone in a different direction anyway +abstract class CMISBaseObject implements CMISObject { + + protected $typeId; + protected $queryName; + protected $displayName; + protected $baseType; + protected $baseTypeQueryName; + protected $parentId; + protected $description; + protected $creatable; + protected $fileable; + protected $queryable; + protected $includedInSupertypeQuery; + protected $controllable; // NOTE deprecated? part of policy objects specification, policy objects are indicated as TODO remove + + protected $properties; // list of property objects which define the additional properties for this object + + // TODO all we have here so far is getAttributes & getProperties :) + // add all the other methods as we go along + + function __construct() + { +// $propertyDef = new PropertyDefinition(); +// $this->properties[] = $propertyDef; + } + + /** + * Returns a listing of all attributes in an array + * + * @return array $attributes + */ + function getAttributes() + { + $attributes = array(); + + // TODO look at how chemistry does this and implement something similar + // for now this is fine as we are just trying to get things up and running :) + $attributes['typeId'] = $this->typeId; + $attributes['queryName'] = $this->queryName; + $attributes['displayName'] = $this->displayName; + $attributes['baseType'] = $this->baseType; + $attributes['baseTypeQueryName'] = $this->baseTypeQueryName; + $attributes['parentId'] = $this->parentId; + $attributes['description'] = $this->description; + $attributes['creatable'] = $this->creatable; + $attributes['fileable'] = $this->fileable; + $attributes['queryable'] = $this->queryable; + $attributes['includedInSupertypeQuery'] = $this->includedInSupertypeQuery; + $attributes['controllable'] = $this->includedInSupertypeQuery; + + return $attributes; + } + + function getAttribute($field) + { + return $this->{$field}; + } + + /** + * Sets properties for this type + * Obeys the rules as specified in the property definitions (once implemented) + */ + function setProperty($field, $value) + { + $this->properties->setValue($field, $value); + } + + /** + * Sets properties for this type - internal only function which allows + * setting of properties by object on initialisation or re-query + * + * This will bypass the property definition checks for updateability (once implemented) + */ + protected function _setPropertyInternal($field, $value) + { + $this->properties->setValue($field, $value); + } + + /** + * Fetches properties for this object type + */ + function getProperties() + { + return $this->properties; + } + +} + +?> diff --git a/ktcmis/classes/CMISDocumentPropertyCollection.inc.php b/ktcmis/classes/CMISDocumentPropertyCollection.inc.php new file mode 100644 index 0000000..8a08b55 --- /dev/null +++ b/ktcmis/classes/CMISDocumentPropertyCollection.inc.php @@ -0,0 +1,68 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +require_once(CMIS_DIR . '/classes/CMISPropertyCollection.inc.php'); + +/** + * This class contains the document object properties + */ +class CMISDocumentPropertyCollection extends CMISPropertyCollection { + + static $name; + static $isImmutable; + static $isLatestVersion; + static $isMajorVersion; + static $isLatestMajorVersion; + static $versionLabel; + static $versionSeriesId; + static $isVersionSeriesCheckedOut; + static $versionSeriesCheckedOutBy; + static $versionSeriesCheckedOutId; + static $checkinComment; + static $contentStreamLength; + static $contentStreamMimeType; + static $contentStreamFilename; + static $contentStreamUri; + +} + +?> diff --git a/ktcmis/classes/CMISFolderPropertyCollection.inc.php b/ktcmis/classes/CMISFolderPropertyCollection.inc.php new file mode 100644 index 0000000..dfafce9 --- /dev/null +++ b/ktcmis/classes/CMISFolderPropertyCollection.inc.php @@ -0,0 +1,56 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +require_once(CMIS_DIR . '/classes/CMISPropertyCollection.inc.php'); + +/** + * This class contains the folder object properties + */ +class CMISFolderPropertyCollection extends CMISPropertyCollection { + + static $name; + static $parentId; + static $allowedChildObjectTypeIds; + +} + +?> diff --git a/ktcmis/classes/CMISObject.inc.php b/ktcmis/classes/CMISObject.inc.php new file mode 100644 index 0000000..ee11fe2 --- /dev/null +++ b/ktcmis/classes/CMISObject.inc.php @@ -0,0 +1,305 @@ + + * The target folder is that into which the object has to be moved. When the + * object is multi-filed, a source folder to be moved out of must be + * specified. + * + * @param targetFolder the target folder + * @param sourceFolder the source folder, or {@code null} + */ +// function move($targetFolder, $sourceFolder = null); + + /** + * Deletes this object. + *

+ * When a filed object is deleted, it is removed from all folders it is + * filed in. + *

+ * This deletes a specific version of a document object. To delete all + * versions, use {@link #deleteAllVersions}. + *

+ * Deletion of a private working copy (checked out version) is the same as + * to cancel checkout. + */ +// function delete(); + + /** + * Unfiles this non-folder object. + *

+ * This removes this object from all folders it is filed in, but never + * deletes the object, which means that if unfiling is not supported, an + * exception will be thrown. + *

+ * If this object is a folder then an exception will be thrown. + * + * @see #delete + * @see Folder#remove + */ +// function unfile(); + + /* + * ----- Navigation Services ----- + */ + + /** + * Gets the parent folder, or the single folder in which the object is + * filed. + *

+ * For a folder, returns the parent folder, or {@code null} if there is no + * parent (for the root folder). + *

+ * For a non-folder, if the object is single-filed then the folder in which + * it is filed is returned, otherwise if the folder is unfiled then {@code + * null} is returned. An exception is raised if the object is multi-filed, + * so in doubt use {@link #getParents}. + * + * @return the parent folder, or {@code null}. + * + * @see #getParents + * @see Folder#getAncestors + */ +// function getParent(); + +// /** +// * Gets the direct parents of this object. +// *

+// * The object must be a non-folder, fileable object. +// * +// * @return the collection of parent folders +// * +// * @see #getParent +// * @see Folder#getAncestors +// */ +// function getParents(); +// +// /* +// * ----- Relationship Services ----- +// */ +// +// /** +// * Gets the relationships having as source or target this object. +// *

+// * Returns a list of relationships associated with this object, optionally +// * of a specified relationship type, and optionally in a specified +// * direction. +// *

+// * If typeId is {@code null}, returns relationships of any type. +// *

+// * Ordering is repository specific but consistent across requests. +// * +// * @param direction the direction of relationships to include +// * @param typeId the type ID, or {@code null} +// * @param includeSubRelationshipTypes {@code true} if relationships of any +// * sub-type of typeId are to be returned as well +// * @return the list of relationships +// */ +// function getRelationships($direction, $typeId, $includeSubRelationshipTypes); +// +// /* +// * ----- Policy Services ----- +// */ +// +// /** +// * Applies a policy to this object. +// *

+// * The object must be controllable. +// * +// * @param policy the policy +// */ +// function applyPolicy(Policy policy); +// +// /** +// * Removes a policy from this object. +// *

+// * Removes a previously applied policy from the object. The policy is not +// * deleted, and may still be applied to other objects. +// *

+// * The object must be controllable. +// * +// * @param policy the policy +// */ +// function removePolicy(Policy policy); +// +// /** +// * Gets the policies applied to this object. +// *

+// * Returns the list of policy objects currently applied to the object. Only +// * policies that are directly (explicitly) applied to the object are +// * returned. +// *

+// * The object must be controllable. +// */ +// function getPolicies(); +// + /* + * ----- data access ----- + */ + + /** + * The object's type definition. + */ +// function getType(); + + /** + * Gets a property. + * + * @param name the property name + * @return the property + */ +// function getProperty($name); + + /** + * Gets all the properties. + * + * @return a map of the properties + */ +// function getProperties(); + + /** + * Gets a property value. + * + * @param name the property name + * @return the property value + */ +// function getValue($name); + +// /** +// * Sets a property value. +// *

+// * Setting a {@code null} value removes the property. +// *

+// * Whether the value is saved immediately or not is repository-specific, see +// * {@link #save()}. +// * +// * @param name the property name +// * @param value the property value, or {@code null} +// */ +// function setValue($name, $value); +// +// /** +// * Sets several property values. +// *

+// * Setting a {@code null} value removes a property. +// *

+// * Whether the values are saved immediately or not is repository-specific, +// * see {@link #save()}. +// * +// * @param values the property values +// */ +// function setValues($values); +// +// /** +// * Saves the modifications done to the object through {@link #setValue}, +// * {@link #setValues} and {@link Document#setContentStream}. +// *

+// * Note that a repository is not required to wait until a {@link #save} is +// * called to actually save the modifications, it may do so as soon as +// * {@link #setValue} is called. +// *

+// * Calling {#link #save} is needed for objects newly created through +// * {@link Connection#newDocument} and similar methods. +// */ +// function save(); +// +// /* +// * ----- convenience methods ----- +// */ +// +// function getString($name); +// +// function getStrings($name); +// +// function getDecimal($name); +// +// function getDecimals($name); +// +// function getInteger($name); +// +// function getIntegers($name); +// +// function getBoolean($name); +// +// function getBooleans($name); +// +// function getDateTime($name); +// +// function getDateTimes($name); +// +// function getURI($name); +// +// function getURIs($name); +// +// function getId($name); +// +// function getIds($name); +// +// function getXML($name); +// +// function getXMLs($name); +// +// function getHTML($name); +// +// function getHTMLs($name); +// +// /* +// * ----- convenience methods for specific properties ----- +// */ +// +// function getId(); +// +// function getURI(); +// +// function getTypeId(); +// +// function getCreatedBy(); +// +// function getCreationDate(); +// +// function getLastModifiedBy(); +// +// function getLastModificationDate(); +// +// function getChangeToken(); +// +// function getName(); +// +// function isImmutable(); +// +// function isLatestVersion(); +// +// function isMajorVersion(); +// +// function isLatestMajorVersion(); +// +// function getVersionLabel(); +// +// function getVersionSeriesId(); +// +// function isVersionSeriesCheckedOut(); +// +// function getVersionSeriesCheckedOutBy(); +// +// function getVersionSeriesCheckedOutId(); +// +// function getCheckinComment(); +// +// /* +// * ----- convenience methods for specific properties (setter) ----- +// */ +// +// function setName($name); + +} + +?> diff --git a/ktcmis/classes/CMISObjectTypes.inc.php b/ktcmis/classes/CMISObjectTypes.inc.php new file mode 100644 index 0000000..fc2bf09 --- /dev/null +++ b/ktcmis/classes/CMISObjectTypes.inc.php @@ -0,0 +1,61 @@ +path = CMIS_DIR . '/objecttypes'; + $this->registerObjects(); + } + + function registerObjects() + { + // read object types directory to find supported object types + $this->objects = array(); + + // TODO check search code for correctPath function and see if similar is needed here + $dir = opendir($this->path); + while (($file = readdir($dir)) !== false) + { + if (substr($file,-14) == 'Object.inc.php') + { + // TODO check what if anything here is useful and reinstate +// require_once($this->path . '/' . $file); +// $class = substr($file, 0, -8); +// +// if (!class_exists($class)) +// { +// continue; +// } +// +// $field = new $class; +// if (is_null($field) || !($field instanceof FieldExpr)) +// { +// continue; +// } + + $this->objects[] = str_replace('CMIS', '', substr($file,0,-14)); + } + } + + closedir($dir); + } + + /** + * return a list of all supported objects + */ + function getObjectTypes() + { + return $this->objects; + } +} + +?> diff --git a/ktcmis/classes/CMISPropertyCollection.inc.php b/ktcmis/classes/CMISPropertyCollection.inc.php new file mode 100644 index 0000000..412f6a6 --- /dev/null +++ b/ktcmis/classes/CMISPropertyCollection.inc.php @@ -0,0 +1,76 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +/** + * This class contains the base properties shared by all object types + */ +abstract class CMISPropertyCollection { + + static $objectId; + static $URI; + static $typeId; + static $createdBy; + static $creationDate; + static $lastModifiedBy; + static $lastModificationDate; + static $changeToken; + + /** + * Gets the property value. + */ + function getValue($field) + { + return $this->{$field}; + } + + /** + * Sets the property value. + */ + // for connection-tied live objects + function setValue($field, $value) + { + $this->{$field} = $value; + } + +} + +?> diff --git a/ktcmis/classes/CMISRepository.inc.php b/ktcmis/classes/CMISRepository.inc.php new file mode 100644 index 0000000..1d11da8 --- /dev/null +++ b/ktcmis/classes/CMISRepository.inc.php @@ -0,0 +1,210 @@ +. +* +* 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. +* +* @copyright 2008-2009, KnowledgeTree Inc. +* @license GNU General Public License version 3 +* @author KnowledgeTree Team +* @package KTCMIS +* @version Version 0.1 +*/ + +require_once(CMIS_DIR . '/classes/CMISRepositoryInfo.inc.php'); + +/** + * A CMIS Repository. + */ +class CMISRepository { + + private $repositoryId; + private $repositoryURI; + + /** + * @var $RepositoryInfo The class holding information about this repository + */ + private $RepositoryInfo; + /** + * + * @var object $objectTypes The supported object types + */ + private $objectTypes; + + function CMISRepository($repositoryId, $config = null) + { + $this->repositoryId = $repositoryId; + $this->RepositoryInfo = new CMISRepositoryInfo(); + $this->getConfig($config); + } + + function getConfig($config = null) + { + // if not supplied config xml + if (is_null($config)) + { + // fetch configuration file + // TODO what if file does not exist? + $xml = simplexml_load_file(CMIS_DIR . '/config/repositories.xml'); + + foreach($xml->repository as $repository) + { + $currentRepo = $repository->repositoryInfo[0]->repositoryId; + if ((int)$currentRepo == $this->repositoryId) + { + $config = $repository; + break; + } + } + } + + // set URI + $this->repositoryURI = (string)$config->repositoryURI[0]; + + // set info + foreach($config->repositoryInfo[0] as $field => $value) + { + $this->setRepositoryInfoField($field, (string)$value); + } + + // set capabilities + foreach($config->repositoryCapabilities->children() as $field => $value) + { + $this->setCapabilityField($field, (string)$value); + } + + // set supported document types + foreach($config->supportedTypes->children() as $field => $value) + { + $this->objectTypes[] = (string)$value; + } + } + + /** + * Set a single value for RepositoryInfo + * + * @param string $field + * @param string/int $value + */ + function setRepositoryInfoField($field, $value) + { + $this->RepositoryInfo->setFieldValue($field, $value); + } + + /** + * Set multiple values for RepositoryInfo + * + * @param array $info + */ + function setRepositoryInfo($info) + { + $this->RepositoryInfo->setInfo($info); + } + + /** + * Set a single value for RepositoryCapabilities + * + * @param string $field + * @param string/int $value + */ + function setCapabilityField($field, $value) + { + $this->RepositoryInfo->setCapabilityValue($field, $value); + } + + function getRepositoryID() + { + return $this->RepositoryInfo->getRepositoryID(); + } + + function getRepositoryName() + { + return $this->RepositoryInfo->getRepositoryName(); + } + + function getRepositoryURI() + { + return $this->repositoryURI; + } + + function getRepositoryInfo() + { + return $this->RepositoryInfo; + } + + function getTypes() + { + return $this->objectTypes; + } + +// // TODO this function MUST accept the same arguments as the calling functions and respond accordingly +// // TODO consider moving this into the RepositoryService class: +// // anything which requires a repository id seems like it does not belong in the repository class +// function getTypes() +// { +// $objectTypes = $this->objectTypes->getObjectTypes(); +// +// // fetch the attributes for each type +// foreach ($objectTypes as $key => $objectType) +// { +// $objectTypes[$key] = $this->getTypeDefinition($this->repositoryId, $objectType); +// } +// +// return $objectTypes; +// } + +// // TODO consider moving this into the RepositoryService class: +// // anything which requires a repository id seems like it does not belong in the repository class +// function getTypeDefinition($repositoryId, $typeId) +// { +// // TODO is this the best way of doing this? +// switch ($typeId) +// { +// case 'Document': +// require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php'); +// $tmpObject = new DocumentObject(); +// $objectAttributes = $tmpObject->getProperties(); +// break; +// case 'Folder': +// require_once(CMIS_DIR . '/objecttypes/CMISFolderObject.inc.php'); +// $tmpObject = new FolderObject(); +// $objectAttributes = $tmpObject->getProperties(); +// break; +// } +// +// return $objectAttributes; +// } + +} + +?> diff --git a/ktcmis/classes/CMISRepositoryCapabilities.inc.php b/ktcmis/classes/CMISRepositoryCapabilities.inc.php new file mode 100644 index 0000000..75e685b --- /dev/null +++ b/ktcmis/classes/CMISRepositoryCapabilities.inc.php @@ -0,0 +1,289 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +class CMISRepositoryCapabilities { + + // boolean values + protected $capabilityMultifiling; + protected $capabilityUnfiling; + protected $capabilityVersionSpecificFiling; + protected $capabilityPWCUpdateable; + protected $capabilityPWCSearchable; + protected $capabilityAllVersionsSearchable; + + // non-boolean values + // TODO these should be defined as classes/enums which will only accept the defined values when set + protected $capabilityQuery; + protected $capabilityFullText; + protected $capabilityJoin; + + /** + * Set a single field value + * + * @param string $field + * @param string/int $value + * @return a collection of repository entries + */ + function setFieldValue($field, $value) + { + $this->{$field} = ($value == 'true' ? true : ($value == 'false' ? false : $value)); + } + + /** + * Gets the value of the capabilityMultifiling property. + * + */ + public function hasCapabilityMultifiling() { + return $this->capabilityMultifiling; + } + + /** + * Sets the value of the capabilityMultifiling property. + * + */ + public function setCapabilityMultifiling($value) { + $this->capabilityMultifiling = $value; + } + + /** + * Gets the value of the capabilityUnfiling property. + * + */ + public function hasCapabilityUnfiling() { + return $this->capabilityUnfiling; + } + + /** + * Sets the value of the capabilityUnfiling property. + * + */ + public function setCapabilityUnfiling($value) { + $this->capabilityUnfiling = $value; + } + + /** + * Gets the value of the capabilityVersionSpecificFiling property. + * + */ + public function hasCapabilityVersionSpecificFiling() { + return $this->capabilityVersionSpecificFiling; + } + + /** + * Sets the value of the capabilityVersionSpecificFiling property. + * + */ + public function setCapabilityVersionSpecificFiling($value) { + $this->capabilityVersionSpecificFiling = $value; + } + + /** + * Gets the value of the capabilityPWCUpdateable property. + * + */ + public function hasCapabilityPWCUpdateable() { + return $this->capabilityPWCUpdateable; + } + + /** + * Sets the value of the capabilityPWCUpdateable property. + * + */ + public function setCapabilityPWCUpdateable($value) { + $this->capabilityPWCUpdateable = $value; + } + + /** + * Gets the value of the capabilityPWCSearchable property. + * + */ + public function hasCapabilityPWCSearchable() { + return $this->capabilityPWCSearchable; + } + + /** + * Sets the value of the capabilityPWCSearchable property. + * + */ + public function setCapabilityPWCSearchable($value) { + $this->capabilityPWCSearchable = $value; + } + + /** + * Gets the value of the capabilityAllVersionsSearchable property. + * + */ + public function hasCapabilityAllVersionsSearchable() { + return $this->capabilityAllVersionsSearchable; + } + + /** + * Sets the value of the capabilityAllVersionsSearchable property. + * + */ + public function setCapabilityAllVersionsSearchable($value) { + $this->capabilityAllVersionsSearchable = $value; + } + + /** + * Gets the value of the capabilityQuery property. + * + * @return + * possible object is + * {@link EnumCapabilityQuery } + * + */ + public function getCapabilityQuery() { + return $this->capabilityQuery; + } + + /** + * Sets the value of the capabilityQuery property. + * + * @param value + * allowed object is + * {@link EnumCapabilityQuery } + * + */ + public function setCapabilityQuery($value) { + $this->capabilityQuery = $value; + } + + /** + * Gets the value of the capabilityJoin property. + * + * @return + * possible object is + * {@link EnumCapabilityJoin } + * + */ + public function getCapabilityJoin() { + return $this->capabilityJoin; + } + + /** + * Sets the value of the capabilityJoin property. + * + * @param value + * allowed object is + * {@link EnumCapabilityJoin } + * + */ + public function setCapabilityJoin($value) { + $this->capabilityJoin = $value; + } + + /** + * Gets the value of the capabilityFullText property. + * + * @return + * possible object is + * {@link EnumCapabilityFullText } + * + */ + public function getCapabilityFullText() { + return $this->capabilityFullText; + } + + /** + * Sets the value of the capabilityFullText property. + * + * @param value + * allowed object is + * {@link EnumCapabilityFullText } + * + */ + public function setCapabilityFullText($value) { + $this->capabilityFullText = $value; + } + +// /** +// * Gets the value of the any property. +// * +// *

+// * This accessor method returns a reference to the live list, +// * not a snapshot. Therefore any modification you make to the +// * returned list will be present inside the JAXB object. +// * This is why there is not a set method for the any property. +// * +// *

+// * For example, to add a new item, do as follows: +// *

+//     *    getAny().add(newItem);
+//     * 
+// * +// * +// *

+// * Objects of the following type(s) are allowed in the list +// * {@link Element } +// * +// * +// */ +// public List getAny() { +// if (any == null) { +// any = new ArrayList(); +// } +// return $this->any; +// } + +// /** +// * Gets a map that contains attributes that aren't bound to any typed property on this class. +// * +// *

+// * the map is keyed by the name of the attribute and +// * the value is the string value of the attribute. +// * +// * the map returned by this method is live, and you can add new attribute +// * by updating the map directly. Because of this design, there's no setter. +// * +// * +// * @return +// * always non-null +// */ +// public Map getOtherAttributes() { +// return $this->otherAttributes; +// } + +} + +?> diff --git a/ktcmis/classes/CMISRepositoryInfo.inc.php b/ktcmis/classes/CMISRepositoryInfo.inc.php new file mode 100644 index 0000000..69b665e --- /dev/null +++ b/ktcmis/classes/CMISRepositoryInfo.inc.php @@ -0,0 +1,169 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +require_once(CMIS_DIR . '/classes/CMISRepositoryCapabilities.inc.php'); + +/** + * CMIS Repository Service. + */ +class CMISRepositoryInfo { + + protected $repositoryId; // The identifier for the Repository + protected $repositoryName; // A display name for the Repository + protected $repositoryRelationship; // A string that MAY describe how this repository relates to other repositories. + protected $repositoryDescription; // A display description for the Repository. + protected $vendorName; // A display name for the vendor of the Repository’s underlying application. + protected $productName; // A display name for the Repository’s underlying application. + protected $productVersion; // A display name for the version number of the Repository’s underlying application. + protected $rootFolderId; // The ID of the Root Folder Object for the Repository. + + protected $capabilities; + + protected $cmisVersionsSupported; // String that indicates what versions of the CMIS specification the repository can support + protected $repositorySpecificInformation; // XML format; MAY be used by the Repository to return additional XML. + + function __construct() + { + $this->capabilities = new CMISRepositoryCapabilities(); + } + + /** + * Set a single field value + * + * @param string $field + * @param string/int $value + * @return a collection of repository entries + */ + function setFieldValue($field, $value) + { + $this->{$field} = $value; + } + + /** + * Set multiple field values + * + * @param array $info + */ + function setInfo($info) + { + foreach($info as $field => $value) + { + $this->setFieldValue($field, $value); + } + } + + /** + * Set a single capability field value + * + * @param string $field + * @param string/int $value + * @return a collection of repository entries + */ + function setCapabilityValue($field, $value) + { + $this->capabilities->setFieldValue($field, $value); + } + + /** + * Sets the capabilities from an existing capabilities object + * + * @param object $capabilities + */ + function setCapabilities($capabilities) + { + $this->capabilities = $capabilities; + } + + function getRepositoryId() + { + return $this->repositoryId; + } + + function getRepositoryName() + { + return $this->repositoryName; + } + + function getCapabilities() + { + return $this->capabilities; + } + + function getRepositoryRelationship() + { + return $this->repositoryRelationship; + } + + function getRepositoryDescription() + { + return $this->repositoryDescription; + } + + function getVendorName() + { + return $this->vendorName; + } + + function getProductName() + { + return $this->productName; + } + + function getProductVersion() + { + return $this->productVersion; + } + + function getRootFolderId() + { + return $this->rootFolderId; + } + + function getcmisVersionsSupported() + { + return $this->cmisVersionsSupported; + } + +} + +?> diff --git a/ktcmis/config/repositories.xml b/ktcmis/config/repositories.xml new file mode 100644 index 0000000..6119698 --- /dev/null +++ b/ktcmis/config/repositories.xml @@ -0,0 +1,70 @@ + + + + + + + http://127.0.0.1/ + + 1 + KnowledgeTree + self + KnowledgeTree Repository + KnowledgeTree + KnowledgeTree + 3.6.2 + 1 + cmis 0.61c + + + false + false + false + false + false + false + None + None + NoJoin + + + Document + Folder + + + + http://12s7.w0.0.1/ + + 44 + asdasdasd + self + KnowledgeTree Repository + KnowledgeTree + KnowledgeTree + 3.6.1 + 1 + 0.61 + + + false + false + false + false + false + false + None + None + NoJoin + + + Document + Folder + + + diff --git a/ktcmis/ktcmis.inc.php b/ktcmis/ktcmis.inc.php new file mode 100644 index 0000000..7025dc3 --- /dev/null +++ b/ktcmis/ktcmis.inc.php @@ -0,0 +1,459 @@ +. +* +* 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. +* +* @copyright 2008-2009, KnowledgeTree Inc. +* @license GNU General Public License version 3 +* @author KnowledgeTree Team +* @package KTCMIS +* @version Version 0.9 +*/ + +// TODO implement exceptions in various calls (in the underlying classes) +// FIXME none of the error handling actually does anything, it's leftover from copy/paste of some ktapi code + +require_once(realpath(dirname(__FILE__) . '/../config/dmsDefaults.php')); +require_once(KT_DIR . '/ktapi/ktapi.inc.php'); + +define ('CMIS_DIR', KT_DIR . '/ktcmis'); +require_once(CMIS_DIR . '/services/CMISRepositoryService.inc.php'); +require_once(CMIS_DIR . '/services/CMISNavigationService.inc.php'); +require_once(CMIS_DIR . '/services/CMISObjectService.inc.php'); +require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); + +class KTCMIS { + + /** + * Class for CMIS Repository Services + * + * @var object + */ + protected $RepositoryService; + /** + * Class for CMIS Navigation Services + * + * @var object + */ + protected $NavigationService; + /** + * Class for CMIS Object Services + * + * @var object + */ + protected $ObjectService; + /** + * KnowledgeTree API instance + * + * @var object + */ + protected $ktapi; + /** + * KnowledgeTree API Session Identifier + * + * @var object + */ + protected $session; + + function __construct(&$ktapi = null, $user = '', $password = '') + { + // ktapi interface + $this->session = null; +// if (is_null($ktapi)) +// { +// // TODO this should probably throw an exception instead +// return PEAR::RaiseError('Cannot continue without KTAPI instance'); + // FIXME this CANNOT be allowed in a live environment + // possibly we should insist on a ktapi instance being passed + // or at least user/pass for logging in here, if one or other + // not sent, return error + $user = 'admin'; + $password = 'admin'; + $this->ktapi = new KTAPI(); + $this->session = $this->ktapi->start_session($user, $password); +// } +// else +// { +// $this->ktapi = $ktapi; +// } + + // instantiate services + $this->RepositoryService = new CMISRepositoryService(); + $this->NavigationService = new CMISNavigationService($this->ktapi); + $this->ObjectService = new CMISObjectService($this->ktapi); + } + + function __destruct() + { +// if ($this->session instanceOf KTAPI_UserSession) +// { +// try +// { +// $this->session->logout(); +// } +// catch (Exception $e) +// { +// // no output +// } +// } + } + + // Repository service functions + + /** + * Fetch a list of all available repositories + * + * NOTE Since we only have one repository at the moment, this is expected to only return one result + * + * @return repositoryList[] + */ + function getRepositories() + { + $repositories = $this->RepositoryService->getRepositories(); + if (PEAR::isError($repositories)) + { + return array( + "status_code" => 1, + "message" => "Failed getting repositories" + ); + } + + // extract the required info fields into array format for easy encoding; + $count = 0; + $repositoryList = array(); + foreach ($repositories as $repository) + { + $repositoryList[$count]['repositoryId'] = $repository->getRepositoryId(); + $repositoryList[$count]['repositoryName'] = $repository->getRepositoryName(); + $repositoryList[$count]['repositoryURI'] = $repository->getRepositoryURI(); + ++$count; + } + + return array( + "status_code" => 0, + "results" => $repositoryList + ); + } + + /** + * Fetches information about the selected repository + * + * @param string $repositoryId + */ + function getRepositoryInfo($repositoryId) + { + $repositoryInfo = $this->RepositoryService->getRepositoryInfo($repositoryId); + if (PEAR::isError($repositoryInfo)) + { + return array( + "status_code" => 1, + "message" => "Failed getting repository information" + ); + } + + // TODO output this manually, the function works but only for some objects so rather avoid it completely + // NOTE the fact that it works for this instance is irrelevant... + return array ( + "status_code" => 0, + "results" => CMISUtil::objectToArray($repositoryInfo) + ); + } + + /** + * Fetch the list of supported object types for the selected repository + * + * @param string $repositoryId + */ + function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, + $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) + { + $repositoryObjectTypeResult = $this->RepositoryService->getTypes($repositoryId, $typeId, $returnPropertyDefinitions, + $maxItems, $skipCount, $hasMoreItems); + if (PEAR::isError($repositoryObjectTypeResult)) + { + return array( + "status_code" => 1, + "message" => "Failed getting supported object types" + ); + } + + // format as array style output + // NOTE only concerned with attributes at this time + // TODO add support for properties + foreach($repositoryObjectTypeResult as $key => $objectType) + { + $repositoryObjectTypes[$key] = $objectType['attributes']; + // TODO properties + // $repositoryObjectTypes[$key]['properties'] = $objectType['properties']; + } + + return array ( + "status_code" => 0, + "results" => $repositoryObjectTypes + ); + } + + /** + * Fetch the object type definition for the requested type + * + * @param string $repositoryId + * @param string $typeId + */ + function getTypeDefinition($repositoryId, $typeId) + { + $typeDefinitionResult = $this->RepositoryService->getTypeDefinition($repositoryId, $typeId); + + if (PEAR::isError($typeDefinitionResult)) + { + return array( + "status_code" => 1, + "message" => "Failed getting object type definition for $typeId" + ); + } + + // format as array style output + // NOTE only concerned with attributes at this time + // TODO add support for properties + $typeDefinition = $typeDefinitionResult['attributes']; + + return array ( + "status_code" => 0, + "results" => $typeDefinition + ); + } + + // Navigation service functions + + /** + * Get descendents of the specified folder, up to the depth indicated + * + * @param string $repositoryId + * @param string $folderId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param string $typeID + * @param int $depth + * @param string $filter + * @return array $descendants + */ + function getDescendants($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, + $depth = 1, $typeID = 'Any', $filter = '') + { + // TODO optional parameters + $descendantsResult = $this->NavigationService->getDescendants($repositoryId, $folderId, $includeAllowableActions, + $includeRelationships, $depth); + + if (PEAR::isError($descendantsResult)) + { + return array( + "status_code" => 1, + "message" => "Failed getting descendants for folder" + ); + } + + // format for webservices consumption + // NOTE this will almost definitely be changing in the future, this is just to get something working + $descendants = CMISUtil::decodeObjectHierarchy($descendantsResult, 'child'); +// $descendants = array(array('properties' => array('objectId' => 'D2', 'typeId' => 'Document', 'name' => 'test document'), +// 'child' => array(array('properties' => array('objectId' => 'D7', +// 'typeId' => 'Document', 'name' => 'CHILD document'), 'child' => null), +// array('properties' => array('objectId' => 'F34', +// 'typeId' => 'Folder', 'name' => 'CHILD FOLDER'), 'child' => null)))); + + return array ( + "status_code" => 0, + "results" => $descendants + ); + } + + /** + * Get direct children of the specified folder + * + * @param string $repositoryId + * @param string $folderId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param string $typeID + * @param string $filter + * @param int $maxItems + * @param int $skipCount + * @return array $descendants + */ + function getChildren($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, + $typeID = 'Any', $filter = '', $maxItems = 0, $skipCount = 0) + { + // TODO paging + // TODO optional parameters + $childrenResult = $this->NavigationService->getChildren($repositoryId, $folderId, $includeAllowableActions, $includeRelationships); + + if (PEAR::isError($childrenResult)) + { + return array( + "status_code" => 1, + "message" => "Failed getting descendants for folder" + ); + } + + $children = CMISUtil::decodeObjectHierarchy($childrenResult, 'child'); +// $children = array(array('properties' => array('objectId' => 'D2', 'typeId' => 'Document', 'name' => 'test document'), +// 'child' => null)); + + return array( + "status_code" => 0, + "results" => $children + ); + } + + /** + * Gets the parent of the selected folder + * + * @param string $repositoryId + * @param string $folderId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param bool $returnToRoot + * @param string $filter + * @return ancestry[] + */ + function getFolderParent($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, $returnToRoot, $filter = '') + { + $ancestryResult = $this->NavigationService->getFolderParent($repositoryId, $folderId, $includeAllowableActions, + $includeRelationships, $returnToRoot); + + if (PEAR::isError($ancestryResult)) + { + return array( + "status_code" => 1, + "message" => "Failed getting ancestry for folder" + ); + } + + $ancestry = CMISUtil::decodeObjectHierarchy($ancestryResult, 'child'); +// $ancestry = array(array('properties' => array('objectId' => 'D2', 'typeId' => 'Document', 'name' => 'test document'), +// 'child' => null)); + + return array( + "status_code" => 0, + "results" => $ancestry + ); + } + + /** + * Gets the parents for the selected object + * + * @param string $repositoryId + * @param string $folderId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param string $filter + * @return ancestry[] + */ + function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') + { + $ancestryResult = $this->NavigationService->getObjectParents($repositoryId, $objectId, $includeAllowableActions, + $includeRelationships); + + if (PEAR::isError($ancestryResult)) + { + return array( + "status_code" => 1, + "message" => "Failed getting ancestry for object" + ); + } + + $ancestry = CMISUtil::decodeObjectHierarchy($ancestryResult, 'child'); +// $ancestry = array(array('properties' => array('objectId' => 'D2', 'typeId' => 'Document', 'name' => 'test document'), +// 'child' => null)); + +// $ancestry = array(array('properties' => array(array('property' => array('name' => 'objectId', $value => 'D2')), +// array('property' => array('name' => 'typeId', $value => 'Document')), +// array('property' => array('name' => 'name', $value => 'test document')))), +// 'child' => null); + + return array( + "status_code" => 0, + "results" => $ancestry + ); + } + + /** + * Gets the properties for the selected object + * + * @param string $repositoryId + * @param string $objectId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param string $returnVersion + * @param string $filter + * @return properties[] + */ + function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, + $returnVersion = false, $filter = '') + { + $propertiesResult = $this->ObjectService->getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships); + + if (PEAR::isError($propertiesResult)) + { + return array( + "status_code" => 1, + "message" => "Failed getting properties for object" + ); + } +// echo '

'.print_r($propertiesResult, true).'
'; + // will need to convert to array format, so: + $propertyCollection['objectId'] = $propertiesResult->getValue('objectId'); + $propertyCollection['URI'] = $propertiesResult->getValue('URI'); + $propertyCollection['typeId'] = $propertiesResult->getValue('typeId'); + $propertyCollection['createdBy'] = $propertiesResult->getValue('createdBy'); + $propertyCollection['creationDate'] = $propertiesResult->getValue('creationDate'); + $propertyCollection['lastModifiedBy'] = $propertiesResult->getValue('lastModifiedBy'); + $propertyCollection['lastModificationDate'] = $propertiesResult->getValue('lastModificationDate'); + $propertyCollection['changeToken'] = $propertiesResult->getValue('changeToken'); + + $properties = array(array('properties' => $propertyCollection, 'child' => null)); +// echo '
'.print_r($properties, true).'
'; +// +// $properties = array(array('properties' => array('objectId' => 'F2', 'URI' => '', 'typeId' => 'Document', +// 'createdBy' => 'Administrator', 'creationDate' => '1 June 2009', +// 'lastModifiedBy' => 'Administrator', 'lastModificationDate' => '1 June 2009', +// 'changeToken' => ''), +// 'child' => null)); + + return array( + "status_code" => 0, + "results" => $properties + ); + } +} + +?> diff --git a/ktcmis/objecttypes/CMISDocumentObject.inc.php b/ktcmis/objecttypes/CMISDocumentObject.inc.php new file mode 100644 index 0000000..3dca392 --- /dev/null +++ b/ktcmis/objecttypes/CMISDocumentObject.inc.php @@ -0,0 +1,170 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +require_once(CMIS_DIR . '/classes/CMISBaseObject.inc.php'); +require_once(CMIS_DIR . '/classes/CMISDocumentPropertyCollection.inc.php'); +require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); + +// TODO Property Type Definitions (only done Attributes up to now) + +class CMISDocumentObject extends CMISBaseObject { + + private $versionable; + private $contentStreamAllowed; + private $ktapi; + private $uri; + + // TODO some of this should probably come from configuration files as it is repository specific + function CMISDocumentObject(&$ktapi = null, $uri = null) + { + $this->ktapi = $ktapi; + // uri to use for document links + $this->uri = $uri; + + // attributes + $this->typeId = 'Document'; // + $this->queryName = 'Document'; + $this->displayName = ''; // + $this->baseType = 'document'; + $this->baseTypeQueryName = 'Document'; + $this->parentId = null; // MUST NOT be set + $this->description = ''; // + $this->creatable = ''; // + /* + * fileable SHOULD be set as follows: + * If the repository does NOT support the “un-filing” capability: + * TRUE + * If the repository does support the “un-filing” capability: + * , but SHOULD be TRUE + */ + $this->fileable = true; // TODO implement check for whether un-filing is supported + $this->queryable = true; // SHOULD be true + $this->includedInSupertypeQuery = true; // + // TODO determine what these next 3 should be + $this->controllable = false; // + $this->versionable = false; // + $this->contentStreamAllowed = false; // + + // properties + $this->properties = new CMISDocumentPropertyCollection(); + + // set base object property definitions +// parent::__construct(); + + // set document specific property definitions + + } + + function get($objectId) + { + $object = $this->ktapi->get_document_by_id($objectId); + + // error? + if (PEAR::isError($object)) + { + // throw an exception? + return $object; + } + + $objectProperties = $object->get_detail(); + + $this->_setPropertyInternal('objectId', CMISUtil::encodeObjectId($this->typeId, $objectProperties['document_id'])); + // prevent doubled '/' chars + $uri = preg_replace_callback('/([^:]\/)\//', + create_function('$matches', 'return $matches[1];'), + $this->uri + . 'action.php?kt_path_info=ktnetwork.inlineview.actions.view&fDocumentId=' + . $objectProperties['document_id']); + // NOTE what about instead creating a downloadable version with appropriate link? see ktapi::download_document + // also ktapidocument::get_download_url + $this->_setPropertyInternal('Uri', $uri); + // TODO what is this? Assuming it is the object type id, and not OUR document type? + $this->_setPropertyInternal('typeId', $this->getAttribute('typeId')); + $this->_setPropertyInternal('createdBy', $objectProperties['created_by']); + $this->_setPropertyInternal('creationDate', $objectProperties['created_date']); + $this->_setPropertyInternal('lastModifiedBy', $objectProperties['modified_by']); + $this->_setPropertyInternal('lastModificationDate', $objectProperties['modified_date']); + $this->_setPropertyInternal('changeToken', null); + $this->_setPropertyInternal('name', $objectProperties['title']); + $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 + // NOTE see ktapi::is_latest_version + $this->_setPropertyInternal('isLatestVersion', true); + $this->_setPropertyInternal('isMajorVersion', (strstr($objectProperties['version'], '.') ? false : true)); + // 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 + // NOTE see ktapi::is_latest_version + $this->_setPropertyInternal('isLatestMajorVersion', true); + $this->_setPropertyInternal('versionLabel', $objectProperties['version']); + // TODO what determines this, do we have anything? + $this->_setPropertyInternal('versionSeriesId', null); + if ($objectProperties['checked_out_by'] != 'n/a') + { + $checkedOut = true; + $checkedOutBy = $objectProperties['checked_out_by']; + // TODO this is not what it will actually be, just a convenient placeholder + $checkedOutId = $objectProperties['version']; + } + else + { + $checkedOut = false; + $checkedOutBy = null; + $checkedOutId = null; + } + $this->_setPropertyInternal('isVersionSeriesCheckedOut', $checkedOut); + $this->_setPropertyInternal('versionSeriesCheckedOutBy', $checkedOutBy); + // TODO presumably this is the ID of the Private Working Copy created on checkout? + // will find out more when we do checkout/checkin + $this->_setPropertyInternal('versionSeriesCheckedOutId', $checkedOutId); + // TODO currently not returned by KnowledgeTree? + $this->_setPropertyInternal('checkinComment', null); + // TODO if we implement content streams + $this->_setPropertyInternal('contentStreamLength', null); + $this->_setPropertyInternal('contentStreamMimeType', null); + $this->_setPropertyInternal('contentStreamFilename', null); + $this->_setPropertyInternal('contentStreamUri', null); + } + +} + +?> diff --git a/ktcmis/objecttypes/CMISFolderObject.inc.php b/ktcmis/objecttypes/CMISFolderObject.inc.php new file mode 100644 index 0000000..4acc778 --- /dev/null +++ b/ktcmis/objecttypes/CMISFolderObject.inc.php @@ -0,0 +1,115 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +require_once(CMIS_DIR . '/classes/CMISBaseObject.inc.php'); +require_once(CMIS_DIR . '/classes/CMISFolderPropertyCollection.inc.php'); +require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); + +class CMISFolderObject extends CMISBaseObject { + + var $ktapi; + var $uri; + + function CMISFolderObject(&$ktapi = null, $uri = null) + { + $this->ktapi = $ktapi; + $this->uri = $uri; + + $this->typeId = 'Folder'; // + $this->queryName = 'Folder'; + $this->displayName = ''; // + $this->baseType = 'folder'; + $this->baseTypeQueryName = 'Folder'; + $this->parentId = null; // MUST NOT be set + $this->description = ''; // + $this->creatable = ''; // + $this->fileable = true; + $this->queryable = true; // SHOULD be true + $this->includedInSupertypeQuery = true; // + $this->controllable = ''; // + + // properties + $this->properties = new CMISFolderPropertyCollection(); + } + + function get($objectId) + { + $object = $this->ktapi->get_folder_by_id($objectId); + + // error? + if (PEAR::isError($object)) + { + // throw an exception? + return $object; + } + +// static $allowedChildObjectTypeIds; + + $objectProperties = $object->get_detail(); + + $this->_setPropertyInternal('objectId', CMISUtil::encodeObjectId($this->typeId, $objectProperties['id'])); + // prevent doubled '/' chars + $uri = preg_replace_callback('/([^:]\/)\//', + create_function('$matches', 'return $matches[1];'), + $this->uri + . '/browse.php?fFolderId=' + . $objectProperties['id']); + // TODO this url is probably incorrect...needs to be checked + $this->_setPropertyInternal('Uri', $uri); + // TODO what is this? Assuming it is the object type id, and not OUR document type? + $this->_setPropertyInternal('typeId', $this->getAttribute('typeId')); + $this->_setPropertyInternal('createdBy', $objectProperties['created_by']); + // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by + $this->_setPropertyInternal('creationDate', $objectProperties['created_date']); + // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by + $this->_setPropertyInternal('lastModifiedBy', $objectProperties['modified_by']); + // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by + $this->_setPropertyInternal('lastModificationDate', $objectProperties['modified_date']); + $this->_setPropertyInternal('changeToken', null); + $this->_setPropertyInternal('name', $objectProperties['folder_name']); + $this->_setPropertyInternal('parentId', $objectProperties['parent_id']); + $this->_setPropertyInternal('allowedChildObjectTypeIds', array('Document', 'Folder')); + } + +} + +?> diff --git a/ktcmis/services/CMISNavigationService.inc.php b/ktcmis/services/CMISNavigationService.inc.php new file mode 100644 index 0000000..a64dbf5 --- /dev/null +++ b/ktcmis/services/CMISNavigationService.inc.php @@ -0,0 +1,255 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +// really wanted to keep KT code out of here but I don't see how +require_once(KT_DIR . '/ktapi/ktapi.inc.php'); +require_once(CMIS_DIR . '/util/CMISUtil.inc.php'); + +class CMISNavigationService { + + protected $ktapi; + + function CMISNavigationService(&$ktapi) + { + $this->ktapi = $ktapi; + } + + /** + * Get descendents of the specified folder, up to the depth indicated + * + * @param string $repositoryId + * @param string $folderId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param string $typeId + * @param int $depth + * @param string $filter + * @return array $descendants + */ + + // NOTE This method does NOT support paging as defined in the paging section + // NOTE If the Repository supports the optional “VersionSpecificFiling” capability, + // then the repository SHALL return the document versions filed in the specified folder or its descendant folders. + // Otherwise, the latest version of the documents SHALL be returned. + + // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid + function getDescendants($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, + $depth = 1, $typeId = 'Any', $filter = '') + { + // TODO optional parameters + $descendants = array(); + $repository = new CMISRepository($repositoryId); + + // if this is not a folder, cannot get descendants + $type = CMISUtil::decodeObjectId($folderId); + + if ($type != 'Folder') + { + return $descendants; + } + + $folder = $this->ktapi->get_folder_by_id($folderId); + $descendants = $folder->get_listing($depth); + + // parse ktapi descendants result into a list of CMIS objects + $descendants = CMISUtil::createChildObjectHierarchy($descendants, $repository->getRepositoryURI, $this->ktapi); + + return $descendants; + } + + /** + * Get direct children of the specified folder + * + * @param string $repositoryId + * @param string $folderId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param string $typeId + * @param string $filter + * @param int $maxItems + * @param int $skipCount + * @return array $descendants + */ + // NOTE If the Repository supports the optional “VersionSpecificFiling” capability, + // then the repository SHALL return the document versions filed in the specified folder or its descendant folders. + // Otherwise, the latest version of the documents SHALL be returned. + // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid + function getChildren($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, + $typeId = 'Any', $filter = '', $maxItems = 0, $skipCount = 0) + { + // TODO paging + // TODO optional parameters + $children = array(); + $repository = new CMISRepository($repositoryId); + + // if this is not a folder, cannot get children + $type = CMISUtil::decodeObjectId($folderId); + // NOTE this will quite possibly break the webservices + if ($type != 'Folder') + { + return $children; + } + + $folder = $this->ktapi->get_folder_by_id($folderId); + $children = $folder->get_listing(); + + $children = CMISUtil::createChildObjectHierarchy($children, $repository->getRepositoryURI, $this->ktapi); + + return $children; + } + + /** + * Fetches the folder parent and optional ancestors + * + * @param string $repositoryId + * @param string $folderId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param bool $returnToRoot If TRUE, then the repository SHALL return all folder objects + * that are ancestors of the specified folder. + * If FALSE, the repository SHALL return only the parent folder of the specified folder. + * @param string $filter + * @return array $ancestry + */ + // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid + // NOTE SHOULD always include the “ObjectId” and “ParentId” properties for all objects returned + // NOTE If this service method is invoked on the root folder of the Repository, then the Repository shall return an empty result set. + function getFolderParent($repositoryId, $folderId, $includeAllowableActions, $includeRelationships, $returnToRoot, $filter = '') + { + $ancestry = array(); + $repository = new CMISRepository($repositoryId); + + // if this is not a folder, cannot get folder parent :) + $type = CMISUtil::decodeObjectId($folderId); + // NOTE this will quite possibly break the webservices + if ($type != 'Folder') + { + return $ancestry; + } + + $ktapiFolder = $this->ktapi->get_folder_by_id($folderId); + + // TODO return full ancestry on $returnToRoot == true + if ($returnToRoot) + { + $folder = $ktapiFolder->get_folder(); + $parents = $folder->generateFolderIDs($folderId); + // remove the id of the requesting folder and convert to array + $ancestry = explode(',', str_replace(','.$folderId, '', $parents)); + // reverse to get bottom up listing? don't think so with the current implementation + // specifying that objectTypes may have children but do not have parents listed. +// $ancestry = array_reverse($ancestry); + } + else + { + $parent = $ktapiFolder->get_parent_folder_id(); + $ancestry[] = $parent; + } + + // need some info about the parent(s) in order to correctly create the hierarchy + $tmpArray = array(); + foreach ($ancestry as $key => $ancestor) + { + $tmpArray[$key] = $this->ktapi->get_folder_by_id($ancestor); + } + $ancestry = $tmpArray; + unset($tmpArray); + + $ancestry = CMISUtil::createParentObjectHierarchy($ancestry, $repository->getRepositoryURI, $this->ktapi); + + return $ancestry; + } + + /** + * + * @param string $repositoryId + * @param string $objectId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param string $filter + * @return array $parents + */ + // TODO ConstraintViolationException: The Repository SHALL throw this exception if this method is invoked + // on an object who Object-Type Defintion specifies that it is not fileable. + // FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid. + function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '') + { + $ancestry = array(); + + $typeId = CMISUtil::decodeObjectId($objectId); + + // TODO - what about other types? only implementing folders and documents at the moment so ignore for now + switch($typeId) + { + case 'Document': + $document = $this->ktapi->get_document_by_id($objectId); + $parent = $document->ktapi_folder; + $ancestry[] = $parent; + break; + case 'Folder': + $folder = $this->ktapi->get_folder_by_id($objectId); + $parent = $this->ktapi->get_folder_by_id($folder->get_parent_folder_id()); + $ancestry[] = $parent; + break; + } + +// echo 'PARENT
'.print_r($parent, true).'
'; +// +//echo '
'.print_r($ancestry, true).'
'; +// // need some info about the parent(s) in order to correctly create the hierarchy +// $tmpArray = array(); +// foreach ($ancestry as $key => $ancestor) +// { +// echo '
'.print_r($ancestor, true).'
'; +// $tmpArray[$key] = $this->ktapi->get_folder_by_id($ancestor); +// } +// $ancestry = $tmpArray; +// unset($tmpArray); + + $ancestry = CMISUtil::createParentObjectHierarchy($ancestry, $repository->getRepositoryURI, $this->ktapi); + + return $ancestry; + } + +} + +?> diff --git a/ktcmis/services/CMISObjectService.inc.php b/ktcmis/services/CMISObjectService.inc.php new file mode 100644 index 0000000..bd12a30 --- /dev/null +++ b/ktcmis/services/CMISObjectService.inc.php @@ -0,0 +1,60 @@ +ktapi = $ktapi; + } + + /** + * Fetches the properties for the specified object + * + * @param string $repositoryId + * @param string $objectId + * @param bool $includeAllowableActions + * @param bool $includeRelationships + * @param bool $returnVersion + * @param string $filter + * @return object CMIS object properties + */ + // TODO optional parameter support + // TODO FilterNotValidException: The Repository SHALL throw this exception if this property filter input parameter is not valid + function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, + $returnVersion = false, $filter = '') + { + $repository = new CMISRepository($repositoryId); + + // TODO a better default value? + $properties = array(); + + $typeId = CMISUtil::decodeObjectId($objectId); + + switch($typeId) + { + case 'Document': + $CMISObject = new CMISDocumentObject($this->ktapi, $repository->getRepositoryURI()); + break; + case 'Folder': + $CMISObject = new CMISFolderObject($this->ktapi, $repository->getRepositoryURI()); + break; + } + + $CMISObject->get($objectId); + $properties = $CMISObject->getProperties(); + + return $properties; + } + +} + +?> diff --git a/ktcmis/services/CMISRepositoryService.inc.php b/ktcmis/services/CMISRepositoryService.inc.php new file mode 100644 index 0000000..adfb54f --- /dev/null +++ b/ktcmis/services/CMISRepositoryService.inc.php @@ -0,0 +1,158 @@ +. +* +* 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. +* +* @copyright 2008-2009, KnowledgeTree Inc. +* @license GNU General Public License version 3 +* @author KnowledgeTree Team +* @package KTCMIS +* @version Version 0.1 +*/ + +require_once(CMIS_DIR . '/classes/CMISRepository.inc.php'); +require_once(CMIS_DIR . '/classes/CMISObjectTypes.inc.php'); + +/** + * CMIS Repository Service. + */ +class CMISRepositoryService { + + /** + * Gets a list of available repositories. + * + * @return a collection of repository entries + */ + function getRepositories() + { + $repositories = array(); + + // read the repositories config file to get the list of available repositories + // TODO what if file does not exist? + $xml = simplexml_load_file(CMIS_DIR . '/config/repositories.xml'); + + foreach($xml->repository as $repositoryXML) + { + $repositoryId = (string)$repositoryXML->repositoryInfo[0]->repositoryId; + $Repository = new CMISRepository($repositoryId, $repositoryXML); + $repositories[] = $Repository; + } + + return $repositories; + } + + /** + * Fetches the RepositoryInfo object for a specified repository + * + * @param string $repositoryId + * @return object $repositoryInfo + */ + function getRepositoryInfo($repositoryId) + { + $Repository = new CMISRepository($repositoryId); + $repositoryInfo = $Repository->getRepositoryInfo(); + + return $repositoryInfo; + } + + /** + * Gets a list of object types supported by the repository + * + * @param string $repositoryId The ID of the repository for which object types must be returned + * @param string $typeId The type to return, ALL if not set + * @param boolean $returnPropertyDefinitions Return property definitions as well if TRUE + * @param int $maxItems The maximum number of items to return + * @param int $skipCount The number of items to skip before starting to return results + * @param boolean $hasMoreItems TRUE if there are more items to return than were requested + * @return array $objectTypes + */ + // NOTE this code may fit better within the Repository Class + function getTypes($repositoryId, $typeId = '', $returnPropertyDefinitions = false, + $maxItems = 0, $skipCount = 0, &$hasMoreItems = false) + { + // TODO throw invalidArgumentException if invalid typeId submitted + + $repository = new CMISRepository($repositoryId); + $supportedTypes = $repository->getTypes(); + + $types = array(); + + // determine which types are actually supported based on available class definitions + // compared with the repository's declaration of the types it supports + $objectTypes = new CMISObjectTypes(); + $types = $objectTypes->getObjectTypes(); + + foreach ($types as $key => $objectType) + { + // filter this list according to what is defined for the selected repository + // additionally filter based on typeId if set + if (!in_array($objectType, $supportedTypes) || (($typeId != '') && ($typeId != $objectType))) + { + unset($types[$key]); + continue; + } + $types[$key] = $this->getTypeDefinition($repositoryId, $objectType); + // only return properties if explicitly requested + if (!$returnPropertyDefinitions) + { + unset($types[$key]['properties']); + } + } + + return $types; + } + + /** + * Fetches the object type definition for the requested type + * + * @param string $repositoryId The ID of the repository + * @param string $typeId The ID of the object type requested + * @return $array $typeDefinition + */ + function getTypeDefinition($repositoryId, $typeId) + { + $typeDefinition = array(); + + require_once(CMIS_DIR . '/objecttypes/CMIS' . $typeId . 'Object.inc.php'); + $object = 'CMIS' . $typeId . 'Object'; + $tmpObject = new $object; + $typeDefinition['attributes'] = $tmpObject->getAttributes(); + $typeDefinition['properties'] = $tmpObject->getProperties(); + + return $typeDefinition; + } + +} + +?> \ No newline at end of file diff --git a/ktcmis/util/CMISUtil.inc.php b/ktcmis/util/CMISUtil.inc.php new file mode 100644 index 0000000..c534250 --- /dev/null +++ b/ktcmis/util/CMISUtil.inc.php @@ -0,0 +1,277 @@ +. + * + * 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. + * + * @copyright 2008-2009, KnowledgeTree Inc. + * @license GNU General Public License version 3 + * @author KnowledgeTree Team + * @package KTCMIS + * @version Version 0.1 + */ + +require_once(CMIS_DIR . '/objecttypes/CMISDocumentObject.inc.php'); +require_once(CMIS_DIR . '/objecttypes/CMISFolderObject.inc.php'); + +class CMISUtil { + + /** + * Adds a text identifier to the object ID in order to easily + * verify which object type we are working with on a return request + * + * @param string $typeId + * @param string $objectId + * @return string $encoded + */ + static function encodeObjectId($typeId, $objectId) + { + $encoded = null; + + switch ($typeId) + { + case 'D': + case 'Document': + $encoded = 'D' . $objectId; + break; + case 'F': + case 'Folder': + $encoded = 'F' . $objectId; + break; + default: + $encoded = $objectId; + break; + } + + return $encoded; + } + + /** + * Decodes the identifier created by encodeObjectId to return an object type + * and a system useable ID + * + * The decoded object ID is returned by reference via the argument list + * + * @param string $objectId + * @return string $typeId + */ + static function decodeObjectId(&$objectId) + { + $typeId = null; + + preg_match('/(\D)(\d*)/', $objectId, $matches); + $type = $matches[1]; + $objectId = $matches[2]; + + switch($type) + { + case 'D': + $typeId = 'Document'; + break; + case 'F': + $typeId = 'Folder'; + break; + default: + $typeId = 'Unknown'; + break; + } + + return $typeId; + } + + /** + * Takes an array of KnowledgeTree KTAPI objects and returns an array of CMIS objects of the same type + * + * Utilises the descending structure already present within KTAPI + * + * @param array $input + * @param string $repositoryURI + * @param object $ktapi // reference to ktapi instance + * @return array $CMISArray + */ + static function createChildObjectHierarchy($input, $repositoryURI, &$ktapi) + { + $CMISArray = array(); + + $count = -1; + foreach($input as $object) + { + ++$count; + if (is_array($object)) + { + if (isset($object['id'])) + { + switch($object['item_type']) + { + case 'D': + $CMISObject = new CMISDocumentObject($ktapi, $repositoryURI); + break; + case 'F': + $CMISObject = new CMISFolderObject($ktapi, $repositoryURI); + break; + } + $CMISObject->get($object['id']); + $CMISArray[$count]['object'] = $CMISObject; + + // if sub-array + if (count($object['items']) > 0) + { + $CMISArray[$count]['items'] = CMISUtil::createChildObjectHierarchy($object['items'], $repositoryURI, $ktapi); + } + } + else + { + // NOTE why is this necessary? That's what you get for not commenting it at the time + // TODO comment this properly + $CMISArray[$count] = CMISUtil::createChildObjectHierarchy($object, $repositoryURI, $ktapi); + } + } + } + + return $CMISArray; + } + + /** + * Takes an array of KnowledgeTree KTAPI objects and returns an array of CMIS objects of the same type + * + * As there is no corresponding hierarchy setup for parent trees, this works differently to the child + * hirerarchy function + * + * @param array $input + * @param string $repositoryURI + * @param object $ktapi // reference to ktapi instance + * @return array $CMISArray + */ + // NOTE this will have to change if we implement multi-filing + static function createParentObjectHierarchy($input, $repositoryURI, &$ktapi) + { + $CMISArray = array(); + + if (count($input) <= 0) return $CMISArray; + + $object = array_shift($input); + $detail = $object->get_detail(); + + if (isset($detail['id'])) + { + $CMISObject = new CMISFolderObject($ktapi, $repositoryURI); + $CMISObject->get($detail['id']); + $CMISElement['object'] = $CMISObject; + + // if more parent elements + if (count($input) > 0) + { + $CMISElement['items'] = CMISUtil::createParentObjectHierarchy($input, $repositoryURI, $ktapi); + } + + $CMISArray[] = $CMISElement; + } + + return $CMISArray; + } + + /** + * Parses a hierarchy of CMIS objects to return an array format of a subset of information + * required for a webservice response + * + * Essentially a reversal of createChildObjectHierarchy and createParentObjectHierarchy, + * though the output may well be different to what went into that function + * + * @param array $input // input hierarchy to decode + * @param string $linkText // 'child' or 'parent' - indicates direction of hierarchy => descending or ascending + * @return array $hierarchy + */ + static function decodeObjectHierarchy($input, $linkText) + { + $hierarchy = array(); + + // first, run through the base array to get the initial children + foreach ($input as $key => $entry) + { + $object = $entry['object']; + $properties = $object->getProperties(); + + $hierarchy[$key]['properties']['objectId'] = $properties->getValue('objectId'); + $hierarchy[$key]['properties']['typeId'] = $properties->getValue('typeId'); + $hierarchy[$key]['properties']['name'] = $properties->getValue('name'); + + // if we have found a child/parent with one or more children/parents, recurse into the child/parent object + if (count($entry['items']) > 0) + { + $hierarchy[$key][$linkText] = CMISUtil::decodeObjectHierarchy($entry['items'], $linkText); + } + // NOTE may need to set a null value here in case webservices don't like it unset + // so we'll set it just in case... + else + { + $hierarchy[$key][$linkText] = null; + } + } + + return $hierarchy; + } + + /** + * This function takes a class object and converts it to an array structure + * via var_export (which returns a useable PHP string for creating the object from array content) + * and regular expressions to extract the array definitions and structure without the class specific code + * + * NOTE this function is not reliable for objects which contain ktapi instances, as it appears there is a recursive reference + * TODO attempt to deal with recursive references? + * + * @param object $data + * @return array $array + */ + static function objectToArray($data) + { + $array = array(); + + $stringdata = var_export($data, true); + // clean up ", )" - NOTE this may not be necessary + $stringdata = preg_replace('/, *\r?\n? *\)/', ')', $stringdata); + + // NOTE is this while loop even needed? + while (preg_match('/\b[\w]*::__set_state\(/', $stringdata, $matches)) + { + $stringdata = preg_replace('/\b[\w]*::__set_state\(/', $matches[1], $stringdata); + } + + // remove end parentheses, should come in pairs to be reduced by 1 + $stringdata = '$array = ' . preg_replace('/\)\)/', ')', $stringdata) . ';'; + eval($stringdata); + + return $array; + } + +} + +?> diff --git a/tests/runtests.php b/tests/runtests.php index d625e6f..f000978 100644 --- a/tests/runtests.php +++ b/tests/runtests.php @@ -7,15 +7,18 @@ class UnitTests extends TestSuite { $this->TestSuite('Unit tests'); + // CMIS API + $this->addFile('ktcmis/testCmisApi.php'); + // KTAPI // Some of these tests will fail if Electronic Signatures are enabled for the API. // To fix, check the failing functions and add 'admin', 'admin' as username and password, // and where necessary send 'Testing API' as a reason - $this->addFile('api/testApi.php'); - $this->addFile('api/testAuto.php'); - $this->addFile('api/testSavedSearches.php'); - $this->addFile('api/testAcl.php'); - $this->addFile('api/testAuthentication.php'); +// $this->addFile('api/testApi.php'); +// $this->addFile('api/testAuto.php'); +// $this->addFile('api/testSavedSearches.php'); +// $this->addFile('api/testAcl.php'); +// $this->addFile('api/testAuthentication.php'); // the next two appear to not use the ktapi functions which require signatures, // e.g. the move function is called directly on the document ($document->move()) @@ -26,14 +29,14 @@ class UnitTests extends TestSuite { // $this->addFile('api/testDocument.php'); // $this->addFile('api/testFolder.php'); - $this->addFile('api/testBulkActions.php'); - $this->addFile('api/testCollection.php'); +// $this->addFile('api/testBulkActions.php'); +// $this->addFile('api/testCollection.php'); // While the original tests for esignatures have been set up to work // if Electronic Signatures are NOT enabled for the API, new tests may not // include the check which allows the tests to be bypassed when esignatures // are not on, so if you have failures, check there first :) - $this->addFile('api/testElectronicSignatures.php'); +// $this->addFile('api/testElectronicSignatures.php'); // $this->addFile('SQLFile/test_sqlfile.php'); // $this->addFile('cache/testCache.php'); diff --git a/webservice/classes/soap/config.php b/webservice/classes/soap/config.php index 6344a5a..e47de8d 100755 --- a/webservice/classes/soap/config.php +++ b/webservice/classes/soap/config.php @@ -1,23 +1,28 @@ - "contact", - "address" => "address", - -); - + "contact", + "address" => "address", + "cmisRepositoryEntryType" => "cmisRepositoryEntryType", + "cmisRepositoryInfoType" => "cmisRepositoryInfoType", + "cmisRepositoryCapabilitiesType" => "cmisRepositoryCapabilitiesType", + "cmisTypeDefinitionType" => "cmisTypeDefinitionType", + "cmisPropertyDefinitionType" => "cmisPropertyDefinitionType", + "cmisObjectType" => "cmisObjectType", + "cmisPropertiesType" => "cmisPropertiesType", +); + ?> \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISObjectPropertiesType.class.php b/webservice/classes/soap/model/CMISObjectPropertiesType.class.php new file mode 100644 index 0000000..86c6b33 --- /dev/null +++ b/webservice/classes/soap/model/CMISObjectPropertiesType.class.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISObjectType.class.php b/webservice/classes/soap/model/CMISObjectType.class.php new file mode 100644 index 0000000..929de87 --- /dev/null +++ b/webservice/classes/soap/model/CMISObjectType.class.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISPropertiesType.class.php b/webservice/classes/soap/model/CMISPropertiesType.class.php new file mode 100644 index 0000000..214daf2 --- /dev/null +++ b/webservice/classes/soap/model/CMISPropertiesType.class.php @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISProperty.class.php b/webservice/classes/soap/model/CMISProperty.class.php new file mode 100644 index 0000000..60836fe --- /dev/null +++ b/webservice/classes/soap/model/CMISProperty.class.php @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISPropertyCollectionType.class.php b/webservice/classes/soap/model/CMISPropertyCollectionType.class.php new file mode 100644 index 0000000..9e95a5c --- /dev/null +++ b/webservice/classes/soap/model/CMISPropertyCollectionType.class.php @@ -0,0 +1,36 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISPropertyDefinitionType.class.php b/webservice/classes/soap/model/CMISPropertyDefinitionType.class.php new file mode 100644 index 0000000..6abeb8a --- /dev/null +++ b/webservice/classes/soap/model/CMISPropertyDefinitionType.class.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISRepositoryCapabilitiesType.class.php b/webservice/classes/soap/model/CMISRepositoryCapabilitiesType.class.php new file mode 100644 index 0000000..26c926f --- /dev/null +++ b/webservice/classes/soap/model/CMISRepositoryCapabilitiesType.class.php @@ -0,0 +1,36 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISRepositoryEntryType.class.php b/webservice/classes/soap/model/CMISRepositoryEntryType.class.php new file mode 100644 index 0000000..be3fb65 --- /dev/null +++ b/webservice/classes/soap/model/CMISRepositoryEntryType.class.php @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISRepositoryInfoType.class.php b/webservice/classes/soap/model/CMISRepositoryInfoType.class.php new file mode 100644 index 0000000..e792d71 --- /dev/null +++ b/webservice/classes/soap/model/CMISRepositoryInfoType.class.php @@ -0,0 +1,42 @@ + \ No newline at end of file diff --git a/webservice/classes/soap/model/CMISService.class.php b/webservice/classes/soap/model/CMISService.class.php new file mode 100644 index 0000000..9bced2e --- /dev/null +++ b/webservice/classes/soap/model/CMISService.class.php @@ -0,0 +1,198 @@ + diff --git a/webservice/classes/soap/model/CMISTypeDefinitionType.class.php b/webservice/classes/soap/model/CMISTypeDefinitionType.class.php new file mode 100644 index 0000000..46fb3ef --- /dev/null +++ b/webservice/classes/soap/model/CMISTypeDefinitionType.class.php @@ -0,0 +1,50 @@ + \ No newline at end of file diff --git a/webservice/tests/webservice.php b/webservice/tests/webservice.php index e0cefbe..7110fac 100755 --- a/webservice/tests/webservice.php +++ b/webservice/tests/webservice.php @@ -1,17 +1,87 @@ -WSDL file: ".$wsdl."
\n"; - -$options = Array('actor' =>'http://www.knowledgetree.pr', - 'trace' => true); -$client = new SoapClient($wsdl,$options); - -echo "
Result from getContacts call:
"; - -$res = $client->getContacts(); -print_r($res); -echo "
Raw Soap response:
"; -echo htmlentities($client->__getLastResponse()); -echo "
SoapFault asking for an unknown contact:
"; -$client->newContact(); +WSDL file: ".$wsdl."
\n"; + +$options = Array('actor' =>'http://127.0.0.1', + 'trace' => true); +$client = new SoapClient($wsdl,$options); + + + +echo "
Result from getrepositories call:
"; +$res = $client->getRepositories(); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); + +echo "
Result from getrepositoryinfo call:
"; + +$res = $client->getRepositoryInfo('1'); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); + +echo "
Result from gettypes call:
"; + +$res = $client->getTypes('1'); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); + +echo "
Result from gettypedefinition (document) call:
"; + +$res = $client->getTypeDefinition('1', 'Document'); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); + +echo "
Result from gettypedefinition (folder) call:
"; + +$res = $client->getTypeDefinition('1', 'Folder'); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); + +/* + +echo "
Result from getdescendants call:
"; + +$res = $client->getDescendants('1', 'F1', false, false, 3); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); + +echo "
Result from getchildren call:
"; + +$res = $client->getChildren('1', 'F1', false, false); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); +// * +// */ + +/* +echo "
Result from getfolderparent call:
"; + +$res = $client->getFolderParent('1', 'F566', false, false, false); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); + +//echo "
Result from getobjectparents call:
"; +// +//$res = $client->getObjectParents('1', 'F566', false, false); +//print_r($res); +//echo "
Raw Soap response:
"; +//echo htmlentities($client->__getLastResponse()); + +echo "
Result from getobjectparents call:
"; + +$res = $client->getProperties('1', 'F566', false, false); +print_r($res); +echo "
Raw Soap response:
"; +echo htmlentities($client->__getLastResponse()); +*/ +// TODO add test of returnToRoot? would need known existing folder other than DroppedDocuments (F566) + ?> \ No newline at end of file -- libgit2 0.21.4