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