. * * 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 public 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 public function decodeObjectId($objectId, &$typeId = null) { if (!is_string($objectId)) { $typeId = 'Unknown'; return null; } $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 $objectId; } /** * 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 public 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($object['id'], $ktapi, $repositoryURI); break; case 'F': $CMISObject = new CMISFolderObject($object['id'], $ktapi, $repositoryURI); break; } $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 public 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($detail['id'], $ktapi, $repositoryURI); $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 public 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] = CMISUtil::createObjectPropertiesEntry($properties); } return $hierarchy; } static public function createObjectPropertiesEntry($properties) { $object = array(); // TODO additional properties to be returned $object['properties']['ObjectId'] = array('type' => $properties->getFieldType('ObjectId'), 'value' => $properties->getValue('ObjectId')); $object['properties']['BaseType'] = array('type' => $properties->getFieldType('BaseType'), 'value' => $properties->getValue('BaseType')); $object['properties']['ObjectTypeId'] = array('type' => $properties->getFieldType('ObjectTypeId'), 'value' => $properties->getValue('ObjectTypeId')); $object['properties']['Name'] = array('type' => $properties->getFieldType('Name'), 'value' => $properties->getValue('Name')); $object['Author'] = array('value' => $properties->getValue('Author')); $object['properties']['ParentId'] = array('type' => $properties->getFieldType('ParentId'), 'value' => CMISUtil::encodeObjectId('Folder', $properties->getValue('ParentId'))); // TODO should check for content stream data before filling these in if (strtolower($properties->getValue('ObjectTypeId')) == 'document') { $object['properties']['ContentStreamLength'] = array('type' => $properties->getFieldType('ContentStreamLength'), 'value' => $properties->getValue('ContentStreamLength')); $object['properties']['ContentStreamMimeType'] = array('type' => $properties->getFieldType('ContentStreamMimeType'), 'value' => $properties->getValue('ContentStreamMimeType')); } // if we have found a child/parent with one or more children/parents, recurse into the child/parent object if (count($entry['items']) > 0) { $object[$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 { $object[$linkText] = null; } return $object; } /** * 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 public 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; } /** * Converts a boolean value to string representation * If input is not true or false, return unaltered * * @param boolean/other $input * @return string */ static public function boolToString($input) { return (($input === true) ? 'true' : (($input === false) ? 'false' : $input)); } /** * Creates a temporary file * Cleanup is the responsibility of the calling code * * @param string|binary $content The content to be written to the file. * @param string $uploadDir Optional upload directory. Will use the KnowledgeTree system tmp directory if not supplied. * @return string The path to the created file (for reference and cleanup.) */ static public function createTemporaryFile($content, $encoding = null, $uploadDir = null) { if(is_null($uploadDir)) { $oKTConfig =& KTConfig::getSingleton(); $uploadDir = $oKTConfig->get('webservice/uploadDirectory'); } $temp = tempnam($uploadDir, 'myfile'); $fp = fopen($temp, 'wb'); fwrite($fp, ($encoding == 'base64' ? base64_decode($content) : $content)); fclose($fp); return $temp; } } ?>